# coding: utf-8 $:.unshift "." require File.join(File.dirname(__FILE__), 'spec_helper') require 'rdf/spec/reader' # w3c test suite: http://www.w3.org/TR/rdf-testcases/ describe "RDF::RDFXML::Reader" do before :each do @reader = RDF::RDFXML::Reader end it_should_behave_like RDF_Reader context "discovery" do { "rdf" => RDF::Reader.for(:rdf), "rdfxml" => RDF::Reader.for(:rdfxml), "etc/foaf.xml" => RDF::Reader.for("etc/foaf.xml"), "etc/foaf.rdf" => RDF::Reader.for("etc/foaf.rdf"), "foaf.xml" => RDF::Reader.for(:file_name => "foaf.xml"), "foaf.rdf" => RDF::Reader.for(:file_name => "foaf.rdf"), ".xml" => RDF::Reader.for(:file_extension => "xml"), ".rdf" => RDF::Reader.for(:file_extension => "rdf"), "application/xml" => RDF::Reader.for(:content_type => "application/xml"), "application/rdf+xml" => RDF::Reader.for(:content_type => "application/rdf+xml"), }.each_pair do |label, format| it "should discover '#{label}'" do format.should == @reader end end end context :interface do before(:each) do @sampledoc = <<-EOF; Foo Bar EOF end it "should yield reader" do inner = mock("inner") inner.should_receive(:called).with(@reader) @reader.new(@sampledoc) do |reader| inner.called(reader.class) end end it "should return reader" do @reader.new(@sampledoc).should be_a(@reader) end it "should yield statements" do inner = mock("inner") inner.should_receive(:called).with(RDF::Statement).twice @reader.new(@sampledoc).each_statement do |statement| inner.called(statement.class) end end it "should yield triples" do inner = mock("inner") inner.should_receive(:called).with(RDF::URI, RDF::URI, RDF::Literal).twice @reader.new(@sampledoc).each_triple do |subject, predicate, object| inner.called(subject.class, predicate.class, object.class) end end end context "simple parsing" do it "should recognise and create single triple for empty non-RDF root" do sampledoc = %( ) graph = parse(sampledoc, :base_uri => "http://example.com", :validate => true) graph.size.should == 1 statement = graph.statements.first statement.subject.class.should == RDF::Node statement.predicate.should == RDF.type statement.object.should == RDF::XML.NotRDF end it "should parse on XML documents with multiple RDF nodes" do sampledoc = <<-EOF; Foo Bar EOF graph = parse(sampledoc, :base_uri => "http://example.com", :validate => true) objects = graph.statements.map {|s| s.object.value}.sort objects.should == ["Bar", "Foo"] end it "should be able to parse a simple single-triple document" do sampledoc = <<-EOF; foo Tom Rob Mary EOF graph = parse(sampledoc, :base_uri => "http://example.com", :validate => true) #puts @debug graph.size.should == 10 # print graph.to_ntriples # TODO: add datatype parsing # TODO: make sure the BNode forging is done correctly - an internal element->nodeID mapping # TODO: proper test end it "should be able to handle Bags/Alts etc." do sampledoc = <<-EOF; EOF graph = parse(sampledoc, :base_uri => "http://example.com", :validate => true) graph.predicates.map(&:to_s).should include("http://www.w3.org/1999/02/22-rdf-syntax-ns#_1", "http://www.w3.org/1999/02/22-rdf-syntax-ns#_2") end end context :exceptions do it "should raise an error if rdf:aboutEach is used, as per the negative parser test rdfms-abouteach-error001 (rdf:aboutEach attribute)" do sampledoc = <<-EOF; me EOF lambda do graph = parse(sampledoc, :base_uri => "http://example.com", :validate => true) end.should raise_error(RDF::ReaderError, /Obsolete attribute .*aboutEach/) end it "should raise an error if rdf:aboutEachPrefix is used, as per the negative parser test rdfms-abouteach-error002 (rdf:aboutEachPrefix attribute)" do sampledoc = <<-EOF; foo me EOF lambda do graph = parse(sampledoc, :base_uri => "http://example.com", :validate => true) end.should raise_error(RDF::ReaderError, /Obsolete attribute .*aboutEachPrefix/) end it "should fail if given a non-ID as an ID (as per rdfcore-rdfms-rdf-id-error001)" do sampledoc = <<-EOF; EOF lambda do graph = parse(sampledoc, :base_uri => "http://example.com", :validate => true) end.should raise_error(RDF::ReaderError, /ID addtribute '.*' must be a NCName/) end it "should make sure that the value of rdf:ID attributes match the XML Name production (child-element version)" do sampledoc = <<-EOF; EOF lambda do graph = parse(sampledoc, :base_uri => "http://example.com", :validate => true) end.should raise_error(RDF::ReaderError, /ID addtribute '.*' must be a NCName/) end it "should make sure that the value of rdf:ID attributes match the XML Name production (data attribute version)" do sampledoc = <<-EOF; EOF lambda do graph = parse(sampledoc, :base_uri => "http://example.com", :validate => true) end.should raise_error(RDF::ReaderError, "ID addtribute 'a/b' must be a NCName") end it "should detect bad bagIDs" do sampledoc = <<-EOF; EOF lambda do graph = parse(sampledoc, :base_uri => "http://example.com", :validate => true) puts @debug end.should raise_error(RDF::ReaderError, /Obsolete attribute .*bagID/) end end context :reification do it "should be able to reify according to ยง2.17 of RDF/XML Syntax Specification" do sampledoc = <<-EOF; blah EOF triples = <<-EOF \"blah\" . . . . \"blah\" . EOF graph = parse(sampledoc, :base_uri => "http://example.com", :validate => true) graph.should be_equivalent_graph(triples, :about => "http://example.com/", :trace => @debug) end end # W3C Test suite from http://www.w3.org/2000/10/rdf-tests/rdfcore/ describe "w3c rdfcore tests" do require 'rdf_test' # Positive parser tests should raise errors. describe "positive parser tests" do Fixtures::TestCase::PositiveParserTest.each do |t| next unless t.status == "APPROVED" #next unless t.about =~ /rdfms-rdf-names-use/ #next unless t.name =~ /11/ #puts t.inspect specify "#{t.name}: " + (t.description || "#{t.inputDocument} against #{t.outputDocument}") do begin t.run_test do t.debug = [] g = RDF::Graph.new @reader.new(t.input, :base_uri => t.inputDocument, :validate => false, :debug => t.debug).each do |statement| g << statement end g end rescue RSpec::Expectations::ExpectationNotMetError => e if t.inputDocument =~ %r(xml-literal|xml-canon) pending("XMLLiteral canonicalization not implemented yet") else raise end end end end end # Negative parser tests should raise errors. describe "negative parser tests" do Fixtures::TestCase::NegativeParserTest.each do |t| next unless t.status == "APPROVED" #next unless t.about =~ /rdfms-empty-property-elements/ #next unless t.name =~ /1/ #puts t.inspect specify "test #{t.name}: " + (t.description || t.inputDocument) do t.run_test do lambda do g = RDF::Graph.new @reader.new(t.input, :base_uri => t.inputDocument, :validate => true).each do |statement| g << statement end g.should be_empty end.should raise_error(RDF::ReaderError) end end end end end def parse(input, options) @debug = [] graph = RDF::Graph.new @reader.new(input, options.merge(:debug => @debug)).each do |statement| graph << statement end graph end end