# coding: utf-8 require File.join(File.dirname(__FILE__), 'spec_helper') describe "RDF::N3::Reader" do context "discovery" do { "n3" => RDF::Reader.for(:n3), "etc/foaf.n3" => RDF::Reader.for("etc/foaf.n3"), "etc/foaf.ttl" => RDF::Reader.for("etc/foaf.ttl"), "foaf.n3" => RDF::Reader.for(:file_name => "foaf.n3"), "foaf.ttl" => RDF::Reader.for(:file_name => "foaf.ttl"), ".n3" => RDF::Reader.for(:file_extension => "n3"), ".ttl" => RDF::Reader.for(:file_extension => "ttl"), "text/n3" => RDF::Reader.for(:content_type => "text/n3"), "text/turtle" => RDF::Reader.for(:content_type => "text/turtle"), }.each_pair do |label, format| it "should discover '#{label}'" do format.should == RDF::N3::Reader end end end context :interface do before(:each) do @sampledoc = <<-EOF; @prefix dc: . @prefix po: . @prefix rdf: . _:broadcast a po:Broadcast; po:schedule_date """2008-06-24T12:00:00Z"""; po:broadcast_of _:version; po:broadcast_on ; . _:version a po:Version; . dc:title """Nemone"""; a po:Brand; . a po:Episode; po:episode ; po:version _:version; po:long_synopsis """Actor and comedian Rhys Darby chats to Nemone."""; dc:title """Nemone"""; po:synopsis """Actor and comedian Rhys Darby chats to Nemone."""; . a po:Service; dc:title """BBC 6 Music"""; . #_:abcd a po:Episode. EOF end it "should yield reader" do inner = mock("inner") inner.should_receive(:called).with(RDF::N3::Reader) RDF::N3::Reader.new(@sampledoc) do |reader| inner.called(reader.class) end end it "should return reader" do RDF::N3::Reader.new(@sampledoc).should be_a(RDF::N3::Reader) end it "should yield statements" do inner = mock("inner") inner.should_receive(:called).with(RDF::Statement).exactly(15) RDF::N3::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).exactly(15) RDF::N3::Reader.new(@sampledoc).each_triple do |subject, predicate, object| inner.called(subject.class, predicate.class, object.class) end end end describe "with simple ntriples" do context "simple triple" do before(:each) do n3_string = %( "Gregg Kellogg" .) @graph = parse(n3_string) @statement = @graph.statements.first end it "should have a single triple" do @graph.size.should == 1 end it "should have subject" do @statement.subject.to_s.should == "http://example.org/" end it "should have predicate" do @statement.predicate.to_s.should == "http://xmlns.com/foaf/0.1/name" end it "should have object" do @statement.object.to_s.should == '"Gregg Kellogg"' end end # NTriple tests from http://www.w3.org/2000/10/rdf-tests/rdfcore/ntriples/test.nt describe "with blank lines" do { "comment" => "# comment lines", "comment after whitespace" => " # comment after whitespace", "empty line" => "", "line with spaces" => " " }.each_pair do |name, statement| specify "test #{name}" do parse(statement).size.should == 0 end end end describe "with literal encodings" do { 'Dürst' => ':a :b "D\u00FCrst" .', 'simple literal' => ':a :b "simple literal" .', 'backslash:\\' => ':a :b "backslash:\\\\" .', 'dquote:"' => ':a :b "dquote:\"" .', "newline:\n" => ':a :b "newline:\n" .', "return\r" => ':a :b "return\r" .', "tab:\t" => ':a :b "tab:\t" .', "é" => ':a :b "\u00E9" .', "€" => ':a :b "\u20AC" .', }.each_pair do |contents, triple| specify "test #{contents}" do graph = parse(triple, :base_uri => "http://a/b") statement = graph.statements.first graph.size.should == 1 statement.object.value.should == contents end end it "should parse long literal with escape" do n3 = %(@prefix : . :a :b "\\U00015678another" .) if defined?(::Encoding) statement = parse(n3).statements.first statement.object.value.should == "\u{15678}another" else lambda { parse(n3) }.should raise_error(RDF::ReaderError, "Long Unicode escapes no supported in Ruby 1.8") pending("Not supported in Ruby 1.8") end end it "should parse multi-line literal" do graph = parse(%( """ Foo barhere baz more """ . )) graph.size.should == 1 graph.statements.first.object.value.should == %( Foo barhere baz more ) end it "should parse long literal ending in double quote" do graph = parse(%(:a :b """ \\"""" .), :base_uri => "http://a/b") graph.size.should == 1 graph.statements.first.object.value.should == ' "' end end it "should create named subject bnode" do graph = parse("_:anon .") graph.size.should == 1 statement = graph.statements.first statement.subject.should be_a(RDF::Node) statement.subject.id.should =~ /anon/ statement.predicate.to_s.should == "http://example.org/property" statement.object.to_s.should == "http://example.org/resource2" end it "should create named predicate bnode" do graph = parse(" _:anon .") graph.size.should == 1 statement = graph.statements.first statement.subject.to_s.should == "http://example.org/resource2" statement.predicate.should be_a(RDF::Node) statement.predicate.id.should =~ /anon/ statement.object.to_s.should == "http://example.org/object" end it "should create named object bnode" do graph = parse(" _:anon .") graph.size.should == 1 statement = graph.statements.first statement.subject.to_s.should == "http://example.org/resource2" statement.predicate.to_s.should == "http://example.org/property" statement.object.should be_a(RDF::Node) statement.object.id.should =~ /anon/ end { "three uris" => " .", "spaces and tabs throughout" => " . ", "line ending with CR NL" => " .\r\n", "literal escapes (1)" => ' "simple literal" .', "literal escapes (2)" => ' "backslash:\\\\" .', "literal escapes (3)" => ' "dquote:\"" .', "literal escapes (4)" => ' "newline:\n" .', "literal escapes (5)" => ' "return:\r" .', "literal escapes (6)" => ' "tab:\t" .', "Space is optional before final . (1)" => [' .', ' .'], "Space is optional before final . (2)" => [' "x".', ' "x" .'], "XML Literals as Datatyped Literals (1)" => ' ""^^ .', "XML Literals as Datatyped Literals (2)" => ' " "^^ .', "XML Literals as Datatyped Literals (3)" => ' "x"^^ .', "XML Literals as Datatyped Literals (4)" => ' "\""^^ .', "XML Literals as Datatyped Literals (5)" => ' ""^^ .', "XML Literals as Datatyped Literals (6)" => ' "a "^^ .', "XML Literals as Datatyped Literals (7)" => ' "a c"^^ .', "XML Literals as Datatyped Literals (8)" => ' "a\n\nc"^^ .', "XML Literals as Datatyped Literals (9)" => ' "chat"^^ .', "Plain literals with languages (1)" => ' "chat"@fr .', "Plain literals with languages (2)" => ' "chat"@en .', "Typed Literals" => ' "abc"^^ .', }.each_pair do |name, statement| specify "test #{name}" do graph = parse([statement].flatten.first) graph.size.should == 1 graph.to_ntriples.chomp.should == [statement].flatten.last.gsub(/\s+/, " ").strip end end it "should create typed literals" do n3doc = " \"Joe\"^^ ." statement = parse(n3doc).statements.first statement.object.class.should == RDF::Literal end it "should create BNodes" do n3doc = "_:a a _:c ." statement = parse(n3doc).statements.first statement.subject.class.should == RDF::Node statement.object.class.should == RDF::Node end describe "should create URIs" do { %( .) => %( .), %( .) => %( .), %(:joe :knows :jane .) => %( .), %(<#D%C3%BCrst> a "URI percent ^encoded as C3, BC".) => %( "URI percent ^encoded as C3, BC" .), }.each_pair do |n3, nt| it "for '#{n3}'" do parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end end { %(<#Dürst> a "URI straight in UTF8".) => %( "URI straight in UTF8" .), %(:a :related :\u3072\u3089\u304C\u306A.) => %( .), }.each_pair do |n3, nt| it "for '#{n3}'" do begin parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) rescue if defined?(::Encoding) raise else pending("Unicode URIs not supported in Ruby 1.8") { raise } end end end end end it "should create URIRefs" do n3doc = " ." statement = parse(n3doc).statements.first statement.subject.class.should == RDF::URI statement.object.class.should == RDF::URI end it "should create literals" do n3doc = " \"Joe\"." statement = parse(n3doc).statements.first statement.object.class.should == RDF::Literal end end describe "with illegal syntax" do { %(:y :p1 "xyz"^^xsd:integer .) => %r(Typed literal has an invalid lexical value: .* "xyz"), %(:y :p1 "12xyz"^^xsd:integer .) => %r(Typed literal has an invalid lexical value: .* "12xyz"), %(:y :p1 "xy.z"^^xsd:double .) => %r(Typed literal has an invalid lexical value: .* "xy\.z"), %(:y :p1 "+1.0z"^^xsd:double .) => %r(Typed literal has an invalid lexical value: .* "\+1.0z"), %(:a :b .) => %r(Illegal statment: ".*" missing object), %(:a :b 'single quote' .) => RDF::ReaderError, %(:a "literal value" :b .) => RDF::ReaderError, %(@keywords prefix. :e prefix :f .) => %r(Keyword ".*" used as expression) }.each_pair do |n3, error| it "should raise error for '#{n3}'" do lambda { parse("@prefix xsd: . #{n3}", :base_uri => "http://a/b") }.should raise_error(error) end end end describe "with n3 grammer" do describe "syntactic expressions" do it "should create typed literals with qname" do n3doc = %( @prefix rdf: @prefix foaf: @prefix xsd: foaf:name \"Joe\"^^xsd:string . ) statement = parse(n3doc).statements.first statement.object.class.should == RDF::Literal end it "should use <> as a prefix and as a triple node" do n3 = %(@prefix : <> . <> a :a.) nt = %( . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should use <#> as a prefix and as a triple node" do n3 = %(@prefix : <#> . <#> a :a.) nt = %( . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should generate rdf:type for 'a'" do n3 = %(@prefix a: . a:b a .) nt = %( .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should generate rdf:type for '@a'" do n3 = %(@prefix a: . a:b @a .) nt = %( .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should generate inverse predicate for 'is xxx of'" do n3 = %("value" is :prop of :b . :b :prop "value" .) nt = %( "value" .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should generate inverse predicate for '@is xxx @of'" do n3 = %("value" @is :prop @of :b . :b :prop "value" .) nt = %( "value" .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should generate inverse predicate for 'is xxx of' with object list" do n3 = %("value" is :prop of :b, :c . ) nt = %( "value" . "value" . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should generate predicate for 'has xxx'" do n3 = %(@prefix a: . a:b has :pred a:c .) nt = %( .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should generate predicate for '@has xxx'" do n3 = %(@prefix a: . a:b @has :pred a:c .) nt = %( .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should create log:implies predicate for '=>'" do n3 = %(@prefix a: . _:a => a:something .) nt = %(_:a .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should create log:implies inverse predicate for '<='" do n3 = %(@prefix a: . _:a <= a:something .) nt = %( _:a .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should create owl:sameAs predicate for '='" do n3 = %(@prefix a: . _:a = a:something .) nt = %(_:a .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end { %(:a :b @true) => %( "true"^^ .), %(:a :b @false) => %( "false"^^ .), %(:a :b 1) => %( "1"^^ .), %(:a :b -1) => %( "-1"^^ .), %(:a :b +1) => %( "+1"^^ .), %(:a :b 1.0) => %( "1.0"^^ .), %(:a :b 1.0e1) => %( "1.0e1"^^ .), %(:a :b 1.0e-1) => %( "1.0e-1"^^ .), %(:a :b 1.0e+1) => %( "1.0e+1"^^ .), }.each_pair do |n3, nt| it "should create typed literal for '#{n3}'" do parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end end it "should accept empty localname" do n3 = %(: : : .) nt = %( .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should accept prefix with empty local name" do n3 = %(@prefix foo: . foo: foo: foo: .) nt = %( .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should do something for @forAll" it "should do something for @forSome" end describe "namespaces" do it "should set absolute base" do n3 = %(@base . <> :a . <#c> :d .) nt = %( . . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should set absolute base (trailing /)" do n3 = %(@base . <> :a . <#c> :d .) nt = %( . . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should set absolute base (trailing #)" do n3 = %(@base . <> :a . <#c> :d .) nt = %( . . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should set relative base" do n3 = %( @base . <> :a , <#c>. @base . <> :a , <#c>. @base <../>. <> :a , <#e>. ) nt = %( . . . . . . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end end describe "keywords" do [ %(prefix :<>.), %(base <>.), %(keywords a.), %(:a is :b of :c.), %(:a @is :b of :c.), %(:a is :b @of :c.), %(:a has :b :c.), ].each do |n3| it "should require @ if keywords set to empty for '#{n3}'" do lambda do parse("@keywords . #{n3}", :base_uri => "http://a/b") end.should raise_error(/unqualified keyword '\w+' used without @keyword directive/) end end { %(:a a :b) => %( .), %(:a :b true) => %( .), %(:a :b false) => %( .), %(c :a :t) => %( .), %(:c a :t) => %( .), %(:c :a t) => %( .), }.each_pair do |n3, nt| it "should use default_ns for '#{n3}'" do parse("@keywords . #{n3}", :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end end { %(@keywords true. :a :b true.) => %( "true"^^ .), %(@keywords false. :a :b false.) => %( "false"^^ .), %(@keywords a. :a a :b.) => %( .), %(@keywords is. :a is :b @of :c.) => %( .), %(@keywords of. :a @is :b of :c.) => %( .), %(@keywords has. :a has :b :c.) => %( .), } .each_pair do |n3, nt| it "should use keyword for '#{n3}'" do parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end end it "should raise error if unknown keyword set" do n3 = %(@keywords foo.) lambda do parse(n3, :base_uri => "http://a/b") end.should raise_error(RDF::ReaderError, "undefined keywords used: foo") end end describe "declaration ordering" do it "should process _ namespace binding after an initial use as a BNode" do n3 = %( _:a a :p. @prefix _: . _:a a :p. ) nt = %( . _:a . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should allow a prefix to be redefined" do n3 = %( @prefix a: . a:b a:p a:v . @prefix a: . a:b a:p a:v . ) nt = %( . . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should process sequential @base declarations (swap base.n3)" do n3 = %( @base . :b . @base . :b2 . @prefix : <#>. :b3 . ) nt = %( . . . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end end describe "BNodes" do it "should create BNode for identifier with '_' prefix" do n3 = %(@prefix a: . _:a a:p a:v .) nt = %(_:bnode0 .) end it "should create BNode for [] as subject" do n3 = %(@prefix a: . [] a:p a:v .) nt = %(_:bnode0 .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should create BNode for [] as predicate" do n3 = %(@prefix a: . a:s [] a:o .) nt = %( _:bnode0 .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should create BNode for [] as object" do n3 = %(@prefix a: . a:s a:p [] .) nt = %( _:bnode0 .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should create BNode for [] as statement" do n3 = %([:a :b] .) nt = %(_:bnode0 .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should create statements with BNode subjects using [ pref obj]" do n3 = %(@prefix a: . [ a:p a:v ] .) nt = %(_:bnode0 .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should create BNode as a single object" do n3 = %(@prefix a: . a:b a:oneRef [ a:pp "1" ; a:qq "2" ] .) nt = %( _:bnode0 "1" . _:bnode0 "2" . _:bnode0 . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should create a shared BNode" do n3 = %( @prefix a: . a:b1 a:twoRef _:a . a:b2 a:twoRef _:a . _:a :pred [ a:pp "1" ; a:qq "2" ]. ) nt = %( _:a . _:a . _:bnode0 "1" . _:bnode0 "2" . _:a :pred _:bnode0 . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should create nested BNodes" do n3 = %( @prefix a: . a:a a:p [ a:p2 [ a:p3 "v1" , "v2" ; a:p4 "v3" ] ; a:p5 "v4" ] . ) nt = %( _:bnode0 "v1" . _:bnode0 "v2" . _:bnode0 "v3" . _:bnode1 _:bnode0 . _:bnode1 "v4" . _:bnode1 . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end describe "from paths" do it "should create bnode for path x.p" do n3 = %(:x2.:y2 :p2 "3" .) nt = %(:x2 :y2 _:bnode0 . _:bnode0 :p2 "3" .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should create bnode for path x!p" do n3 = %(:x2!:y2 :p2 "3" .) nt = %(:x2 :y2 _:bnode0 . _:bnode0 :p2 "3" .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should create bnode for path x^p" do n3 = %(:x2^:y2 :p2 "3" .) nt = %(_:bnode0 :y2 :x2 . _:bnode0 :p2 "3" .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should decode :joe!fam:mother!loc:office!loc:zip as Joe's mother's office's zipcode" do n3 = %( @prefix fam: . @prefix loc: . :joe!fam:mother!loc:office!loc:zip . ) nt = %( :joe _:bnode0 . _:bnode0 _:bnode1 . _:bnode1 _:bnode2 . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should decode :joe!fam:mother^fam:mother Anyone whose mother is Joe's mother." do n3 = %( @prefix fam: . @prefix loc: . :joe!fam:mother^fam:mother . ) nt = %( :joe _:bnode0 . _:bnode1 _:bnode0 . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should decode path with property list." do n3 = %( @prefix a: . :a2.a:b2.a:c2 :q1 "3" ; :q2 "4" , "5" . ) nt = %( :a2 _:bnode0 . _:bnode0 _:bnode1 . _:bnode1 :q1 "3" . _:bnode1 :q2 "4" . _:bnode1 :q2 "5" . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should decode path as object(1)" do n3 = %(:a :b "lit"^:c.) nt = %( :a :b _:bnode . _:bnode :c "lit" . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should decode path as object(2)" do n3 = %(@prefix a: . :r :p :o.a:p1.a:p2 .) nt = %( :o _:bnode0 . _:bnode0 _:bnode1 . :r :p _:bnode1 . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end end end describe "formulae" do it "should require that graph be formula_aware when encountering a formlua" it "should separate triples between specified and quoted graphs" end describe "object lists" do it "should create 2 statements for simple list" do n3 = %(:a :b :c, :d) nt = %( . .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end end describe "property lists" do it "should parse property list" do n3 = %( @prefix a: . a:b a:p1 "123" ; a:p1 "456" . a:b a:p2 a:v1 ; a:p3 a:v2 . ) nt = %( "123" . "456" . . . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end end describe "lists" do it "should parse empty list" do n3 = %(@prefix :. :empty :set ().) nt = %( .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should parse list with single element" do n3 = %(@prefix :. :gregg :wrote ("RdfContext").) nt = %( _:bnode0 "RdfContext" . _:bnode0 . _:bnode0 . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should parse list with multiple elements" do n3 = %(@prefix :. :gregg :name ("Gregg" "Barnum" "Kellogg").) nt = %( _:bnode0 "Gregg" . _:bnode0 _:bnode1 . _:bnode1 "Barnum" . _:bnode1 _:bnode2 . _:bnode2 "Kellogg" . _:bnode2 . _:bnode0 . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should parse unattached lists" do n3 = %( @prefix a: . ("1" "2" "3") . # This is not a statement. () . ) nt = %( _:bnode0 "1" . _:bnode0 _:bnode1 . _:bnode1 "2" . _:bnode1 _:bnode2 . _:bnode2 "3" . _:bnode2 . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end it "should add property to nil list" do n3 = %(@prefix a: . () a:prop "nilProp" .) nt = %( "nilProp" .) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug, :compare => :array) end it "should parse with compound items" do n3 = %( @prefix a: . a:a a:p ( [ a:p2 "v1" ] ("inner list") ) . a:p "value" . ) nt = %( _:bnode0 "v1" . _:bnode1 _:bnode0 . _:bnode1 _:bnode2 . _:bnode2 . _:bnode2 _:bnode3 . _:bnode3 . _:bnode4 "inner list" . _:bnode4 . _:bnode3 _:bnode5 . _:bnode5 _:bnode4 . _:bnode5 . _:bnode1 . "value" . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end end # n3p tests taken from http://inamidst.com/n3p/test/ describe "with real data tests" do dirs = %w(misc lcsh rdflib n3p) dirs.each do |dir| dir_name = File.join(File.dirname(__FILE__), '..', 'test', 'n3_tests', dir, '*.n3') Dir.glob(dir_name).each do |n3| it "#{dir} #{n3}" do test_file(n3) end end end end describe "with AggregateGraph tests" do describe "with a type" do it "should have 3 namespaces" do n3 = %( @prefix rdf: . @prefix rdfs: . @prefix : . :foo a rdfs:Class. :bar :d :c. :a :d :c. ) nt = %( . . . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end end describe "with blank clause" do it "should have 4 namespaces" do n3 = %( @prefix rdf: . @prefix rdfs: . @prefix : . @prefix log: . :foo a rdfs:Resource. :bar rdfs:isDefinedBy [ a log:Formula ]. :a :d :e. ) nt = %( . _:g2160128180 . _:g2160128180 . . ) parse(n3, :base_uri => "http://a/b").should be_equivalent_graph(nt, :about => "http://a/b", :trace => @debug) end end describe "with empty subject" do before(:each) do @graph = parse(%( @prefix rdf: . @prefix rdfs: . @prefix log: . @prefix : . <> a log:N3Document. ), :base_uri => "http://test/") end it "should have 4 namespaces" do nt = %( . ) @graph.should be_equivalent_graph(nt, :about => "http://test/", :trace => @debug) end it "should have default subject" do @graph.size.should == 1 @graph.statements.first.subject.to_s.should == "http://test/" end end end end it "should parse rdf_core testcase" do sampledoc = <<-EOF; . . . . . "APPROVED" . . . EOF graph = parse(sampledoc, :base_uri => "http://www.w3.org/2000/10/rdf-tests/rdfcore/amp-in-url/Manifest.rdf") graph.should be_equivalent_graph(sampledoc, :about => "http://www.w3.org/2000/10/rdf-tests/rdfcore/amp-in-url/Manifest.rdf", :trace => @debug, :compare => :array ) end def parse(input, options = {}) @debug = [] graph = RDF::Graph.new RDF::N3::Reader.new(input, options.merge(:debug => @debug, :strict => true)).each do |statement| graph << statement end graph end def test_file(filepath) n3_string = File.read(filepath) @graph = parse(File.open(filepath), :base_uri => "file:#{filepath}") nt_string = File.read(filepath.sub('.n3', '.nt')) @graph.should be_equivalent_graph(nt_string, :about => "file:#{filepath}", :trace => @debug) end end