stable 1.2.0 → 1.3.0

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/stable/spec.rb +18 -9
  3. data/lib/stable.rb +21 -2
  4. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d4375cbe65cd2bf8c245d6415fbf69f7a3d52089e625f9c5d60d776db18bb8e7
4
- data.tar.gz: 73a10041d5fcd9d1c156b62081f477aada4bc8a61fa1fc3fe4b50a102358dba1
3
+ metadata.gz: 632d329e437a0d82fed98a7fd06f9f93c160363e961ea2c835bcc40cc1330066
4
+ data.tar.gz: e301162819f6e056594cc07c600c4c678d91143e371b848367be9e9abaaceaca
5
5
  SHA512:
6
- metadata.gz: d19ad046cd24e28cbb20ef92e23406dff44cc0f798d09a5c1b921d98d48f5edcb7c3dce7180484e535b32ff46ce14e5dddd68e3306d18dc15641069cca39786a
7
- data.tar.gz: 4e05508756de9a0cca55277846f630a54a638504594de3ddd9b024da4f6cd78815407918a610f8800c623552f5b7cbb642fda714176ac680e952ecbda39d91b5
6
+ metadata.gz: '036778caa60876817ab53b71c2e5c2fbedd4105e9084c1bc6a45b6c688a6172f60a0b3434cc732806426131259848ed345de71d519011263692a907282f9a02a'
7
+ data.tar.gz: f427b87ee21f105729862a77e51d06814c90a931f18ced149a6b22cfff42cce643997252e0fdc42f00b9ec6a1db7e478c635db9f45bb7b49076b77443c650804
data/lib/stable/spec.rb CHANGED
@@ -1,14 +1,16 @@
1
1
  # lib/stable/spec.rb
2
2
  require 'json'
3
+ require 'securerandom'
4
+ require 'digest'
3
5
 
4
6
  module Stable
5
7
  # a spec is a recording of a single method call, including the inputs and
6
8
  # outputs. it's a self-contained, serializable representation of a method's
7
9
  # behavior at a specific point in time.
8
10
  class Spec
9
- attr_reader :class_name, :method_name, :args, :result, :error, :timestamp, :actual_result, :actual_error, :status
11
+ attr_reader :class_name, :method_name, :args, :result, :error, :timestamp, :actual_result, :actual_error, :status, :uuid, :signature
10
12
 
11
- def initialize(class_name:, method_name:, args:, result: nil, error: nil, timestamp: Time.now.iso8601)
13
+ def initialize(class_name:, method_name:, args:, result: nil, error: nil, timestamp: Time.now.iso8601, uuid: SecureRandom.uuid)
12
14
  @class_name = class_name
13
15
  @method_name = method_name
14
16
  @args = args
@@ -16,6 +18,8 @@ module Stable
16
18
  @error = error
17
19
  @timestamp = timestamp
18
20
  @status = :pending
21
+ @uuid = uuid
22
+ @signature = Digest::SHA256.hexdigest("#{class_name}##{method_name}:#{args.to_json}")
19
23
  end
20
24
 
21
25
  def run!
@@ -43,14 +47,16 @@ module Stable
43
47
  end
44
48
 
45
49
  def to_s
46
- description = "#{class_name}##{method_name}(#{args.join(', ')})"
50
+ desc = "#{uuid}/#{signature}"
51
+ call = "#{class_name}##{method_name}(#{args.join(', ')})"
52
+
47
53
  case status
48
54
  when :passed
49
- "PASSED: #{description}"
55
+ "#{desc} P #{call}"
50
56
  when :passed_with_error
51
- "PASSED: #{description} (error)"
57
+ "#{desc} P (error) #{call}"
52
58
  when :failed
53
- lines = ["FAILED: #{description}"]
59
+ lines = ["#{desc} F #{call}"]
54
60
  if actual_error
55
61
  if error
56
62
  lines << " Expected error: #{error['class']}"
@@ -70,7 +76,7 @@ module Stable
70
76
  end
71
77
  lines.join("\n")
72
78
  else
73
- "PENDING: #{description}"
79
+ "#{desc} ? #{call}"
74
80
  end
75
81
  end
76
82
 
@@ -81,7 +87,9 @@ module Stable
81
87
  args: args,
82
88
  result: result,
83
89
  error: error,
84
- timestamp: timestamp
90
+ timestamp: timestamp,
91
+ uuid: uuid,
92
+ signature: signature
85
93
  }.compact.to_json
86
94
  end
87
95
 
@@ -93,7 +101,8 @@ module Stable
93
101
  args: data['args'],
94
102
  result: data['result'],
95
103
  error: data['error'],
96
- timestamp: data['timestamp']
104
+ timestamp: data['timestamp'],
105
+ uuid: data['uuid']
97
106
  )
98
107
  end
99
108
  end
data/lib/stable.rb CHANGED
@@ -37,7 +37,10 @@ module Stable
37
37
  args: args,
38
38
  result: result
39
39
  )
40
- Stable.storage.puts(spec.to_jsonl)
40
+ unless Stable.send(:_spec_exists?, spec.signature)
41
+ Stable.storage.puts(spec.to_jsonl)
42
+ Stable.send(:_recorded_specs) << spec
43
+ end
41
44
  result
42
45
  rescue => e
43
46
  spec = Spec.new(
@@ -50,7 +53,10 @@ module Stable
50
53
  backtrace: e.backtrace
51
54
  }
52
55
  )
53
- Stable.storage.puts(spec.to_jsonl)
56
+ unless Stable.send(:_spec_exists?, spec.signature)
57
+ Stable.storage.puts(spec.to_jsonl)
58
+ Stable.send(:_recorded_specs) << spec
59
+ end
54
60
  raise e
55
61
  end
56
62
  else
@@ -64,5 +70,18 @@ module Stable
64
70
  def verify(record_hash)
65
71
  Spec.from_jsonl(record_hash.to_json).run!
66
72
  end
73
+
74
+ private
75
+
76
+ def _recorded_specs
77
+ @_recorded_specs ||= begin
78
+ return [] unless storage.respond_to?(:path) && File.exist?(storage.path)
79
+ File.foreach(storage.path).map { |line| Spec.from_jsonl(line) }
80
+ end
81
+ end
82
+
83
+ def _spec_exists?(signature)
84
+ _recorded_specs.any? { |spec| spec.signature == signature }
85
+ end
67
86
  end
68
87
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Lunt