module Matchers class BeEquivalentGraph Info = Struct.new(:about, :information, :trace, :compare, :inputDocument, :outputDocument) def normalize(graph) case @info.compare when :array array = case graph when Graph, Parser graph = graph.graph if graph.respond_to?(:graph) anon = "a" anon_ctx = {} graph.triples.collect {|triple| triple.to_ntriples }.each do |t| t.gsub(/_:nbn\d+[a-z]+N/, "_:"). gsub!(/_:bn\d+[a-z]+/) do |bn| # Normalize anon BNodes if anon_ctx[bn] anon_ctx[bn] else anon_ctx[bn] = anon anon = anon.succ end "_:#{anon_ctx[bn]}" end end.sort when Array graph.sort else graph.to_s.split("\n"). map {|t| t.gsub(/^\s*(.*)\s*$/, '\1')}. reject {|t2| t2.match(/^\s*$/)}. compact. sort. uniq end # Implement to_ntriples on array, to simplify logic later def array.to_ntriples; self.join("\n") + "\n"; end array else case graph when Graph then graph when Parser then graph.graph when IO, StringIO Parser.parse(graph, @info.about) else parser = Parser.new(:struct => true) fmt = parser.detect_format(graph.to_s) parser.parse(graph.to_s, @info.about, :type => fmt) end end end def initialize(expected, info) @info = if info.respond_to?(:about) info elsif info.is_a?(Hash) identifier = info[:identifier] || expected.is_a?(Graph) ? expected.identifier : info[:about] Info.new(identifier, info[:information] || "", info[:trace], info[:compare]) else Info.new(expected.is_a?(Graph) ? expected.identifier : info, info.to_s) end @expected = normalize(expected) end def matches?(actual) @actual = normalize(actual) @actual == @expected end def failure_message_for_should info = @info.respond_to?(:information) ? @info.information : "" if @expected.is_a?(Graph) && @actual.size != @expected.size "Graph entry count differs:\nexpected: #{@expected.size}\nactual: #{@actual.size}" elsif @expected.is_a?(Array) && @actual.size != @expected.length "Graph entry count differs:\nexpected: #{@expected.length}\nactual: #{@actual.size}" elsif @expected.is_a?(Graph) && @actual.identifier != @expected.identifier "Graph identifiers differ:\nexpected: #{@expected.identifier}\nactual: #{@actual.identifier}" else "Graph differs#{@info.compare == :array ? '(array)' : ''}\n" end + "\n#{info + "\n" unless info.empty?}" + (@info.inputDocument ? "Input file: #{@info.inputDocument}\n" : "") + (@info.outputDocument ? "Output file: #{@info.outputDocument}\n" : "") + "Unsorted Expected:\n#{@expected.to_ntriples}" + "Unsorted Results:\n#{@actual.to_ntriples}" + (@info.trace ? "\nDebug:\n#{@info.trace}" : "") end def negative_failure_message "Graphs do not differ\n" end end def be_equivalent_graph(expected, info = nil) BeEquivalentGraph.new(expected, info) end # Run expected SPARQL query against actual if $redland_enabled class PassQuery def initialize(expected, info) @expected = expected @query = Redland::Query.new(expected) @info = info end def matches?(actual) @actual = actual @expected_results = @info.respond_to?(:expectedResults) ? @info.expectedResults : true model = Redland::Model.new ntriples_parser = Redland::Parser.ntriples ntriples_parser.parse_string_into_model(model, actual.to_ntriples, "http://www.w3.org/2006/07/SWD/RDFa/testsuite/xhtml1-testcases/") @results = @query.execute(model) #puts "Redland query results: #{@results.inspect}" if @expected_results && @results @results.is_boolean? && @results.get_boolean? else @results.nil? || @results.is_boolean? && !@results.get_boolean? end end def failure_message_for_should info = @info.respond_to?(:information) ? @info.information : "" "#{info + "\n" unless info.empty?}" + if @results.nil? "Query failed to return results" elsif !@results.is_boolean? "Query returned non-boolean results" elsif @expected_results "Query returned false" else "Query returned true (expected false)" end + "\n#{@expected}" + "\n#{@info.input}" + "\nResults:\n#{@actual.to_ntriples}" + "\nDebug:\n#{@info.trace}" end end def pass_query(expected, info = "") PassQuery.new(expected, info) end else def pass_query(expect, info = ""); false; end end class BeValidXML def initialize(info) @info = info end def matches?(actual) @actual = actual @doc = Nokogiri::XML.parse(actual) @results = @doc.validate @results.nil? rescue false end def failure_message_for_should "#{@info + "\n" unless @info.empty?}" + if @doc.nil? "did not parse" else "\n#{@results}" + "\nParsed:\n#{@doc}" end + "\nActual:\n#{@actual}" end end def be_valid_xml(info = "") BeValidXML.new(info) end class BeEquivalentXML def initialize(expected, info) @expected = expected @info = info end def matches?(actual) @actual = actual a = @actual.index("<") == 0 ? @actual : "#{@actual}" e = @expected.index("<") == 0 ? @expected : "#{@expected}" a_hash = ActiveSupport::XmlMini.parse(a) e_hash = ActiveSupport::XmlMini.parse(e) a_hash == e_hash rescue puts $! @fault = $!.message false end def failure_message_for_should "#{@info + "\n" unless @info.empty?}" + "Fault: #{@fault + "\n" if @fault}" + "Expected:#{@expected}\n" + "Actual:#{@actual}" end end def be_equivalent_xml(expected, info = "") BeEquivalentXML.new(expected, info) end end