dbd 0.0.7 → 0.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 34e70c3c3d08093acee3610c0e3d93ac5bace6b6
4
- data.tar.gz: 64f2171e686baaa681c3dccef02ef7feb543b71b
3
+ metadata.gz: 8ceec5332dfdb3174ee303dcd09cf401186990c8
4
+ data.tar.gz: a7e61a7b4acc1dcb9a966369ba1c4d8a853b5f9f
5
5
  SHA512:
6
- metadata.gz: 202ce2b19b1c53a04aa84c0089935baf715f76ed0836d0aaf2259ea930f528592e71ad45f6580679dd1fb5d3174755cbe943092f6c2ac275016294b5908e1920
7
- data.tar.gz: 64dd10c180cb960f408d3de9be9227c392a2dddc93a6db8c4e0e1baa11345b6591df0a3a227fe3ca79d57366c6cfd584378cddabb1b5a327e0c1baf22955b90a
6
+ metadata.gz: f1da941433fd3f5dc0f077992bec69d6dc2a3dc761d52549934dd707e713d6317495ae54659e764c21bab079789ed3e74e260ff639bf237715f14222bc267e9b
7
+ data.tar.gz: cfdd88e0c3ed9e012f354008ab32685c052fffef7897492d78663d2d243c76abd9ae0a3f3a0c2b8b4f5c54ab8371553a9f129436a36a25ea57e46b86d555d8ef
@@ -6,5 +6,4 @@ rvm:
6
6
  - 1.9.3
7
7
  - 1.9.2
8
8
  - jruby-19mode
9
- - ruby-head
10
9
  - jruby-head
@@ -37,3 +37,9 @@
37
37
  =====
38
38
 
39
39
  * fix a bug in TimeStamp round trip in JRuby
40
+
41
+ 0.0.8 (23 June 2013)
42
+ =====
43
+
44
+ * bin/test_1.rb was used for first successful writing of 10M facts using
45
+ ruby-1.9.3-p429 (will report issues on ruby-2.0.0-p195 and jruby-1.7.4)
@@ -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
@@ -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', '> 1.2.4'
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', '~> 0.9'
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', '~> 1.0.6'
29
- spec.add_runtime_dependency 'ruby_peter_v', '>= 0.0.8'
28
+ spec.add_runtime_dependency 'rdf'
29
+ spec.add_runtime_dependency 'ruby_peter_v', '>= 0.0.9'
30
30
  end
@@ -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
- raise ArgumentError unless time_stamp.is_a?(TimeStamp)
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 subject.
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 subject=(subject)
93
- set_once(:subject, subject)
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 provenance_subject.
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 provenance_subject=(provenance_subject)
103
- set_once(:provenance_subject, provenance_subject)
104
+ def subject=(subject)
105
+ set_once(:subject, subject)
104
106
  end
105
107
 
106
108
  ##
107
- # @return [Subject] A new random subject.
109
+ # @return [String] A new subject string.
108
110
  def self.new_subject
109
- Subject.new
111
+ Subject.new_subject
110
112
  end
111
113
 
112
114
  ##
113
- # @return [ID] A new random id.
115
+ # @return [String] A new id string.
114
116
  def self.new_id
115
- ID.new
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 [Subject] :provenance_subject (nil) Optional: the subject of the provenance(resource|fact)
125
- # @option options [Subject] :subject (nil) Optional: the subject for this Fact
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 [ID] :id Optional : set the id
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
- # Constructs a Fact or ProvenanceFact from a values array
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.from_values(values)
152
- hash = hash_from_values(values)
153
- fact_from_hash(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.select{|a,v| v != ''}
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
@@ -1,19 +1,15 @@
1
1
  module Dbd
2
2
  class Fact
3
- class ID
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
@@ -2,20 +2,16 @@ require 'dbd/helpers/uuid'
2
2
 
3
3
  module Dbd
4
4
  class Fact
5
- class Subject
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
@@ -48,7 +48,7 @@ module Dbd
48
48
  new.tap do |graph|
49
49
  CSV.new(csv).each do |row|
50
50
  # TODO validate the input formats (e.g. invalid uuid codes)
51
- graph << Fact.from_values(row)
51
+ graph << Fact.from_string_values(row)
52
52
  end
53
53
  end
54
54
  end
@@ -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 self.time_format
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(self.class.time_format)
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
- # with a nanosecond granularity and in UTC
83
- def self.from_s(time_string)
84
- # For ns precision in JRuby this extended process is required
85
- time_hash = DateTime._strptime(time_string, time_format)
86
- raise(
87
- ArgumentError,
88
- "Time zone must be UTC, was #{time_hash[:zone]}") unless time_hash[:zone] == "UTC"
89
- time = Time.utc(time_hash[:year],
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)
@@ -1,3 +1,3 @@
1
1
  module Dbd
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
@@ -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,
@@ -1,13 +1,8 @@
1
1
  module Factories
2
2
  module Fact
3
3
  module ID
4
-
5
- def self.factory_for
6
- ::Dbd::Fact::ID
7
- end
8
-
9
4
  def self.fixed_id
10
- factory_for.new(uuid: "825e44d5-af33-4858-8047-549bd813daa8")
5
+ "825e44d5-af33-4858-8047-549bd813daa8"
11
6
  end
12
7
  end
13
8
  end
@@ -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
- factory_for.new(uuid: "2e9fbc87-2e94-47e9-a8fd-121cc4bc3e8f")
5
+ "2e9fbc87-2e94-47e9-a8fd-121cc4bc3e8f"
11
6
  end
12
7
 
13
8
  def self.fixed_provenance_subject
14
- factory_for.new(uuid: "40fab407-9b04-4a51-9a52-d978abfcbb1f")
9
+ "40fab407-9b04-4a51-9a52-d978abfcbb1f"
15
10
  end
16
11
  end
17
12
  end
@@ -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.from_s("2013-06-17 21:55:09.967653012 UTC")
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.new(2013,05,9,12,0,0)))
102
- fact_3_with_subject.stub(:time_stamp).and_return(TimeStamp.new(time: Time.new(2013,05,9,12,0,1)))
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.to_s.should == "825e44d5-af33-4858-8047-549bd813daa8"
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 and values" do
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
- fact_1.values.size.should == 6
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 values
118
+ def string_values
96
119
  ["825e44d5-af33-4858-8047-549bd813daa8",
97
- "2013-06-17 21:55:09.967653012 UTC",
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 "from_values" do
105
- it "reads the values correctly" do
106
- fact = described_class.from_values(values)
107
- fact.values.should == values
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 "provenance_fact?" do
112
- it "is false for a base fact or derived from it that is not a ProvenanceFact " do
113
- fact_1.provenance_fact?.should be_false
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(:id_class) { Fact::ID }
11
- let(:subject_class) { Fact::Subject }
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 be_a(subject_class)
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 (id_class)" do
31
- fact_1.id.should be_a(id_class)
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 be_a(subject_class)
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 an Fact::Subject" do
13
- fixed_subject.should be_a(described_class)
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 an Fact::Subject" do
23
- fixed_provenance_subject.should be_a(described_class)
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.new(2250,1,1,12,0,0).utc) }
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 "#from_CSV reads back a csv exported graph correctly" do
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.new(2013,5,18,12,0,0)) }
7
- let(:time_stamp_1) { described_class.new(time: Time.new(2013,5,18,12,0,0)) }
8
- let(:time_stamp_2) { described_class.new(time: Time.new(2013,5,18,12,0,1)) }
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.967653012 UTC"
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.from_s(a_time_stamp).should be_a(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.from_s(a_time_stamp)
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.from_s(time_CET) }.should raise_error ArgumentError
38
+ lambda{ described_class.new(time: time_CET) }.should raise_error ArgumentError
39
39
  end
40
40
  end
41
- end
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.7
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-19 00:00:00.000000000 Z
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: 1.2.4
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: 1.2.4
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.9'
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.9'
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: 1.0.6
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: 1.0.6
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.8
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.8
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