# 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