dbd 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/HISTORY.txt +6 -0
- data/bin/test_1.rb +34 -0
- data/dbd.gemspec +4 -4
- data/lib/dbd/fact.rb +60 -20
- data/lib/dbd/fact/id.rb +5 -9
- data/lib/dbd/fact/subject.rb +5 -9
- data/lib/dbd/graph.rb +1 -1
- data/lib/dbd/time_stamp.rb +36 -18
- data/lib/dbd/version.rb +1 -1
- data/spec/factories/fact.rb +9 -0
- data/spec/factories/fact/id.rb +1 -6
- data/spec/factories/fact/subject.rb +2 -7
- data/spec/factories/resource.rb +5 -0
- data/spec/factories/time_stamp.rb +5 -1
- data/spec/lib/dbd/fact/collection/collection_spec.rb +2 -2
- data/spec/lib/dbd/fact/id/factory_spec.rb +1 -5
- data/spec/lib/dbd/fact/id/id_spec.rb +4 -16
- data/spec/lib/dbd/fact/methods_spec.rb +56 -11
- data/spec/lib/dbd/fact/new_spec.rb +25 -7
- data/spec/lib/dbd/fact/subject/factory_spec.rb +4 -12
- data/spec/lib/dbd/fact/subject/subject_spec.rb +4 -16
- data/spec/lib/dbd/graph/add_to_graph_spec.rb +1 -1
- data/spec/lib/dbd/graph/from_csv_spec.rb +18 -1
- data/spec/lib/dbd/performance_spec.rb +1 -0
- data/spec/lib/dbd/resource/factory_spec.rb +4 -0
- data/spec/lib/dbd/time_stamp/comparisons_spec.rb +25 -3
- data/spec/lib/dbd/time_stamp/factory_spec.rb +2 -1
- data/spec/lib/dbd/time_stamp/methods_spec.rb +4 -4
- data/spec/lib/dbd/time_stamp/new_spec.rb +8 -1
- metadata +19 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ceec5332dfdb3174ee303dcd09cf401186990c8
|
4
|
+
data.tar.gz: a7e61a7b4acc1dcb9a966369ba1c4d8a853b5f9f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1da941433fd3f5dc0f077992bec69d6dc2a3dc761d52549934dd707e713d6317495ae54659e764c21bab079789ed3e74e260ff639bf237715f14222bc267e9b
|
7
|
+
data.tar.gz: cfdd88e0c3ed9e012f354008ab32685c052fffef7897492d78663d2d243c76abd9ae0a3f3a0c2b8b4f5c54ab8371553a9f129436a36a25ea57e46b86d555d8ef
|
data/.travis.yml
CHANGED
data/HISTORY.txt
CHANGED
data/bin/test_1.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# This is a very primitive implementation:
|
4
|
+
# the CSV is first fully built and only then
|
5
|
+
# written to disk. Needs to be modified to
|
6
|
+
# stream to disk.
|
7
|
+
|
8
|
+
count = ARGV[0].to_i
|
9
|
+
unless count > 0
|
10
|
+
puts "Give a 'count' as first argument."
|
11
|
+
exit(1)
|
12
|
+
end
|
13
|
+
|
14
|
+
filename = ARGV[1]
|
15
|
+
unless filename.size > 0
|
16
|
+
puts "Give a 'filename' as second argument."
|
17
|
+
exit(1)
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'dbd'
|
21
|
+
provenance_resource = Dbd::ProvenanceResource.new
|
22
|
+
provenance_resource << Dbd::ProvenanceFact.new(predicate: "prov:test" , object: "A" * 10)
|
23
|
+
|
24
|
+
resource = Dbd::Resource.new(provenance_subject: provenance_resource.subject)
|
25
|
+
(0...count).each do |i|
|
26
|
+
resource << Dbd::Fact.new(predicate: "test", object: "#{'B' * 80} #{i}")
|
27
|
+
end
|
28
|
+
|
29
|
+
graph = Dbd::Graph.new
|
30
|
+
graph << provenance_resource << resource
|
31
|
+
|
32
|
+
File.open(filename, 'w') do |f|
|
33
|
+
f << graph.to_CSV
|
34
|
+
end
|
data/dbd.gemspec
CHANGED
@@ -18,13 +18,13 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency 'bundler'
|
21
|
+
spec.add_development_dependency 'bundler'
|
22
22
|
spec.add_development_dependency 'rake'
|
23
23
|
spec.add_development_dependency 'guard-rspec'
|
24
|
-
spec.add_development_dependency 'rb-fsevent'
|
24
|
+
spec.add_development_dependency 'rb-fsevent'
|
25
25
|
spec.add_development_dependency 'terminal-notifier-guard'
|
26
26
|
spec.add_development_dependency 'yard'
|
27
27
|
spec.add_runtime_dependency 'neography'
|
28
|
-
spec.add_runtime_dependency 'rdf'
|
29
|
-
spec.add_runtime_dependency 'ruby_peter_v', '>= 0.0.
|
28
|
+
spec.add_runtime_dependency 'rdf'
|
29
|
+
spec.add_runtime_dependency 'ruby_peter_v', '>= 0.0.9'
|
30
30
|
end
|
data/lib/dbd/fact.rb
CHANGED
@@ -78,41 +78,43 @@ module Dbd
|
|
78
78
|
# This implements a "form" of immutable behavior. The value can
|
79
79
|
# be set once (possibly after creation the object), but can
|
80
80
|
# never be changed after that.
|
81
|
+
#
|
82
|
+
# The input class is validated (easy confusion with String or Time).
|
81
83
|
def time_stamp=(time_stamp)
|
82
|
-
|
84
|
+
validate_time_stamp_class(time_stamp)
|
83
85
|
set_once(:time_stamp, time_stamp)
|
84
86
|
end
|
85
87
|
|
86
88
|
##
|
87
|
-
# A set_once setter for
|
89
|
+
# A set_once setter for provenance_subject.
|
88
90
|
#
|
89
91
|
# This implements a "form" of immutable behavior. The value can
|
90
92
|
# be set once (possibly after creation the object), but can
|
91
93
|
# never be changed after that.
|
92
|
-
def
|
93
|
-
set_once(:
|
94
|
+
def provenance_subject=(provenance_subject)
|
95
|
+
set_once(:provenance_subject, provenance_subject)
|
94
96
|
end
|
95
97
|
|
96
98
|
##
|
97
|
-
# A set_once setter for
|
99
|
+
# A set_once setter for subject.
|
98
100
|
#
|
99
101
|
# This implements a "form" of immutable behavior. The value can
|
100
102
|
# be set once (possibly after creation the object), but can
|
101
103
|
# never be changed after that.
|
102
|
-
def
|
103
|
-
set_once(:
|
104
|
+
def subject=(subject)
|
105
|
+
set_once(:subject, subject)
|
104
106
|
end
|
105
107
|
|
106
108
|
##
|
107
|
-
# @return [
|
109
|
+
# @return [String] A new subject string.
|
108
110
|
def self.new_subject
|
109
|
-
Subject.
|
111
|
+
Subject.new_subject
|
110
112
|
end
|
111
113
|
|
112
114
|
##
|
113
|
-
# @return [
|
115
|
+
# @return [String] A new id string.
|
114
116
|
def self.new_id
|
115
|
-
ID.
|
117
|
+
ID.new_id
|
116
118
|
end
|
117
119
|
|
118
120
|
##
|
@@ -121,13 +123,14 @@ module Dbd
|
|
121
123
|
# @param [Hash{Symbol => Object}] options
|
122
124
|
# @option options [#to_s] :predicate Required : the predicate for this Fact
|
123
125
|
# @option options [#to_s] :object Required : the object for this Fact (required)
|
124
|
-
# @option options [
|
125
|
-
# @option options [
|
126
|
+
# @option options [String (uuid)] :provenance_subject (nil) Optional: the subject of the provenance(resource|fact)
|
127
|
+
# @option options [String (uuid)] :subject (nil) Optional: the subject for this Fact
|
126
128
|
# @option options [TimeStamp] :time_stamp (nil) Optional: the time_stamp for this Fact
|
127
|
-
# @option options [
|
129
|
+
# @option options [String (uuid)] :id Optional : set the id
|
128
130
|
def initialize(options)
|
129
131
|
@id = options[:id] || self.class.new_id
|
130
132
|
@time_stamp = options[:time_stamp]
|
133
|
+
validate_time_stamp_class(@time_stamp)
|
131
134
|
@provenance_subject = options[:provenance_subject]
|
132
135
|
@subject = options[:subject]
|
133
136
|
@predicate = options[:predicate]
|
@@ -143,14 +146,38 @@ module Dbd
|
|
143
146
|
end
|
144
147
|
|
145
148
|
##
|
146
|
-
#
|
149
|
+
# @return [Array] The 6 values of a Fact converted to a string.
|
150
|
+
# This is similar to the 6 entries in the to_CSV mapping
|
151
|
+
def string_values
|
152
|
+
values.map(&:to_s)
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# Constructs a Fact or ProvenanceFact from a string values array
|
147
157
|
# (e.g. pulled from a CSV row).
|
148
158
|
#
|
149
159
|
# @param [Array] values Required : the array with values, organized as in attributes
|
150
160
|
# @return [Fact, ProvenanceFact] the constructed fact
|
151
|
-
def self.
|
152
|
-
|
153
|
-
fact_from_hash(
|
161
|
+
def self.from_string_values(string_values)
|
162
|
+
string_hash = hash_from_values(string_values)
|
163
|
+
fact_from_hash(values_hash(string_hash))
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# Equivalent facts (have all same values, except time_stamp).
|
168
|
+
#
|
169
|
+
# For "equality" only a test on the id is used. If the id
|
170
|
+
# (which is a uuid) is the same, we assume that is the "same"
|
171
|
+
# fact. This equivalent? method is used to test is equal
|
172
|
+
# methods are "really" equivalent.
|
173
|
+
#
|
174
|
+
# The time_stamp may be slightly different (because shifts
|
175
|
+
# of a few nanoseconds will be required to resolve collisions
|
176
|
+
# on merge).
|
177
|
+
def equivalent?(other)
|
178
|
+
(self.class.attributes - [:time_stamp]).
|
179
|
+
all?{ |attribute| self.send(attribute) == other.send(attribute) } &&
|
180
|
+
self.time_stamp.near?(other.time_stamp)
|
154
181
|
end
|
155
182
|
|
156
183
|
##
|
@@ -219,19 +246,32 @@ module Dbd
|
|
219
246
|
"#{provenance_subject.to_s[0...8]}"
|
220
247
|
end
|
221
248
|
|
249
|
+
# FIXME This has to move to a Fact::Factory
|
222
250
|
def self.hash_from_values(values)
|
223
251
|
# Do not keep "empty" values (e.g. the provenance_subject for a ProvenanceFact).
|
224
|
-
attributes_values_array = [attributes, values].transpose.
|
252
|
+
attributes_values_array = [attributes, values].transpose.delete_if{|a,v| v.nil? || v == ''}
|
225
253
|
Hash[attributes_values_array]
|
226
254
|
end
|
227
255
|
|
256
|
+
def self.values_hash(string_hash)
|
257
|
+
string_hash.dup.tap do |h|
|
258
|
+
h[:time_stamp] = TimeStamp.new(time: h[:time_stamp])
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
228
262
|
def self.fact_from_hash(hash)
|
229
263
|
if hash[:provenance_subject]
|
230
|
-
new(hash)
|
264
|
+
Fact.new(hash)
|
231
265
|
else
|
232
266
|
ProvenanceFact.new(hash)
|
233
267
|
end
|
234
268
|
end
|
235
269
|
|
270
|
+
def validate_time_stamp_class(time_stamp)
|
271
|
+
unless time_stamp.nil? || time_stamp.is_a?(TimeStamp)
|
272
|
+
raise ArgumentError, "time_stamp is of class #{time_stamp.class}, should be TimeStamp"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
236
276
|
end
|
237
277
|
end
|
data/lib/dbd/fact/id.rb
CHANGED
@@ -1,19 +1,15 @@
|
|
1
1
|
module Dbd
|
2
2
|
class Fact
|
3
|
-
|
4
|
-
|
5
|
-
def initialize(options = {})
|
6
|
-
@uuid = options[:uuid] || Helpers::UUID.new.to_s
|
7
|
-
end
|
8
|
-
|
9
|
-
def to_s
|
10
|
-
@uuid
|
11
|
-
end
|
3
|
+
module ID
|
12
4
|
|
13
5
|
def self.regexp
|
14
6
|
Helpers::UUID.regexp
|
15
7
|
end
|
16
8
|
|
9
|
+
def self.new_id
|
10
|
+
Helpers::UUID.new.to_s
|
11
|
+
end
|
12
|
+
|
17
13
|
end
|
18
14
|
end
|
19
15
|
end
|
data/lib/dbd/fact/subject.rb
CHANGED
@@ -2,20 +2,16 @@ require 'dbd/helpers/uuid'
|
|
2
2
|
|
3
3
|
module Dbd
|
4
4
|
class Fact
|
5
|
-
|
6
|
-
|
7
|
-
def initialize(options = {})
|
8
|
-
@uuid = options[:uuid] || Helpers::UUID.new.to_s
|
9
|
-
end
|
10
|
-
|
11
|
-
def to_s
|
12
|
-
@uuid
|
13
|
-
end
|
5
|
+
module Subject
|
14
6
|
|
15
7
|
def self.regexp
|
16
8
|
Helpers::UUID.regexp
|
17
9
|
end
|
18
10
|
|
11
|
+
def self.new_subject
|
12
|
+
Helpers::UUID.new.to_s
|
13
|
+
end
|
14
|
+
|
19
15
|
end
|
20
16
|
end
|
21
17
|
end
|
data/lib/dbd/graph.rb
CHANGED
data/lib/dbd/time_stamp.rb
CHANGED
@@ -42,10 +42,11 @@ module Dbd
|
|
42
42
|
# Builds a new TimeStamp.
|
43
43
|
#
|
44
44
|
# @param [Hash{Symbol => Object}] options
|
45
|
-
# @option options [Time] :time (Time.now) force the time to this value
|
45
|
+
# @option options [Time, String] :time (Time.now) force the time to this value
|
46
46
|
# @option options [TimeStamp] :larger_than (void) time_stamp must be larger than this
|
47
47
|
def initialize(options={})
|
48
48
|
@time = options[:time] || new_time(options[:larger_than])
|
49
|
+
@time = time_from_s(@time) if @time.is_a?(String)
|
49
50
|
end
|
50
51
|
|
51
52
|
##
|
@@ -66,34 +67,51 @@ module Dbd
|
|
66
67
|
Rational("#{1+rand(999)}/1_000_000_000")
|
67
68
|
end
|
68
69
|
|
69
|
-
def
|
70
|
+
def time_format
|
70
71
|
'%F %T.%N %Z'
|
71
72
|
end
|
72
73
|
|
74
|
+
##
|
75
|
+
# with a nanosecond granularity and in UTC
|
76
|
+
def time_from_s(time_string)
|
77
|
+
# For ns precision in JRuby this extended process is required
|
78
|
+
time_hash = DateTime._strptime(time_string, time_format)
|
79
|
+
validate_time_zone(time_hash)
|
80
|
+
Time.utc(time_hash[:year],
|
81
|
+
time_hash[:mon],
|
82
|
+
time_hash[:mday],
|
83
|
+
time_hash[:hour],
|
84
|
+
time_hash[:min],
|
85
|
+
time_hash[:sec],
|
86
|
+
time_hash[:sec_fraction] * 1_000_000)
|
87
|
+
end
|
88
|
+
|
89
|
+
def validate_time_zone(time_hash)
|
90
|
+
unless time_hash[:zone] == 'UTC'
|
91
|
+
raise(ArgumentError, "Time zone was #{time_hash[:zone]}, must be 'UTC'")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
73
95
|
public
|
74
96
|
|
75
97
|
##
|
76
98
|
# with a nanosecond granularity and in UTC
|
77
99
|
def to_s
|
78
|
-
@time.strftime(
|
100
|
+
@time.strftime(time_format)
|
79
101
|
end
|
80
102
|
|
103
|
+
# Max drift in time_stamp
|
104
|
+
MAX_DRIFT = Rational("1/1_000_000")
|
105
|
+
|
81
106
|
##
|
82
|
-
#
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
time_hash[:mon],
|
91
|
-
time_hash[:mday],
|
92
|
-
time_hash[:hour],
|
93
|
-
time_hash[:min],
|
94
|
-
time_hash[:sec],
|
95
|
-
time_hash[:sec_fraction] * 1_000_000)
|
96
|
-
TimeStamp.new(time: time)
|
107
|
+
# determines if 2 time_stamps are "near".
|
108
|
+
#
|
109
|
+
# The time_stamp of an equivalent fact may be slightly different
|
110
|
+
# (because shifts of a few nanoseconds will be required to resolve
|
111
|
+
# collisions on a merge of fact streams with overlapping time_stamp
|
112
|
+
# ranges).
|
113
|
+
def near?(other)
|
114
|
+
(self - other).abs <= MAX_DRIFT
|
97
115
|
end
|
98
116
|
|
99
117
|
def >(other)
|
data/lib/dbd/version.rb
CHANGED
data/spec/factories/fact.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding=utf-8
|
1
2
|
module Factories
|
2
3
|
module Fact
|
3
4
|
|
@@ -23,6 +24,14 @@ module Factories
|
|
23
24
|
object: "Gandhi")
|
24
25
|
end
|
25
26
|
|
27
|
+
def self.fact_with_special_chars(provenance_subject = nil, subject = nil)
|
28
|
+
factory_for.new(
|
29
|
+
provenance_subject: provenance_subject,
|
30
|
+
subject: subject,
|
31
|
+
predicate: "http://example.org/test/comment",
|
32
|
+
object: "A long story\nreally with a comma, a double quote \" and a non-ASCII char éà Über.")
|
33
|
+
end
|
34
|
+
|
26
35
|
def self.fact_with_time_stamp(time_stamp)
|
27
36
|
factory_for.new(
|
28
37
|
time_stamp: time_stamp,
|
data/spec/factories/fact/id.rb
CHANGED
@@ -1,17 +1,12 @@
|
|
1
1
|
module Factories
|
2
2
|
module Fact
|
3
3
|
module Subject
|
4
|
-
|
5
|
-
def self.factory_for
|
6
|
-
::Dbd::Fact::Subject
|
7
|
-
end
|
8
|
-
|
9
4
|
def self.fixed_subject
|
10
|
-
|
5
|
+
"2e9fbc87-2e94-47e9-a8fd-121cc4bc3e8f"
|
11
6
|
end
|
12
7
|
|
13
8
|
def self.fixed_provenance_subject
|
14
|
-
|
9
|
+
"40fab407-9b04-4a51-9a52-d978abfcbb1f"
|
15
10
|
end
|
16
11
|
end
|
17
12
|
end
|
data/spec/factories/resource.rb
CHANGED
@@ -5,6 +5,11 @@ module Factories
|
|
5
5
|
::Dbd::Resource
|
6
6
|
end
|
7
7
|
|
8
|
+
def self.empty(provenance_subject)
|
9
|
+
subject = Fact.new_subject
|
10
|
+
factory_for.new(subject: subject, provenance_subject: provenance_subject)
|
11
|
+
end
|
12
|
+
|
8
13
|
def self.facts_resource(provenance_subject)
|
9
14
|
subject = Fact.new_subject
|
10
15
|
factory_for.new(subject: subject, provenance_subject: provenance_subject).tap do |resource|
|
@@ -5,8 +5,12 @@ module Factories
|
|
5
5
|
::Dbd::TimeStamp
|
6
6
|
end
|
7
7
|
|
8
|
+
def self.fixed_time_string
|
9
|
+
"2013-06-17 21:55:09.967653013 UTC"
|
10
|
+
end
|
11
|
+
|
8
12
|
def self.fixed_time_stamp
|
9
|
-
factory_for.
|
13
|
+
factory_for.new(time: fixed_time_string)
|
10
14
|
end
|
11
15
|
end
|
12
16
|
end
|
@@ -98,8 +98,8 @@ module Dbd
|
|
98
98
|
|
99
99
|
describe "validate that only 'newer' elements are added" do
|
100
100
|
before(:each) do
|
101
|
-
fact_2_with_subject.stub(:time_stamp).and_return(TimeStamp.new(time: Time.
|
102
|
-
fact_3_with_subject.stub(:time_stamp).and_return(TimeStamp.new(time: Time.
|
101
|
+
fact_2_with_subject.stub(:time_stamp).and_return(TimeStamp.new(time: Time.utc(2013,05,9,12,0,0)))
|
102
|
+
fact_3_with_subject.stub(:time_stamp).and_return(TimeStamp.new(time: Time.utc(2013,05,9,12,0,1)))
|
103
103
|
end
|
104
104
|
|
105
105
|
it "adding an element with a newer time_stamp succeeds" do
|
@@ -7,12 +7,8 @@ module Dbd
|
|
7
7
|
|
8
8
|
let(:fixed_id) { Factories::Fact::ID.fixed_id }
|
9
9
|
|
10
|
-
it "fixed_id is an Fact::ID" do
|
11
|
-
fixed_id.should be_a(described_class)
|
12
|
-
end
|
13
|
-
|
14
10
|
it "fixed_id is exactly this fixed id" do
|
15
|
-
fixed_id.
|
11
|
+
fixed_id.should == "825e44d5-af33-4858-8047-549bd813daa8"
|
16
12
|
end
|
17
13
|
end
|
18
14
|
end
|
@@ -3,25 +3,13 @@ require 'spec_helper'
|
|
3
3
|
module Dbd
|
4
4
|
class Fact
|
5
5
|
describe ID do
|
6
|
-
describe ".new" do
|
7
|
-
it "creates an ID with a random uuid" do
|
8
|
-
subject.should be_a(described_class)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "optionally takes an options hash with :uuid key" do
|
12
|
-
uuid = "825e44d5-af33-4858-8047-549bd813daa8"
|
13
|
-
id = described_class.new(uuid: uuid)
|
14
|
-
id.to_s.should == uuid
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
it "#to_s is a UUID string" do
|
19
|
-
subject.to_s.should match(Helpers::UUID.regexp)
|
20
|
-
end
|
21
|
-
|
22
6
|
it ".regexp has a regexp for the to_s" do
|
23
7
|
described_class.regexp.should == Helpers::UUID.regexp
|
24
8
|
end
|
9
|
+
|
10
|
+
it ".new_id" do
|
11
|
+
described_class.new_id.should match(described_class.regexp)
|
12
|
+
end
|
25
13
|
end
|
26
14
|
end
|
27
15
|
end
|
@@ -8,6 +8,7 @@ module Dbd
|
|
8
8
|
let(:fact_1) { Factories::Fact.fact_1(provenance_subject) }
|
9
9
|
let(:fact_2_with_subject) { Factories::Fact.fact_2_with_subject(provenance_subject) }
|
10
10
|
let(:fact_with_newline) { Factories::Fact.fact_with_newline(provenance_subject) }
|
11
|
+
let(:full_fact) { Factories::Fact.full_fact }
|
11
12
|
|
12
13
|
describe "time_stamp=" do
|
13
14
|
it "checks the type (too easy to try to give a Time arg)" do
|
@@ -78,7 +79,7 @@ module Dbd
|
|
78
79
|
end
|
79
80
|
end
|
80
81
|
|
81
|
-
describe "attributes
|
82
|
+
describe "attributes" do
|
82
83
|
it "there are 6 attributes" do
|
83
84
|
described_class.attributes.size.should == 6
|
84
85
|
end
|
@@ -86,31 +87,75 @@ module Dbd
|
|
86
87
|
it "first attribute is :id" do
|
87
88
|
described_class.attributes.first.should == :id
|
88
89
|
end
|
90
|
+
end
|
89
91
|
|
92
|
+
describe "values" do
|
90
93
|
it "there are 6 values" do
|
91
|
-
|
94
|
+
full_fact.values.size.should == 6
|
95
|
+
end
|
96
|
+
|
97
|
+
it "the second element (time_stamp) is a TimeStamp" do
|
98
|
+
full_fact.values[1].should be_a(TimeStamp)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "string_values" do
|
103
|
+
it "there are 6 string_values" do
|
104
|
+
full_fact.string_values.size.should == 6
|
105
|
+
end
|
106
|
+
|
107
|
+
it "the second element (time_stamp) is a String" do
|
108
|
+
full_fact.string_values[1].should be_a(String)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "provenance_fact?" do
|
113
|
+
it "is false for a base fact or derived from it that is not a ProvenanceFact " do
|
114
|
+
fact_1.provenance_fact?.should be_false
|
92
115
|
end
|
93
116
|
end
|
94
117
|
|
95
|
-
def
|
118
|
+
def string_values
|
96
119
|
["825e44d5-af33-4858-8047-549bd813daa8",
|
97
|
-
"2013-06-17 21:55:09.
|
120
|
+
"2013-06-17 21:55:09.967653013 UTC",
|
98
121
|
"40fab407-9b04-4a51-9a52-d978abfcbb1f",
|
99
122
|
"2e9fbc87-2e94-47e9-a8fd-121cc4bc3e8f",
|
100
123
|
"http://example.org/test/name",
|
101
124
|
"Gandhi"]
|
102
125
|
end
|
103
126
|
|
104
|
-
describe "
|
105
|
-
it "reads the values correctly" do
|
106
|
-
fact = described_class.
|
107
|
-
fact.
|
127
|
+
describe "from_string_values" do
|
128
|
+
it "reads the values correctly (round trip test)" do
|
129
|
+
fact = described_class.from_string_values(string_values)
|
130
|
+
fact.string_values.should == string_values
|
108
131
|
end
|
109
132
|
end
|
110
133
|
|
111
|
-
describe "
|
112
|
-
|
113
|
-
|
134
|
+
describe "equivalent?" do
|
135
|
+
|
136
|
+
let(:ref) { described_class.from_string_values(string_values) }
|
137
|
+
|
138
|
+
it "is true for facts with same values" do
|
139
|
+
other = described_class.from_string_values(string_values)
|
140
|
+
other.should be_equivalent(ref)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "is false for each of the entries largely different" do
|
144
|
+
(0...string_values.size).each do |index|
|
145
|
+
string_values_1_modified = string_values.dup.tap { |_string_values|
|
146
|
+
_string_values[index][3] = '4' # different and valid for all cases
|
147
|
+
}
|
148
|
+
other = described_class.from_string_values(string_values_1_modified)
|
149
|
+
other.should_not be_equivalent(ref)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
it "is true when the time_stamp is 500 ns larger" do
|
154
|
+
string_values_time_modified = string_values.dup.tap { |_string_values|
|
155
|
+
_string_values[1] = "2013-06-17 21:55:09.967653513 UTC"
|
156
|
+
}
|
157
|
+
other = described_class.from_string_values(string_values_time_modified)
|
158
|
+
other.should be_equivalent(ref)
|
114
159
|
end
|
115
160
|
end
|
116
161
|
end
|
@@ -2,21 +2,23 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Dbd
|
4
4
|
describe Fact do
|
5
|
+
let(:provenance_subject) { ProvenanceFact.new_subject }
|
5
6
|
let(:fact_1) { Factories::Fact.fact_1(provenance_subject) }
|
6
7
|
let(:fact_2_with_subject) { Factories::Fact.fact_2_with_subject(provenance_subject) }
|
7
|
-
let(:provenance_subject) { ProvenanceFact.new_subject }
|
8
8
|
let(:data_predicate) { "http://example.org/test/name" }
|
9
9
|
let(:string_object_1) { "Gandhi" }
|
10
|
-
let(:
|
11
|
-
let(:
|
10
|
+
let(:id_regexp) { Fact::ID.regexp }
|
11
|
+
let(:subject_regexp) { Fact::Subject.regexp }
|
12
12
|
let(:forced_id) { described_class.new_id }
|
13
|
+
let(:subject) { described_class.new_subject }
|
13
14
|
let(:fact_with_forced_id) { Factories::Fact.fact_with_forced_id(forced_id) }
|
14
15
|
let(:time_stamp) { TimeStamp.new }
|
15
16
|
let(:fact_with_time_stamp) { Factories::Fact.fact_with_time_stamp(time_stamp) }
|
17
|
+
let(:fact_with_incorrect_time_stamp) { Factories::Fact.fact_with_time_stamp(time_stamp.time) }
|
16
18
|
|
17
19
|
describe ".new_subject" do
|
18
20
|
it "creates a new (random) subject" do
|
19
|
-
described_class.new_subject.should
|
21
|
+
described_class.new_subject.should match(subject_regexp)
|
20
22
|
end
|
21
23
|
|
22
24
|
it "creating a second one is different" do
|
@@ -26,9 +28,21 @@ module Dbd
|
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
31
|
+
describe ".new_id" do
|
32
|
+
it "creates a new (random) id" do
|
33
|
+
described_class.new_id.should match(id_regexp)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creating a second one is different" do
|
37
|
+
id_1 = described_class.new_id
|
38
|
+
id_2 = described_class.new_id
|
39
|
+
id_1.should_not == id_2
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
29
43
|
describe "create a fact" do
|
30
|
-
it "has a unique id (
|
31
|
-
fact_1.id.should
|
44
|
+
it "has a unique id (matches id_regexp)" do
|
45
|
+
fact_1.id.should match(id_regexp)
|
32
46
|
end
|
33
47
|
|
34
48
|
it "two facts have different id" do
|
@@ -43,12 +57,16 @@ module Dbd
|
|
43
57
|
fact_with_time_stamp.time_stamp.should == time_stamp
|
44
58
|
end
|
45
59
|
|
60
|
+
it "setting the time_stamp to a non TimeStamp raises ArgumentError" do
|
61
|
+
lambda{ fact_with_incorrect_time_stamp }.should raise_error ArgumentError
|
62
|
+
end
|
63
|
+
|
46
64
|
it "new sets the provenance_subject" do
|
47
65
|
fact_1.provenance_subject.should == provenance_subject
|
48
66
|
end
|
49
67
|
|
50
68
|
it "new sets the subject" do
|
51
|
-
fact_2_with_subject.subject.should
|
69
|
+
fact_2_with_subject.subject.should match(subject_regexp)
|
52
70
|
end
|
53
71
|
|
54
72
|
it "a nil predicate raises PredicateError" do
|
@@ -9,22 +9,14 @@ module Dbd
|
|
9
9
|
let(:fixed_provenance_subject) { Factories::Fact::Subject.fixed_provenance_subject }
|
10
10
|
|
11
11
|
describe "fixed_subject" do
|
12
|
-
it "is
|
13
|
-
fixed_subject.should
|
14
|
-
end
|
15
|
-
|
16
|
-
it "fixed_subject is exactly this fixed id" do
|
17
|
-
fixed_subject.to_s.should == "2e9fbc87-2e94-47e9-a8fd-121cc4bc3e8f"
|
12
|
+
it "fixed_subject is exactly this fixed subject" do
|
13
|
+
fixed_subject.should == "2e9fbc87-2e94-47e9-a8fd-121cc4bc3e8f"
|
18
14
|
end
|
19
15
|
end
|
20
16
|
|
21
17
|
describe "fixed_provenance_subject" do
|
22
|
-
it "is
|
23
|
-
fixed_provenance_subject.should
|
24
|
-
end
|
25
|
-
|
26
|
-
it "fixed_provenance_subject is exactly this fixed id" do
|
27
|
-
fixed_provenance_subject.to_s.should == "40fab407-9b04-4a51-9a52-d978abfcbb1f"
|
18
|
+
it "fixed_provenance_subject is exactly this fixed subject" do
|
19
|
+
fixed_provenance_subject.should == "40fab407-9b04-4a51-9a52-d978abfcbb1f"
|
28
20
|
end
|
29
21
|
end
|
30
22
|
end
|
@@ -3,25 +3,13 @@ require 'spec_helper'
|
|
3
3
|
module Dbd
|
4
4
|
class Fact
|
5
5
|
describe Subject do
|
6
|
-
describe ".new" do
|
7
|
-
it "creates a Subject" do
|
8
|
-
subject.should be_a(described_class)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "takes an optional :uuid option argument" do
|
12
|
-
uuid = "fe75eae3-cb14-4495-b726-7ecba8798b6d"
|
13
|
-
subject = described_class.new(uuid: uuid)
|
14
|
-
subject.to_s.should == uuid
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
it "#to_s is a UUID string" do
|
19
|
-
subject.to_s.should match(Helpers::UUID.regexp)
|
20
|
-
end
|
21
|
-
|
22
6
|
it ".regexp has a regexp for the to_s" do
|
23
7
|
described_class.regexp.should == Helpers::UUID.regexp
|
24
8
|
end
|
9
|
+
|
10
|
+
it ".new_subject" do
|
11
|
+
described_class.new_subject.should match(described_class.regexp)
|
12
|
+
end
|
25
13
|
end
|
26
14
|
end
|
27
15
|
end
|
@@ -54,7 +54,7 @@ module Dbd
|
|
54
54
|
|
55
55
|
# NOTE: reduced the far_future from 2500 to 2250 as work around for
|
56
56
|
# http://jira.codehaus.org/browse/JRUBY-7095
|
57
|
-
let(:far_future) { TimeStamp.new(time: Time.
|
57
|
+
let(:far_future) { TimeStamp.new(time: Time.utc(2250,1,1,12,0,0)) }
|
58
58
|
|
59
59
|
it "don't touch the time_stamp if already set" do
|
60
60
|
data_fact.time_stamp = far_future
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding=utf-8
|
1
2
|
require 'spec_helper'
|
2
3
|
|
3
4
|
module Dbd
|
@@ -14,7 +15,7 @@ module Dbd
|
|
14
15
|
graph_from_CSV.to_CSV.should == graph.to_CSV
|
15
16
|
end
|
16
17
|
|
17
|
-
describe "
|
18
|
+
describe ".from_CSV reads back a csv exported graph correctly" do
|
18
19
|
|
19
20
|
describe "for a graph with only provenance_facts" do
|
20
21
|
|
@@ -45,5 +46,21 @@ module Dbd
|
|
45
46
|
end
|
46
47
|
end
|
47
48
|
end
|
49
|
+
|
50
|
+
describe ".from_CSV reads special cases correctly" do
|
51
|
+
|
52
|
+
let(:provenance_subject) { Factories::Fact::Subject.fixed_provenance_subject }
|
53
|
+
let(:resource) { Factories::Resource.empty(provenance_subject) }
|
54
|
+
let(:special_fact) { Factories::Fact.fact_with_special_chars(provenance_subject, resource.subject) }
|
55
|
+
|
56
|
+
it "as object" do
|
57
|
+
resource << special_fact
|
58
|
+
graph = described_class.new << resource
|
59
|
+
csv = graph.to_CSV
|
60
|
+
csv.should match(%r{A long story\nreally with a comma, a double quote "" and a non-ASCII char éà Über.})
|
61
|
+
graph_from_CSV = described_class.from_CSV(csv)
|
62
|
+
graph_from_CSV.first.should be_equivalent(graph.first)
|
63
|
+
end
|
64
|
+
end
|
48
65
|
end
|
49
66
|
end
|
@@ -36,6 +36,7 @@ module Dbd
|
|
36
36
|
duration.should < 0.000_15 * NUMBER_OF_FACTS
|
37
37
|
# typ. 37 us on Mac Ruby 2.0.0 (on 2013-05-15 over 15K iterations)
|
38
38
|
# typ. 45 us on Mac Ruby 2.0.0 (on 2013-06-05 over 10K iterations)
|
39
|
+
# typ. 47 us on Mac Ruby 2.0.0 (on 2013-06-21 over 10K iterations)
|
39
40
|
# typ. 60 us on Mac jruby 1.7.3
|
40
41
|
end
|
41
42
|
end
|
@@ -6,6 +6,10 @@ module Dbd
|
|
6
6
|
let(:provenance_subject) { Factories::ProvenanceResource.provenance_resource.subject }
|
7
7
|
|
8
8
|
describe "Factories::Resource" do
|
9
|
+
it ".empty works" do
|
10
|
+
Factories::Resource.facts_resource(provenance_subject)
|
11
|
+
end
|
12
|
+
|
9
13
|
it ".facts_resource works" do
|
10
14
|
Factories::Resource.facts_resource(provenance_subject)
|
11
15
|
end
|
@@ -3,9 +3,13 @@ require 'spec_helper'
|
|
3
3
|
module Dbd
|
4
4
|
describe TimeStamp do
|
5
5
|
|
6
|
-
let(:time_stamp_0) { described_class.new(time: Time.
|
7
|
-
let(:time_stamp_1) { described_class.new(time: Time.
|
8
|
-
let(:time_stamp_2) { described_class.new(time: Time.
|
6
|
+
let(:time_stamp_0) { described_class.new(time: Time.utc(2013,5,18,12,0,0)) }
|
7
|
+
let(:time_stamp_1) { described_class.new(time: Time.utc(2013,5,18,12,0,0)) }
|
8
|
+
let(:time_stamp_2) { described_class.new(time: Time.utc(2013,5,18,12,0,1,5_000)) }
|
9
|
+
let(:time_stamp_3) { described_class.new(time: Time.utc(2013,5,18,12,0,1,5_001)) }
|
10
|
+
let(:time_stamp_4) { described_class.new(time: Time.utc(2013,5,18,12,0,1,4_999)) }
|
11
|
+
let(:time_stamp_5) { described_class.new(time: Time.utc(2013,5,18,12,0,1,5_002)) }
|
12
|
+
let(:time_stamp_6) { described_class.new(time: Time.utc(2013,5,18,12,0,1,4_998)) }
|
9
13
|
|
10
14
|
describe "==" do
|
11
15
|
it "should be ==" do
|
@@ -17,6 +21,24 @@ module Dbd
|
|
17
21
|
end
|
18
22
|
end
|
19
23
|
|
24
|
+
describe "near?(other)" do
|
25
|
+
it "is true when the time_stamp is 1000 ns larger" do
|
26
|
+
time_stamp_2.near?(time_stamp_3).should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it "is true when the time_stamp is 1000 ns smaller" do
|
30
|
+
time_stamp_2.near?(time_stamp_4).should be_true
|
31
|
+
end
|
32
|
+
|
33
|
+
it "is false when the time_stamp is 2000 ns larger" do
|
34
|
+
time_stamp_2.near?(time_stamp_5).should_not be_true
|
35
|
+
end
|
36
|
+
|
37
|
+
it "is false when the time_stamp is 2000 ns smaller" do
|
38
|
+
time_stamp_2.near?(time_stamp_6).should_not be_true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
20
42
|
describe ">" do
|
21
43
|
it "is true if time_stamp is really larger" do
|
22
44
|
time_stamp_2.should > time_stamp_1
|
@@ -2,6 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Dbd
|
4
4
|
describe TimeStamp do
|
5
|
+
|
5
6
|
let(:fixed_time_stamp) { Factories::TimeStamp.fixed_time_stamp }
|
6
7
|
|
7
8
|
describe "factory works" do
|
@@ -10,7 +11,7 @@ module Dbd
|
|
10
11
|
end
|
11
12
|
|
12
13
|
it "has an exact time" do
|
13
|
-
fixed_time_stamp.to_s.should == "2013-06-17 21:55:09.
|
14
|
+
fixed_time_stamp.to_s.should == "2013-06-17 21:55:09.967653013 UTC"
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
@@ -25,18 +25,18 @@ module Dbd
|
|
25
25
|
|
26
26
|
describe ".from_s" do
|
27
27
|
it "returns a TimeStamp" do
|
28
|
-
described_class.
|
28
|
+
described_class.new(time: a_time_stamp).should be_a(described_class)
|
29
29
|
end
|
30
30
|
|
31
31
|
it "round trips with to_s" do
|
32
|
-
time_stamp = described_class.
|
32
|
+
time_stamp = described_class.new(time: a_time_stamp)
|
33
33
|
time_stamp.to_s.should == a_time_stamp
|
34
34
|
end
|
35
35
|
|
36
36
|
it "raises ArgumentError is time_zone is not UTC" do
|
37
37
|
time_CET = a_time_stamp.sub(/UTC/, 'CET')
|
38
|
-
lambda{ described_class.
|
38
|
+
lambda{ described_class.new(time: time_CET) }.should raise_error ArgumentError
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
41
|
+
end
|
42
42
|
end
|
@@ -6,6 +6,8 @@ module Dbd
|
|
6
6
|
|
7
7
|
let(:time) { Time.now.utc }
|
8
8
|
|
9
|
+
let(:time_string) { Factories::TimeStamp.fixed_time_string }
|
10
|
+
|
9
11
|
before(:each) do
|
10
12
|
time
|
11
13
|
Time.stub(:now).and_return(time)
|
@@ -15,12 +17,17 @@ module Dbd
|
|
15
17
|
subject # should_not raise_error
|
16
18
|
end
|
17
19
|
|
18
|
-
it "with :time option, sets that to time" do
|
20
|
+
it "with :time option given a Time object, sets that to time" do
|
19
21
|
near_future = time + 100
|
20
22
|
time_stamp = described_class.new(time: near_future)
|
21
23
|
time_stamp.time.should == near_future
|
22
24
|
end
|
23
25
|
|
26
|
+
it "with :time option given a String object, sets that to time" do
|
27
|
+
time_stamp = described_class.new(time: time_string)
|
28
|
+
time_stamp.to_s.should == time_string
|
29
|
+
end
|
30
|
+
|
24
31
|
it "with :larger_than, sets a time that is strictly and slightly larger than this" do
|
25
32
|
larger_than = described_class.new(time: time + Rational('500/1000_000')) # 0.5 ms
|
26
33
|
time_stamp = described_class.new(larger_than: larger_than)
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Vandenabeele
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-06-
|
11
|
+
date: 2013-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - '
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - '
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,16 +56,16 @@ dependencies:
|
|
56
56
|
name: rb-fsevent
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: terminal-notifier-guard
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,34 +112,35 @@ dependencies:
|
|
112
112
|
name: rdf
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - '>='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: '0'
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- -
|
122
|
+
- - '>='
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: ruby_peter_v
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - '>='
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: 0.0.
|
131
|
+
version: 0.0.9
|
132
132
|
type: :runtime
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - '>='
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: 0.0.
|
138
|
+
version: 0.0.9
|
139
139
|
description: A data store that (almost) never forgets
|
140
140
|
email:
|
141
141
|
- peter@vandenabeele.com
|
142
|
-
executables:
|
142
|
+
executables:
|
143
|
+
- test_1.rb
|
143
144
|
extensions: []
|
144
145
|
extra_rdoc_files: []
|
145
146
|
files:
|
@@ -153,6 +154,7 @@ files:
|
|
153
154
|
- LICENSE.txt
|
154
155
|
- README.md
|
155
156
|
- Rakefile
|
157
|
+
- bin/test_1.rb
|
156
158
|
- dbd.gemspec
|
157
159
|
- docs/rationale.md
|
158
160
|
- docs/stories/001_create_a_fact.txt
|