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 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