chutzen 0.8.4 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aa53613b2fb5208ae0f7824b9617cde550535abaa2306e05d862cad1ae147b2b
4
- data.tar.gz: 5c4b6dd163b1097a14a49d2b39bb94322c1378089784d8b3d8e589d0523d5404
3
+ metadata.gz: d5150871b332694272fd6cd676916cc8b710c13e7f4f47cdfd717b0b5517a398
4
+ data.tar.gz: b47c1877522ef2082e3d507a03c735a817906cd751da307aaa94bf81ae678972
5
5
  SHA512:
6
- metadata.gz: 3195bbf164332b41112fde4ba6a0d88cfcde0cab7adf278daf64d1197bd30f70529af1630fa3fa7e9cc889f99b10bee3253f8ce98bc6ac42cfc2c9ecbeab5e26
7
- data.tar.gz: f871912fa5c9df6eb51124c4a457f9e7e20dd6609e0558ed52505ff8f81f09236c7f8bbb194e1d4319ef3375c221b31025417747b92f375c72a37938911f715d
6
+ metadata.gz: 56cbd867e92a2f6bd9e0cc3ce366e84099f7f5f82b1a46f3126c578692c1af764ccecb96156e93fa893975e6e3aad46d34f3c729166da53939faa9fe9525c5ec
7
+ data.tar.gz: a597dfd4348eddf963d3e815fdb6734a6f545a9c01180524cfff41593fd0e18cdea5f1de0bf5170fc9d3e854c793e81181bff526611e3d523c19066450b0e239
data/README.md CHANGED
@@ -242,3 +242,39 @@ That is why a `Chutzen::Signal` worker will, by default, only process within 30
242
242
  Chutzen::Signal.
243
243
  set(queue: 'chutzen-5-test').
244
244
  perform_async('stop', (Time.now + 10).to_i)
245
+
246
+ ## Mocking
247
+
248
+ Chutzen descriptions can get relatively complex and you may want to use a mock to test logic. You can do this by mocking commands:
249
+
250
+ Chutzen.mocked(
251
+ 'ls' => lamda do
252
+ # Generally you only access stdout and stderr from mocks and return
253
+ # the exit status code.
254
+ stdout.puts("app test")
255
+ 0
256
+ end,
257
+ 'unknown' => lambda do
258
+ # The mock uses the basepath of the executed path to look up the
259
+ # Proc. So /path/to/unknown becomes unknown. Use the 127 exit status
260
+ # to simulate a missing binary.
261
+ 127
262
+ end,
263
+ # The value returned from the Proc is cast to an integer, so this is
264
+ # zero.
265
+ 'zero' => -> {},
266
+ # You have full access to the Chutzen::Command internals, but these
267
+ # mocks may break when internals change.
268
+ 'hack' => lambda do
269
+ @dictionary['width'] = '201'
270
+ 0
271
+ end,
272
+ ) do
273
+ # Any command executed in the same process/thread will now use the mocked
274
+ # commands instead of using Open3 to execute it.
275
+ Command.new(
276
+ { "execute" => "ls" },
277
+ dictionary:,
278
+ work_path:
279
+ ).perform
280
+ end
@@ -58,11 +58,19 @@ module Chutzen
58
58
  def perform
59
59
  return if skip?
60
60
 
61
- result = @execute ? perform_command : self
61
+ result = @execute ? perform_command_or_mock : self
62
62
  merge_remember_into_dictionary
63
63
  result
64
64
  end
65
65
 
66
+ def perform_command_or_mock
67
+ if Chutzen.mock
68
+ perform_mock
69
+ else
70
+ perform_command
71
+ end
72
+ end
73
+
66
74
  def perform_command
67
75
  trace_execution do
68
76
  # We use the STOP signal to instruct Sidekiq to stop reading from the queue and the TERM
@@ -87,6 +95,13 @@ module Chutzen
87
95
  end
88
96
  end
89
97
 
98
+ def perform_mock
99
+ @exit_status = ExitStatus.new(Chutzen.mock.perform(self).to_i)
100
+ verify_exit_status
101
+ merge_output_into_dictionary
102
+ self
103
+ end
104
+
90
105
  # Returns the result expressed by the result section but with its variables
91
106
  # instantiated.
92
107
  def result
@@ -82,7 +82,7 @@ module Chutzen
82
82
  else
83
83
  data.each do |name, value|
84
84
  path = search(value, key)
85
- return (path << name) if path
85
+ return path << name if path
86
86
  end
87
87
  nil
88
88
  end
@@ -91,7 +91,7 @@ module Chutzen
91
91
  def self.search_array(data, key)
92
92
  data.each.with_index do |item, index|
93
93
  path = search(item, key)
94
- return (path << index) if path
94
+ return path << index if path
95
95
  end
96
96
  nil
97
97
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'parslet'
4
+
5
+ module Chutzen
6
+ # Used to mock an exit status normally provided by executing something through Open3.
7
+ ExitStatus = Data.define(:status) do
8
+ def to_i
9
+ status.to_i
10
+ end
11
+
12
+ def success?
13
+ status.zero?
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chutzen
4
+ # Keeps mocked commands and executes Command instances against them.
5
+ class Mock
6
+ attr_reader :mocks
7
+
8
+ def initialize(mocks)
9
+ @mocks = mocks
10
+ end
11
+
12
+ def perform(command)
13
+ name = File.basename(command.to_s.split(' ', 2).first.to_s)
14
+ command.instance_exec(&mocks.fetch(name))
15
+ end
16
+ end
17
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Chutzen
4
- VERSION = '0.8.4'
4
+ VERSION = '0.9.0'
5
5
  end
data/lib/chutzen.rb CHANGED
@@ -9,10 +9,12 @@ module Chutzen
9
9
  autoload :Command, 'chutzen/command'
10
10
  autoload :Demux, 'chutzen/demux'
11
11
  autoload :Dictionary, 'chutzen/dictionary'
12
+ autoload :ExitStatus, 'chutzen/exit_status'
12
13
  autoload :Expression, 'chutzen/expression'
13
14
  autoload :ExpressionParser, 'chutzen/expression_parser'
14
15
  autoload :FailWhen, 'chutzen/fail_when'
15
16
  autoload :Job, 'chutzen/job'
17
+ autoload :Mock, 'chutzen/mock'
16
18
  autoload :Notification, 'chutzen/notification'
17
19
  autoload :RuntimeError, 'chutzen/runtime_error'
18
20
  autoload :Shell, 'chutzen/shell'
@@ -24,9 +26,10 @@ module Chutzen
24
26
  autoload :Worker, 'chutzen/worker'
25
27
 
26
28
  class << self
27
- attr_accessor :sidekiq_queue
29
+ attr_accessor :sidekiq_queue, :mock
28
30
  end
29
31
  self.sidekiq_queue = 'chutzen'
32
+ self.mock = nil
30
33
 
31
34
  # Enqueue a Sidekiq job that will eventually perform the job in the
32
35
  # description.
@@ -90,4 +93,12 @@ module Chutzen
90
93
  expires_in ||= 30
91
94
  (Time.now + expires_in).to_i
92
95
  end
96
+
97
+ # Sets the global mock instance for the duration of the block.
98
+ def self.mocked(**)
99
+ self.mock = Chutzen::Mock.new(**)
100
+ yield
101
+ ensure
102
+ self.mock = nil
103
+ end
93
104
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chutzen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.4
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manfred Stienstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-06 00:00:00.000000000 Z
11
+ date: 2026-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet
@@ -81,12 +81,14 @@ files:
81
81
  - lib/chutzen/command/execution_failed.rb
82
82
  - lib/chutzen/demux.rb
83
83
  - lib/chutzen/dictionary.rb
84
+ - lib/chutzen/exit_status.rb
84
85
  - lib/chutzen/expression.rb
85
86
  - lib/chutzen/expression/lookup_error.rb
86
87
  - lib/chutzen/expression/syntax_error.rb
87
88
  - lib/chutzen/expression_parser.rb
88
89
  - lib/chutzen/fail_when.rb
89
90
  - lib/chutzen/job.rb
91
+ - lib/chutzen/mock.rb
90
92
  - lib/chutzen/notification.rb
91
93
  - lib/chutzen/runtime_error.rb
92
94
  - lib/chutzen/shell.rb
@@ -108,7 +110,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
108
110
  requirements:
109
111
  - - ">="
110
112
  - !ruby/object:Gem::Version
111
- version: '3.1'
113
+ version: '3.2'
112
114
  required_rubygems_version: !ruby/object:Gem::Requirement
113
115
  requirements:
114
116
  - - ">="