rdf-spec 1.99.0 → 2.0.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/{README → README.md} +2 -0
- data/VERSION +1 -1
- data/lib/rdf/spec.rb +18 -0
- data/lib/rdf/spec/countable.rb +5 -28
- data/lib/rdf/spec/dataset.rb +47 -0
- data/lib/rdf/spec/durable.rb +8 -23
- data/lib/rdf/spec/enumerable.rb +118 -102
- data/lib/rdf/spec/format.rb +4 -26
- data/lib/rdf/spec/http_adapter.rb +1 -23
- data/lib/rdf/spec/indexable.rb +1 -23
- data/lib/rdf/spec/inferable.rb +0 -16
- data/lib/rdf/spec/inspects.rb +4 -5
- data/lib/rdf/spec/matchers.rb +95 -4
- data/lib/rdf/spec/mutable.rb +227 -81
- data/lib/rdf/spec/queryable.rb +122 -165
- data/lib/rdf/spec/readable.rb +0 -22
- data/lib/rdf/spec/reader.rb +21 -29
- data/lib/rdf/spec/repository.rb +80 -40
- data/lib/rdf/spec/transactable.rb +43 -0
- data/lib/rdf/spec/transaction.rb +294 -71
- data/lib/rdf/spec/version.rb +2 -2
- data/lib/rdf/spec/writable.rb +78 -100
- data/lib/rdf/spec/writer.rb +51 -28
- data/spec/countable_spec.rb +11 -0
- data/spec/dataset_spec.rb +14 -0
- data/spec/durable_spec.rb +12 -0
- data/spec/enumerable_spec.rb +11 -0
- data/spec/format_spec.rb +12 -0
- data/spec/http_adapter_spec.rb +15 -0
- data/spec/indexable.rb +15 -0
- data/spec/literal_spec.rb +75 -0
- data/spec/mutable_spec.rb +11 -0
- data/spec/queryable_spec.rb +13 -0
- data/spec/readable.rb +11 -0
- data/spec/reader_spec.rb +17 -0
- data/spec/repository_spec.rb +11 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/transaction_spec.rb +7 -0
- data/spec/version_spec.rb +2 -0
- data/spec/writable_spec.rb +13 -0
- data/spec/writer_spec.rb +11 -0
- metadata +56 -12
data/lib/rdf/spec/format.rb
CHANGED
@@ -13,21 +13,21 @@ RSpec.shared_examples 'an RDF::Format' do
|
|
13
13
|
describe ".for" do
|
14
14
|
RDF::Format.file_extensions.each do |ext, formats|
|
15
15
|
it "detects #{formats.first} using file path foo.#{ext}" do
|
16
|
-
expect(RDF::Format.for("foo.#{ext}")).to eq formats.
|
16
|
+
expect(RDF::Format.for("foo.#{ext}")).to eq formats.last
|
17
17
|
end
|
18
18
|
|
19
19
|
it "detects #{formats.first} using file_name foo.#{ext}" do
|
20
|
-
expect(RDF::Format.for(file_name: "foo.#{ext}")).to eq formats.
|
20
|
+
expect(RDF::Format.for(file_name: "foo.#{ext}")).to eq formats.last
|
21
21
|
end
|
22
22
|
|
23
23
|
it "detects #{formats.first} using file_extension #{ext}" do
|
24
|
-
expect(RDF::Format.for(file_extension: ext)).to eq formats.
|
24
|
+
expect(RDF::Format.for(file_extension: ext)).to eq formats.last
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
28
|
RDF::Format.content_types.each do |content_type, formats|
|
29
29
|
it "detects #{formats.first} using content_type #{content_type}" do
|
30
|
-
expect(RDF::Format.for(content_type: content_type)).to eq formats.
|
30
|
+
expect(RDF::Format.for(content_type: content_type)).to eq formats.last
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -51,25 +51,3 @@ RSpec.shared_examples 'an RDF::Format' do
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
54
|
-
|
55
|
-
##
|
56
|
-
# @deprecated use `it_behaves_like "an RDF::Format"` instead
|
57
|
-
module RDF_Format
|
58
|
-
extend RSpec::SharedContext
|
59
|
-
include RDF::Spec::Matchers
|
60
|
-
|
61
|
-
def self.included(mod)
|
62
|
-
warn "[DEPRECATION] `RDF_Format` is deprecated. "\
|
63
|
-
"Please use `it_behaves_like 'an RDF::Format'`"
|
64
|
-
end
|
65
|
-
|
66
|
-
describe 'examples for' do
|
67
|
-
include_examples 'an RDF::Format' do
|
68
|
-
let(:format_class) { @format_class }
|
69
|
-
|
70
|
-
before do
|
71
|
-
raise '@format_class must be defined' unless defined?(format_class)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -214,7 +214,7 @@ RSpec.shared_examples 'an RDF::HttpAdapter' do
|
|
214
214
|
end
|
215
215
|
expect(WebMock).to have_requested(:get, uri)
|
216
216
|
end
|
217
|
-
end
|
217
|
+
end unless ENV['CI']
|
218
218
|
|
219
219
|
context "https" do
|
220
220
|
let(:uri) {"https://some/secure/uri"}
|
@@ -291,25 +291,3 @@ RSpec.shared_examples 'an RDF::HttpAdapter' do
|
|
291
291
|
end
|
292
292
|
|
293
293
|
end
|
294
|
-
|
295
|
-
##
|
296
|
-
# @deprecated use `it_behaves_like "an RDF::HttpAdapter"` instead
|
297
|
-
module RDF_HttpAdapter
|
298
|
-
extend RSpec::SharedContext
|
299
|
-
include RDF::Spec::Matchers
|
300
|
-
|
301
|
-
def self.included(mod)
|
302
|
-
warn "[DEPRECATION] `RDF_HttpAdapter` is deprecated. "\
|
303
|
-
"Please use `it_behaves_like 'an RDF::HttpAdapter'`"
|
304
|
-
end
|
305
|
-
|
306
|
-
describe 'examples for' do
|
307
|
-
include_examples 'an RDF::HttpAdapter' do
|
308
|
-
let(:http_adapter) { @http_adapter }
|
309
|
-
|
310
|
-
before do
|
311
|
-
raise '@http_adapter must be defined' unless defined?(http_adapter)
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|
315
|
-
end
|
data/lib/rdf/spec/indexable.rb
CHANGED
@@ -18,28 +18,6 @@ RSpec.shared_examples 'an RDF::Indexable' do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it "returns self on #index!" do
|
21
|
-
expect(subject.index!).to
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
##
|
26
|
-
# @deprecated use `it_behaves_like "an RDF::Indexable"` instead
|
27
|
-
module RDF_Indexable
|
28
|
-
extend RSpec::SharedContext
|
29
|
-
include RDF::Spec::Matchers
|
30
|
-
|
31
|
-
def self.included(mod)
|
32
|
-
warn "[DEPRECATION] `RDF_Indexable` is deprecated. "\
|
33
|
-
"Please use `it_behaves_like 'an RDF::Indexable'`"
|
34
|
-
end
|
35
|
-
|
36
|
-
describe 'examples for' do
|
37
|
-
include_examples 'an RDF::Indexable' do
|
38
|
-
let(:indexable) { @indexable }
|
39
|
-
|
40
|
-
before do
|
41
|
-
raise '@indexable must be defined' unless defined?(indexable)
|
42
|
-
end
|
43
|
-
end
|
21
|
+
expect(subject.index!).to eql(subject)
|
44
22
|
end
|
45
23
|
end
|
data/lib/rdf/spec/inferable.rb
CHANGED
@@ -5,19 +5,3 @@ RSpec.shared_examples 'an RDF::Inferable' do
|
|
5
5
|
|
6
6
|
it "is_expected.to implement specs" #TODO
|
7
7
|
end
|
8
|
-
|
9
|
-
##
|
10
|
-
# @deprecated use `it_behaves_like "an RDF::Inferable"` instead
|
11
|
-
module RDF_Inferable
|
12
|
-
extend RSpec::SharedContext
|
13
|
-
include RDF::Spec::Matchers
|
14
|
-
|
15
|
-
def self.included(mod)
|
16
|
-
warn "[DEPRECATION] `RDF_Inferable` is deprecated. "\
|
17
|
-
"Please use `it_behaves_like 'an RDF::Inferable'`"
|
18
|
-
end
|
19
|
-
|
20
|
-
describe 'examples for' do
|
21
|
-
include_examples 'an RDF::Inferable'
|
22
|
-
end
|
23
|
-
end
|
data/lib/rdf/spec/inspects.rb
CHANGED
@@ -1,28 +1,27 @@
|
|
1
1
|
require 'rdf'
|
2
|
-
require 'rdf/ntriples'
|
3
2
|
# override several inspect functions to improve output for what we're doing
|
4
3
|
|
5
4
|
class RDF::Literal
|
6
5
|
def inspect
|
7
|
-
|
6
|
+
"\"#{escape(value)}\" R:L:(#{self.class.to_s.match(/([^:]*)$/)})"
|
8
7
|
end
|
9
8
|
end
|
10
9
|
|
11
10
|
class RDF::URI
|
12
11
|
def inspect
|
13
|
-
RDF::
|
12
|
+
"RDF::URI(#{to_base})"
|
14
13
|
end
|
15
14
|
end
|
16
15
|
|
17
16
|
class RDF::Node
|
18
17
|
def inspect
|
19
|
-
RDF::
|
18
|
+
"RDF::Node(#{to_base})"
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
23
22
|
class RDF::Graph
|
24
23
|
def inspect
|
25
|
-
"
|
24
|
+
"RDF::Graph(graph_name: #{self.graph_name || 'nil'})"
|
26
25
|
end
|
27
26
|
end
|
28
27
|
|
data/lib/rdf/spec/matchers.rb
CHANGED
@@ -184,12 +184,18 @@ module RDF; module Spec
|
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
187
|
-
RSpec::Matchers.define :
|
188
|
-
|
189
|
-
|
187
|
+
RSpec::Matchers.define :write_each do |*messages|
|
188
|
+
supports_block_expectations { true }
|
189
|
+
|
190
|
+
match do |block|
|
191
|
+
messages.each { |message| expect(&block).to write(message) }
|
190
192
|
end
|
193
|
+
end
|
191
194
|
|
192
|
-
|
195
|
+
RSpec::Matchers.define :write do |message|
|
196
|
+
chain(:to) { |io| @io = io }
|
197
|
+
|
198
|
+
supports_block_expectations { true }
|
193
199
|
|
194
200
|
match do |block|
|
195
201
|
@output =
|
@@ -258,6 +264,91 @@ module RDF; module Spec
|
|
258
264
|
{:output => "standard output", :error => "standard error"}[io]
|
259
265
|
end
|
260
266
|
end
|
267
|
+
|
268
|
+
Info = Struct.new(:id, :logger, :action, :result)
|
269
|
+
|
270
|
+
RSpec::Matchers.define :be_equivalent_graph do |expected, info|
|
271
|
+
match do |actual|
|
272
|
+
def normalize(graph)
|
273
|
+
case graph
|
274
|
+
when RDF::Enumerable then graph
|
275
|
+
when IO, StringIO
|
276
|
+
RDF::Repository.new(graph, base_uri: @info.action)
|
277
|
+
else
|
278
|
+
# Figure out which parser to use
|
279
|
+
r = RDF::Repository.new
|
280
|
+
reader_class = RDF::Reader.for() {graph}
|
281
|
+
reader_class.new(graph, base_uri: @info.action).each {|s| r << s}
|
282
|
+
r
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
@info = if (info.id rescue false)
|
287
|
+
info
|
288
|
+
elsif info.is_a?(Logger)
|
289
|
+
Info.new("", info)
|
290
|
+
elsif info.is_a?(Hash)
|
291
|
+
Info.new(info[:id], info[:logger], info[:action], info[:result])
|
292
|
+
else
|
293
|
+
Info.new(info)
|
294
|
+
end
|
295
|
+
@expected = normalize(expected)
|
296
|
+
@actual = normalize(actual)
|
297
|
+
@actual.isomorphic_with?(@expected) rescue false
|
298
|
+
end
|
299
|
+
|
300
|
+
failure_message do |actual|
|
301
|
+
format = case
|
302
|
+
when RDF.const_defined?(:TriG) then :trig
|
303
|
+
when RDF.const_defined?(:Turtle) then :ttl
|
304
|
+
else :nquads
|
305
|
+
end
|
306
|
+
info = @info.respond_to?(:information) ? @info.information : @info.inspect
|
307
|
+
if @expected.is_a?(RDF::Enumerable) && @actual.size != @expected.size
|
308
|
+
"Graph entry counts differ:\nexpected: #{@expected.size}\nactual: #{@actual.size}\n"
|
309
|
+
else
|
310
|
+
"Graphs differ\n"
|
311
|
+
end +
|
312
|
+
"\n#{info + "\n" unless info.empty?}" +
|
313
|
+
"Expected:\n#{@expected.dump(format, standard_prefixes: true, literal_shorthand: false, validate: false) rescue @expected.inspect}" +
|
314
|
+
"Results:\n#{@actual.dump(format, standard_prefixes: true, literal_shorthand: false, validate: false) rescue @actual.inspect}" +
|
315
|
+
"\nDebug:\n#{@info.logger}"
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
require 'json'
|
320
|
+
JSON_STATE = ::JSON::State.new(
|
321
|
+
indent: " ",
|
322
|
+
space: " ",
|
323
|
+
space_before: "",
|
324
|
+
object_nl: "\n",
|
325
|
+
array_nl: "\n"
|
326
|
+
)
|
327
|
+
|
328
|
+
RSpec::Matchers.define :produce do |expected, info|
|
329
|
+
match do |actual|
|
330
|
+
@info = if (info.id rescue false)
|
331
|
+
info
|
332
|
+
elsif info.is_a?(Logger)
|
333
|
+
Info.new("", info)
|
334
|
+
elsif info.is_a?(Hash)
|
335
|
+
Info.new(info[:id], info[:logger], info[:action], info[:result])
|
336
|
+
else
|
337
|
+
Info.new(info)
|
338
|
+
end
|
339
|
+
expect(actual).to eq expected
|
340
|
+
end
|
341
|
+
|
342
|
+
failure_message do |actual|
|
343
|
+
info = @info.respond_to?(:information) ? @info.information : @info.inspect
|
344
|
+
|
345
|
+
"Expected: #{expected.is_a?(String) ? expected : expected.to_json(JSON_STATE) rescue 'malformed json'}\n" +
|
346
|
+
"Actual : #{actual.is_a?(String) ? actual : actual.to_json(JSON_STATE) rescue 'malformed json'}\n" +
|
347
|
+
"\n#{info + "\n" unless info.empty?}" +
|
348
|
+
"\nDebug:\n#{@info.logger}"
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
261
352
|
end # Matchers
|
262
353
|
end; end # RDF::Spec
|
263
354
|
|
data/lib/rdf/spec/mutable.rb
CHANGED
@@ -8,11 +8,15 @@ RSpec.shared_examples 'an RDF::Mutable' do
|
|
8
8
|
raise 'mutable must be defined with let(:mutable)' unless
|
9
9
|
defined? mutable
|
10
10
|
|
11
|
+
skip "Immutable resource" unless mutable.mutable?
|
12
|
+
@statements = RDF::Spec.triples
|
11
13
|
@supports_named_graphs = mutable.respond_to?(:supports?) && mutable.supports?(:graph_name)
|
14
|
+
@supports_literal_equality = mutable.respond_to?(:supports?) && mutable.supports?(:literal_equality)
|
12
15
|
end
|
13
16
|
|
14
17
|
let(:resource) { RDF::URI('http://rubygems.org/gems/rdf') }
|
15
18
|
let(:graph_name) { RDF::URI('http://example.org/graph_name') }
|
19
|
+
let(:non_bnode_statements) {@statements.reject(&:node?)}
|
16
20
|
|
17
21
|
describe RDF::Mutable do
|
18
22
|
subject { mutable }
|
@@ -43,36 +47,26 @@ RSpec.shared_examples 'an RDF::Mutable' do
|
|
43
47
|
its(:count) {is_expected.to be_zero}
|
44
48
|
|
45
49
|
context "#load" do
|
46
|
-
it "
|
50
|
+
it "should require an argument" do
|
47
51
|
expect { subject.load }.to raise_error(ArgumentError)
|
48
52
|
end
|
49
53
|
|
50
|
-
it "
|
51
|
-
expect { subject.load(RDF::Spec::TRIPLES_FILE) }.not_to raise_error
|
54
|
+
it "should accept a string filename argument" do
|
55
|
+
expect { subject.load(RDF::Spec::TRIPLES_FILE) }.not_to raise_error
|
52
56
|
end
|
53
57
|
|
54
|
-
it "
|
55
|
-
expect { subject.load(RDF::Spec::TRIPLES_FILE, {}) }.not_to raise_error
|
58
|
+
it "should accept an optional hash argument" do
|
59
|
+
expect { subject.load(RDF::Spec::TRIPLES_FILE, {}) }.not_to raise_error
|
56
60
|
end
|
57
61
|
|
58
|
-
it "
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
is_expected.to have_subject(resource)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
it "is_expected.to load statements with a context override", unless: RDF::VERSION.to_s >= "1.99" do
|
67
|
-
if subject.mutable? && @supports_named_graphs
|
68
|
-
subject.load RDF::Spec::TRIPLES_FILE, context: graph_name
|
69
|
-
is_expected.to have_context(graph_name)
|
70
|
-
expect(subject.query(context: graph_name).size).to eq subject.size
|
71
|
-
end
|
62
|
+
it "should load statements" do
|
63
|
+
subject.load RDF::Spec::TRIPLES_FILE
|
64
|
+
expect(subject.size).to eq File.readlines(RDF::Spec::TRIPLES_FILE).size
|
65
|
+
is_expected.to have_subject(resource)
|
72
66
|
end
|
73
67
|
|
74
|
-
it "
|
75
|
-
if
|
68
|
+
it "should load statements with a graph_name override" do
|
69
|
+
if @supports_named_graphs
|
76
70
|
subject.load RDF::Spec::TRIPLES_FILE, graph_name: graph_name
|
77
71
|
is_expected.to have_graph(graph_name)
|
78
72
|
expect(subject.query(graph_name: graph_name).size).to eq subject.size
|
@@ -81,7 +75,7 @@ RSpec.shared_examples 'an RDF::Mutable' do
|
|
81
75
|
end
|
82
76
|
|
83
77
|
context "#from_{reader}" do
|
84
|
-
it "
|
78
|
+
it "should instantiate a reader" do
|
85
79
|
reader = double("reader")
|
86
80
|
expect(reader).to receive(:new).and_return(RDF::Spec.quads.first)
|
87
81
|
allow(RDF::Reader).to receive(:for).and_call_original
|
@@ -90,89 +84,241 @@ RSpec.shared_examples 'an RDF::Mutable' do
|
|
90
84
|
end
|
91
85
|
end
|
92
86
|
|
87
|
+
context "when updating statements" do
|
88
|
+
let(:s1) { RDF::Statement(resource, RDF::URI.new("urn:predicate:1"), RDF::URI.new("urn:object:1")) }
|
89
|
+
let(:s2) { RDF::Statement(resource, RDF::URI.new("urn:predicate:2"), RDF::URI.new("urn:object:2")) }
|
90
|
+
|
91
|
+
before :each do
|
92
|
+
subject.insert(*[s1,s2])
|
93
|
+
end
|
94
|
+
|
95
|
+
after :each do
|
96
|
+
subject.delete(*[s1,s2])
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should not raise errors" do
|
100
|
+
s1_updated = RDF::Statement(resource, RDF::URI.new("urn:predicate:1"), RDF::URI.new("urn:object:2"))
|
101
|
+
expect { subject.update(s1_updated) }.not_to raise_error
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should support updating one statement at a time with an object" do
|
105
|
+
s1_updated = RDF::Statement(resource, RDF::URI.new("urn:predicate:1"), RDF::URI.new("urn:object:2"))
|
106
|
+
subject.update(s1_updated)
|
107
|
+
expect(subject.has_statement?(s1_updated)).to be true
|
108
|
+
expect(subject.has_statement?(s1)).to be false
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should support updating one statement at a time without an object" do
|
112
|
+
s1_deleted = RDF::Statement(resource, RDF::URI.new("urn:predicate:1"), nil)
|
113
|
+
subject.update(s1_deleted)
|
114
|
+
expect(subject.has_statement?(s1)).to be false
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should support updating an array of statements at a time" do
|
118
|
+
s1_updated = RDF::Statement(resource, RDF::URI.new("urn:predicate:1"), RDF::URI.new("urn:object:2"))
|
119
|
+
s2_updated = RDF::Statement(resource, RDF::URI.new("urn:predicate:2"), RDF::URI.new("urn:object:3"))
|
120
|
+
subject.update(*[s1_updated, s2_updated])
|
121
|
+
expect(subject.has_statement?(s1_updated)).to be true
|
122
|
+
expect(subject.has_statement?(s2_updated)).to be true
|
123
|
+
expect(subject.has_statement?(s1)).to be false
|
124
|
+
expect(subject.has_statement?(s2)).to be false
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should support updating an enumerable of statements at a time" do
|
128
|
+
s1_updated = RDF::Statement(resource, RDF::URI.new("urn:predicate:1"), RDF::URI.new("urn:object:2"))
|
129
|
+
s2_updated = RDF::Statement(resource, RDF::URI.new("urn:predicate:2"), RDF::URI.new("urn:object:3"))
|
130
|
+
updates = [s1_updated, s2_updated]
|
131
|
+
updates.extend(RDF::Enumerable)
|
132
|
+
subject.update(updates)
|
133
|
+
expect(subject.has_statement?(s1_updated)).to be true
|
134
|
+
expect(subject.has_statement?(s2_updated)).to be true
|
135
|
+
expect(subject.has_statement?(s1)).to be false
|
136
|
+
expect(subject.has_statement?(s2)).to be false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
93
140
|
context "when deleting statements" do
|
94
141
|
before :each do
|
95
|
-
@statements = RDF::NTriples::Reader.new(File.open(RDF::Spec::TRIPLES_FILE)).to_a
|
96
142
|
subject.insert(*@statements)
|
97
143
|
end
|
98
144
|
|
99
|
-
it "
|
100
|
-
expect { subject.delete(
|
145
|
+
it "should not raise errors" do
|
146
|
+
expect { subject.delete(non_bnode_statements.first) }.not_to raise_error
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should support deleting one statement at a time" do
|
150
|
+
subject.delete(non_bnode_statements.first)
|
151
|
+
is_expected.not_to have_statement(non_bnode_statements.first)
|
101
152
|
end
|
102
153
|
|
103
|
-
it "
|
154
|
+
it "should support deleting multiple statements at a time" do
|
155
|
+
subject.delete(*@statements)
|
156
|
+
expect(subject.find { |s| subject.has_statement?(s) }).to be_nil
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should support wildcard deletions" do
|
160
|
+
# nothing deleted
|
161
|
+
require 'digest/sha1'
|
162
|
+
count = subject.count
|
163
|
+
subject.delete([nil, nil, Digest::SHA1.hexdigest(File.read(__FILE__))])
|
164
|
+
is_expected.not_to be_empty
|
165
|
+
expect(subject.count).to eq count
|
166
|
+
|
167
|
+
# everything deleted
|
168
|
+
subject.delete([nil, nil, nil])
|
169
|
+
is_expected.to be_empty
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should only delete statements when the graph_name matches" do
|
173
|
+
# Setup three statements identical except for graph_name
|
174
|
+
count = subject.count + (@supports_named_graphs ? 3 : 1)
|
175
|
+
s1 = RDF::Statement.new(resource, RDF::URI.new("urn:predicate:1"), RDF::URI.new("urn:object:1"))
|
176
|
+
s2 = s1.dup
|
177
|
+
s2.graph_name = RDF::URI.new("urn:graph_name:1")
|
178
|
+
s3 = s1.dup
|
179
|
+
s3.graph_name = RDF::URI.new("urn:graph_name:2")
|
180
|
+
subject.insert(s1)
|
181
|
+
subject.insert(s2)
|
182
|
+
subject.insert(s3)
|
183
|
+
expect(subject.count).to eq count
|
184
|
+
|
185
|
+
# Delete one by one
|
186
|
+
subject.delete(s1)
|
187
|
+
expect(subject.count).to eq count - (@supports_named_graphs ? 1 : 1)
|
188
|
+
subject.delete(s2)
|
189
|
+
expect(subject.count).to eq count - (@supports_named_graphs ? 2 : 1)
|
190
|
+
subject.delete(s3)
|
191
|
+
expect(subject.count).to eq count - (@supports_named_graphs ? 3 : 1)
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'does not delete literal with different language' do
|
104
195
|
if subject.mutable?
|
105
|
-
|
106
|
-
|
196
|
+
en = RDF::Literal('abc', language: 'en')
|
197
|
+
fi = RDF::Literal('abc', language: 'fi')
|
198
|
+
|
199
|
+
subject.insert([RDF::URI('http://example.com/s'), RDF::URI('http://example.com/p'), en])
|
200
|
+
expect { subject.delete([RDF::URI('http://example.com/s'), RDF::URI('http://example.com/p'), fi]) }
|
201
|
+
.not_to change { subject.count }
|
107
202
|
end
|
108
203
|
end
|
109
204
|
|
110
|
-
it
|
111
|
-
if subject.mutable?
|
112
|
-
|
113
|
-
|
205
|
+
it 'does not delete literal with different datatype' do
|
206
|
+
if subject.mutable? && @supports_literal_equality
|
207
|
+
dec = RDF::Literal::Decimal.new(1)
|
208
|
+
int = RDF::Literal::Integer.new(1)
|
209
|
+
|
210
|
+
subject.insert([RDF::URI('http://example.com/s'), RDF::URI('http://example.com/p'), dec])
|
211
|
+
|
212
|
+
expect { subject.delete([RDF::URI('http://example.com/s'), RDF::URI('http://example.com/p'), int]) }
|
213
|
+
.not_to change { subject.count }
|
114
214
|
end
|
115
215
|
end
|
116
216
|
|
117
|
-
it
|
118
|
-
if subject.mutable?
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
subject.
|
123
|
-
|
124
|
-
expect
|
125
|
-
|
126
|
-
# everything deleted
|
127
|
-
subject.delete([nil, nil, nil])
|
128
|
-
is_expected.to be_empty
|
217
|
+
it 'does not delete literal with different lexical value' do
|
218
|
+
if subject.mutable? && @supports_literal_equality
|
219
|
+
one = RDF::Literal::Integer.new("1")
|
220
|
+
zero_one = RDF::Literal::Integer.new("01")
|
221
|
+
|
222
|
+
subject.insert([RDF::URI('http://example.com/s'), RDF::URI('http://example.com/p'), one])
|
223
|
+
|
224
|
+
expect { subject.delete([RDF::URI('http://example.com/s'), RDF::URI('http://example.com/p'), zero_one]) }
|
225
|
+
.not_to change { subject.count }
|
129
226
|
end
|
130
227
|
end
|
131
228
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
subject.
|
152
|
-
|
229
|
+
describe '#delete_insert' do
|
230
|
+
let(:statement) do
|
231
|
+
RDF::Statement.new(resource,
|
232
|
+
RDF::URI.new("urn:predicate:1"),
|
233
|
+
RDF::URI.new("urn:object:1"))
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'deletes and inserts' do
|
237
|
+
subject.delete_insert(@statements, [statement])
|
238
|
+
is_expected.to contain_exactly statement
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'deletes before inserting' do
|
242
|
+
subject.delete_insert(@statements, [@statements.first])
|
243
|
+
is_expected.to contain_exactly @statements.first
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'deletes patterns' do
|
247
|
+
pattern = [non_bnode_statements.first.subject, nil, nil]
|
248
|
+
expect { subject.delete_insert([pattern], []) }
|
249
|
+
.to change { subject.has_subject?(non_bnode_statements.first.subject) }
|
250
|
+
.from(true).to(false)
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'handles Enumerables' do
|
254
|
+
dels = non_bnode_statements.take(10)
|
255
|
+
dels.extend(RDF::Enumerable)
|
256
|
+
ins = RDF::Graph.new << statement
|
257
|
+
expect { subject.delete_insert(dels, ins) }
|
258
|
+
.to change { dels.find { |s| subject.include?(s) } }.to be_nil
|
259
|
+
is_expected.to include statement
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'handles Graph names' do
|
263
|
+
if @supports_named_graphs
|
264
|
+
dels = non_bnode_statements.take(10).map do |st|
|
265
|
+
RDF::Statement.from(st.to_hash.merge(graph_name: RDF::URI('http://example.com/fake')))
|
266
|
+
end
|
267
|
+
dels.map! { |st| st.graph_name = RDF::URI('http://example.com/fake'); st }
|
268
|
+
dels.extend(RDF::Enumerable)
|
269
|
+
expect { subject.delete_insert(dels, []) }
|
270
|
+
.not_to change { subject.statements.count }
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
context 'when transactions are supported' do
|
275
|
+
it 'updates atomically' do
|
276
|
+
if subject.mutable? && subject.supports?(:atomic_write)
|
277
|
+
contents = subject.statements.to_a
|
278
|
+
|
279
|
+
expect { subject.delete_insert(@statements, [nil]) }
|
280
|
+
.to raise_error ArgumentError
|
281
|
+
expect(subject.statements).to contain_exactly(*contents)
|
282
|
+
end
|
283
|
+
end
|
153
284
|
end
|
154
285
|
end
|
155
286
|
end
|
156
|
-
|
157
|
-
|
287
|
+
|
288
|
+
describe '#apply_changeset' do
|
289
|
+
let(:changeset) { RDF::Changeset.new }
|
158
290
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
include RDF::Spec::Matchers
|
291
|
+
it 'is a no-op when changeset is empty' do
|
292
|
+
expect { subject.apply_changeset(changeset) }
|
293
|
+
.not_to change { subject.statements }
|
294
|
+
end
|
164
295
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
296
|
+
it 'inserts statements' do
|
297
|
+
changeset.insert(*non_bnode_statements)
|
298
|
+
|
299
|
+
expect { subject.apply_changeset(changeset) }
|
300
|
+
.to change { subject.statements }
|
301
|
+
.to contain_exactly(*non_bnode_statements)
|
302
|
+
end
|
303
|
+
|
304
|
+
it 'deletes statements' do
|
305
|
+
subject.insert(*non_bnode_statements)
|
306
|
+
deletes = non_bnode_statements.take(10)
|
307
|
+
|
308
|
+
changeset.delete(*deletes)
|
309
|
+
subject.apply_changeset(changeset)
|
310
|
+
|
311
|
+
expect(subject).not_to include(*deletes)
|
312
|
+
end
|
169
313
|
|
170
|
-
|
171
|
-
|
172
|
-
|
314
|
+
it 'deletes before inserting' do
|
315
|
+
statement = non_bnode_statements.first
|
316
|
+
|
317
|
+
changeset.insert(statement)
|
318
|
+
changeset.delete(statement)
|
319
|
+
subject.apply_changeset(changeset)
|
173
320
|
|
174
|
-
|
175
|
-
raise '@mutable must be defined' unless defined?(mutable)
|
321
|
+
expect(subject).to include(statement)
|
176
322
|
end
|
177
323
|
end
|
178
324
|
end
|