From 649ac0b90eedb21df0232ca5d0705e006dec511c Mon Sep 17 00:00:00 2001 From: Matthias Kramm Date: Tue, 11 Aug 2009 12:22:52 +0200 Subject: [PATCH] implemented bitmap checks in test framwork --- spec/spec_helper.rb | 93 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 19aaec3..78a25b3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,6 @@ require 'spec' +require 'rubygems' +require 'RMagick' class WrongColor < Exception def initialize(pixel) @@ -24,58 +26,103 @@ class PixelError < Exception "Pixel #{@p1} #{@relation} #{@p2}" end end +class ConversionFailed < Exception + def initialize(output,file) + @output = output + @file = file + @exists = File.exists?(file) + end + def to_s + puts "-"*26+" Conversion failed "+"-"*27 + (puts @output) if @output + puts "file #{@file} doesn't exist" if not @exists + puts "-"*72 + end +end class Area - def initialize(x1,y1,x2,y2) + def initialize(x1,y1,x2,y2,data) @x1,@y1,@x2,@y2 = x1,y1,x2,y2 + @rgb = Array.new(data.size/3) do |i| data.slice(i*3,3) end end def should_be_plain_colored - raise AreaError.new(self,"is not plain colored") + @rgb.minmax == [@rgb[0],@rgb[0]] or raise AreaError.new(self,"is not plain colored") end def should_not_be_plain_colored - raise AreaError.new(self,"is plain colored") + @rgb.minmax != [@rgb[0],@rgb[0]] or raise AreaError.new(self,"is plain colored") end def to_s "(#{@x1},#{@y1},#{@x2},#{@y2})" end end + +def rgb_to_int(rgb) + # ImageMagick rgb triples are 16 bit + (rgb.reverse+[0]).map {|c| c>>8}.pack("CCCC").unpack("i")[0] +end + class Pixel - def initialize(x,y) - @x = x - @y = y + attr :rgb + def initialize(x,y,rgb) + @x,@y,@rgb = x,y,rgb end - def should_be_of_color(color) - raise WrongColor.new(self) + def should_be_of_color(color2) + color1 = rgb_to_int(@rgb) + color1 == color2 or raise WrongColor.new(self) end def should_be_brighter_than(pixel) - raise PixelError.new(self,"is not brighter than",pixel) + gray1 = @rgb.inject(0) {|sum,e| sum+e} + gray2 = pixel.rgb.inject(0) {|sum,e| sum+e} + gray1 > gray2 or raise PixelError.new(self,"is not brighter than",pixel) end def should_be_less_bright_than(pixel) - raise PixelError.new(self,"is brighter than",pixel) + gray1 = @rgb.inject(0) {|sum,e| sum+e} + gray2 = pixel.rgb.inject(0) {|sum,e| sum+e} + gray1 < gray2 or raise PixelError.new(self,"is not less bright than",pixel) end def should_be_the_same_as(pixel) - raise PixelError.new(self,"is not the same as",pixel) + @rgb == pixel.rgb or raise PixelError.new(self,"is not the same as",pixel) end def to_s "(#{@x},#{@y})" end end class DocFile - def initialize(filename, options) + def initialize(filename, page) @filename = filename - @page = (options[:page] or 1) + @page = page + end + def load() + @swfname = @filename.gsub(/.pdf$/i,"")+".swf" + @pngname = @filename.gsub(/.pdf$/i,"")+".png" + begin + output = `pdf2swf --flatten -p #{@page} #{@filename} -o #{@swfname} 2>&1` + raise ConversionFailed.new(output,@swfname) unless File.exists?(@swfname) + output = `swfrender --legacy #{@swfname} -o #{@pngname} 2>&1` + raise ConversionFailed.new(output,@pngname) unless File.exists?(@pngname) + @img = Magick::Image.read(@pngname).first + ensure + `rm -f #{@swfname}` + `rm -f #{@pngname}` + end end def area_at(x1,y1,x2,y2) - return Area.new(x1,y1,x2,y2) + self.load() + data = @img.export_pixels(x1, y1, x2-x1, y2-y1, "RGB") + return Area.new(x1,y1,x2,y2,data) end - def width - return 300 + def width() + self.load() + return @img.columns end - def height - return 200 + def height() + self.load() + return @img.rows end def pixel_at(x,y) - return Pixel.new(x,y) + self.load() + data = @img.export_pixels(x, y, 1, 1, "RGB") + return Pixel.new(x,y,data) end end @@ -95,10 +142,16 @@ module Spec @file.pixel_at(x,y) end def initialize(proxy,&impl) + + # overriding the initialize() function saves us from having to + # set up the document in the test. The bad news, however, is that + # we have to be very careful not to raise exceptions here- + # rspec would miss those. + @_proxy = proxy @_implementation = impl @_backtrace = caller - @file = DocFile.new(proxy.description, proxy.options) + @file = DocFile.new(proxy.description, (proxy.options[:page] or 1)) end end module ExampleGroupMethods -- 1.7.10.4