exel 1.2.1 → 1.5.2
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 +5 -5
- data/.codeclimate.yml +4 -4
- data/.gitignore +1 -2
- data/.rubocop.yml +23 -14
- data/.rubocop_airbnb.yml +2 -0
- data/.rubocop_todo.yml +1 -13
- data/.travis.yml +26 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +118 -0
- data/Guardfile +1 -0
- data/README.md +96 -31
- data/Rakefile +2 -0
- data/exel.gemspec +7 -7
- data/lib/exel.rb +7 -1
- data/lib/exel/ast_node.rb +6 -10
- data/lib/exel/context.rb +4 -1
- data/lib/exel/deferred_context_value.rb +3 -1
- data/lib/exel/error/job_termination.rb +12 -0
- data/lib/exel/events.rb +6 -0
- data/lib/exel/instruction.rb +5 -2
- data/lib/exel/instruction_node.rb +2 -0
- data/lib/exel/job.rb +8 -4
- data/lib/exel/listen_instruction.rb +2 -0
- data/lib/exel/logging.rb +24 -1
- data/lib/exel/logging/logger_wrapper.rb +31 -0
- data/lib/exel/logging_helper.rb +36 -0
- data/lib/exel/middleware/chain.rb +67 -0
- data/lib/exel/middleware/logging.rb +30 -0
- data/lib/exel/null_instruction.rb +2 -0
- data/lib/exel/processor_helper.rb +9 -1
- data/lib/exel/processors/async_processor.rb +2 -8
- data/lib/exel/processors/run_processor.rb +2 -6
- data/lib/exel/processors/split_processor.rb +15 -10
- data/lib/exel/providers/local_file_provider.rb +9 -6
- data/lib/exel/providers/threaded_async_provider.rb +2 -0
- data/lib/exel/remote_value.rb +11 -0
- data/lib/exel/sequence_node.rb +2 -0
- data/lib/exel/value.rb +2 -0
- data/lib/exel/version.rb +3 -1
- data/spec/exel/ast_node_spec.rb +48 -27
- data/spec/exel/context_spec.rb +77 -77
- data/spec/exel/deferred_context_value_spec.rb +42 -42
- data/spec/exel/events_spec.rb +68 -59
- data/spec/exel/instruction_node_spec.rb +17 -16
- data/spec/exel/instruction_spec.rb +49 -42
- data/spec/exel/job_spec.rb +99 -84
- data/spec/exel/listen_instruction_spec.rb +11 -10
- data/spec/exel/logging/logger_wrapper_spec.rb +93 -0
- data/spec/exel/logging_helper_spec.rb +24 -0
- data/spec/exel/logging_spec.rb +69 -24
- data/spec/exel/middleware/chain_spec.rb +65 -0
- data/spec/exel/middleware/logging_spec.rb +31 -0
- data/spec/exel/middleware_spec.rb +68 -0
- data/spec/exel/null_instruction_spec.rb +4 -4
- data/spec/exel/processors/async_processor_spec.rb +17 -18
- data/spec/exel/processors/run_processor_spec.rb +10 -11
- data/spec/exel/processors/split_processor_spec.rb +99 -74
- data/spec/exel/providers/local_file_provider_spec.rb +26 -28
- data/spec/exel/providers/threaded_async_provider_spec.rb +37 -38
- data/spec/exel/sequence_node_spec.rb +12 -11
- data/spec/exel/value_spec.rb +33 -33
- data/spec/exel_spec.rb +9 -7
- data/spec/integration/integration_spec.rb +3 -1
- data/spec/spec_helper.rb +4 -2
- data/spec/support/integration_test_classes.rb +4 -3
- metadata +37 -48
@@ -1,65 +1,65 @@
|
|
1
|
-
|
2
|
-
describe DeferredContextValue do
|
3
|
-
subject(:deferred_value) { DeferredContextValue.new }
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
|
3
|
+
describe EXEL::DeferredContextValue do
|
4
|
+
subject(:deferred_value) { EXEL::DeferredContextValue.new }
|
7
5
|
|
8
|
-
|
9
|
-
|
6
|
+
describe '.resolve' do
|
7
|
+
subject(:deferred_value) { EXEL::DeferredContextValue.new[:key] }
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
context 'at the top level' do
|
10
|
+
let(:context) { {key: 'value', deferred_value: deferred_value} }
|
11
|
+
|
12
|
+
it 'returns the lookup value from the context' do
|
13
|
+
expect(EXEL::DeferredContextValue.resolve(context[:deferred_value], context)).to eq(context[:key])
|
14
14
|
end
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
context 'in an array' do
|
18
|
+
let(:context) { {key: 'value', array: [1, 2, deferred_value]} }
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
end
|
20
|
+
it 'returns the lookup value from the context' do
|
21
|
+
expect(EXEL::DeferredContextValue.resolve(context[:array], context)).to eq([1, 2, context[:key]])
|
22
22
|
end
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
25
|
+
context 'in a hash' do
|
26
|
+
let(:context) { {key: 'value', hash: {hash_key: deferred_value}} }
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
28
|
+
it 'returns the lookup value from the context' do
|
29
|
+
expect(EXEL::DeferredContextValue.resolve(context[:hash], context)).to eq(hash_key: context[:key])
|
30
30
|
end
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
33
|
+
context 'in a hash nested in an array' do
|
34
|
+
let(:context) { {key: 'value', nested: [{}, {hash_key: deferred_value}]} }
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
end
|
36
|
+
it 'looks up a deferred context value in a hash nested in an array' do
|
37
|
+
expect(EXEL::DeferredContextValue.resolve(context[:nested], context)).to eq([{}, {hash_key: context[:key]}])
|
38
38
|
end
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
-
|
41
|
+
context 'in an array nested in a hash' do
|
42
|
+
let(:context) { {key: 'value', nested: {hash_key: [1, deferred_value]}} }
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
end
|
44
|
+
it 'looks up a deferred context value in an array nested in a hash' do
|
45
|
+
expect(EXEL::DeferredContextValue.resolve(context[:nested], context)).to eq(hash_key: [1, context[:key]])
|
46
46
|
end
|
47
47
|
end
|
48
|
+
end
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
50
|
+
describe '#[]' do
|
51
|
+
it 'stores the given key in the keys attribute' do
|
52
|
+
deferred_value[:top_level_key]['sub_key']
|
53
|
+
expect(deferred_value.keys).to eq([:top_level_key, 'sub_key'])
|
54
54
|
end
|
55
|
+
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
57
|
+
describe '#get' do
|
58
|
+
it 'looks up the value of the keys attribute in the passed-in context' do
|
59
|
+
allow(deferred_value).to receive(:keys).and_return([:top_level_key, 'sub_key'])
|
60
|
+
value = 'example_value'
|
61
|
+
context = EXEL::Context.new(top_level_key: {'sub_key' => value})
|
62
|
+
expect(deferred_value.get(context)).to eq(value)
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
data/spec/exel/events_spec.rb
CHANGED
@@ -1,88 +1,97 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe EXEL::Events do
|
4
|
+
class EventTest
|
5
|
+
include EXEL::Events
|
6
|
+
|
7
|
+
def initialize(context)
|
8
|
+
@context = context
|
5
9
|
end
|
10
|
+
end
|
6
11
|
|
7
|
-
|
8
|
-
let(:event_listener) { double(:event_listener) }
|
9
|
-
let(:context) { EXEL::Context.new(Events::LISTENERS_KEY => {event: [event_listener]}) }
|
12
|
+
subject(:events) { EventTest.new(context) }
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
let(:context) { EXEL::Context.new }
|
14
|
+
let(:event_listener) { double(:event_listener) }
|
15
|
+
let(:context) { EXEL::Context.new(EXEL::Events::LISTENERS_KEY => {event: [event_listener]}) }
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
17
|
+
it 'defines an attr_reader for context on the class it is included in' do
|
18
|
+
expect(events.context).to eq(context)
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
describe '#register_listener' do
|
22
|
+
context 'when no listeners have been defined' do
|
23
|
+
let(:context) { EXEL::Context.new }
|
24
|
+
|
25
|
+
it 'adds a new listener to the context' do
|
26
|
+
events.register_listener(context, :event, event_listener)
|
27
|
+
expect(context[EXEL::Events::LISTENERS_KEY].fetch(:event)).to contain_exactly(event_listener)
|
25
28
|
end
|
26
29
|
end
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
it 'registers multiple listeners for the same event' do
|
32
|
+
new_listener = double(:event_listener2)
|
33
|
+
events.register_listener(context, :event, new_listener)
|
34
|
+
expect(context[EXEL::Events::LISTENERS_KEY].fetch(:event)).to contain_exactly(event_listener, new_listener)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#trigger' do
|
39
|
+
let(:context) { EXEL::Context.new }
|
40
|
+
let(:data) { {foo: 1} }
|
31
41
|
|
32
|
-
|
42
|
+
before { allow(events).to receive(:context).and_return(context) }
|
33
43
|
|
34
|
-
|
35
|
-
|
36
|
-
|
44
|
+
context 'when no events have been registered' do
|
45
|
+
it 'does not trigger anything' do
|
46
|
+
expect(event_listener).not_to receive(:event)
|
37
47
|
|
38
|
-
|
39
|
-
end
|
48
|
+
events.trigger(:event, data)
|
40
49
|
end
|
50
|
+
end
|
41
51
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
52
|
+
context 'with a single listener registered for the event' do
|
53
|
+
before do
|
54
|
+
events.register_listener(context, :event, event_listener)
|
55
|
+
end
|
46
56
|
|
47
|
-
|
48
|
-
|
57
|
+
it 'calls the listener with the context and event data' do
|
58
|
+
expect(event_listener).to receive(:event).with(context, data)
|
49
59
|
|
50
|
-
|
51
|
-
|
60
|
+
events.trigger(:event, data)
|
61
|
+
end
|
52
62
|
|
53
|
-
|
54
|
-
|
63
|
+
it 'passes an empty hash if no data was given' do
|
64
|
+
expect(event_listener).to receive(:event).with(context, {})
|
55
65
|
|
56
|
-
|
57
|
-
end
|
66
|
+
events.trigger(:event)
|
58
67
|
end
|
68
|
+
end
|
59
69
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
70
|
+
context 'with no listeners registered for the event' do
|
71
|
+
before do
|
72
|
+
events.register_listener(context, :other_event, event_listener)
|
73
|
+
end
|
64
74
|
|
65
|
-
|
66
|
-
|
75
|
+
it 'does not trigger anything' do
|
76
|
+
expect(event_listener).not_to receive(:event)
|
67
77
|
|
68
|
-
|
69
|
-
end
|
78
|
+
events.trigger(:event, data)
|
70
79
|
end
|
80
|
+
end
|
71
81
|
|
72
|
-
|
73
|
-
|
82
|
+
context 'with multiple listeners registered for the event' do
|
83
|
+
let(:event_listener2) { double(:event_listener2) }
|
74
84
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
85
|
+
before do
|
86
|
+
events.register_listener(context, :event, event_listener)
|
87
|
+
events.register_listener(context, :event, event_listener2)
|
88
|
+
end
|
79
89
|
|
80
|
-
|
81
|
-
|
82
|
-
|
90
|
+
it 'calls each listener with the context and event data' do
|
91
|
+
expect(event_listener).to receive(:event).with(context, data)
|
92
|
+
expect(event_listener2).to receive(:event).with(context, data)
|
83
93
|
|
84
|
-
|
85
|
-
end
|
94
|
+
events.trigger(:event, data)
|
86
95
|
end
|
87
96
|
end
|
88
97
|
end
|
@@ -1,22 +1,23 @@
|
|
1
|
-
|
2
|
-
describe InstructionNode do
|
3
|
-
let(:context) { {} }
|
4
|
-
let(:instruction) { instance_double(Instruction, execute: nil) }
|
5
|
-
let(:child) { instance_double(ASTNode) }
|
6
|
-
subject(:node) { InstructionNode.new(instruction, [child]) }
|
1
|
+
# frozen_string_literal: true
|
7
2
|
|
8
|
-
|
3
|
+
describe EXEL::InstructionNode do
|
4
|
+
subject(:node) { EXEL::InstructionNode.new(instruction, children: [child]) }
|
9
5
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
node.run(context)
|
14
|
-
end
|
6
|
+
let(:context) { {} }
|
7
|
+
let(:instruction) { instance_double(EXEL::Instruction, execute: nil) }
|
8
|
+
let(:child) { instance_double(EXEL::ASTNode) }
|
15
9
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
it { is_expected.to be_kind_of(EXEL::ASTNode) }
|
11
|
+
|
12
|
+
describe '#run' do
|
13
|
+
it 'only executes the instruction' do
|
14
|
+
expect(instruction).to receive(:execute).with(context).once
|
15
|
+
node.run(context)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'does not run it`s children' do
|
19
|
+
expect(child).not_to receive(:run)
|
20
|
+
node.run(context)
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
@@ -1,57 +1,64 @@
|
|
1
|
-
|
2
|
-
describe Instruction do
|
3
|
-
subject(:instruction) { EXEL::Instruction.new(processor_class, args) }
|
4
|
-
let(:processor_class) { double(:processor_class, new: processor_instance) }
|
5
|
-
let(:processor_instance) { double(:processor_instance, process: nil) }
|
6
|
-
let(:args) { {arg1: 'arg_value1', arg2: {}} }
|
7
|
-
let(:context) { {context_key: 'context_value'} }
|
8
|
-
|
9
|
-
describe '#execute' do
|
10
|
-
it 'calls process on an instance of the processor class' do
|
11
|
-
expect(processor_class).to receive(:new).and_return(processor_instance)
|
12
|
-
expect(processor_instance).to receive(:process)
|
1
|
+
# frozen_string_literal: true
|
13
2
|
|
14
|
-
|
15
|
-
|
3
|
+
describe EXEL::Instruction do
|
4
|
+
subject(:instruction) { EXEL::Instruction.new(processor_class, args) }
|
16
5
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
6
|
+
let(:processor_class) { double(:processor_class, new: processor_instance) }
|
7
|
+
let(:processor_instance) { double(:processor_instance, process: nil) }
|
8
|
+
let(:args) { {arg1: 'arg_value1', arg2: {}} }
|
9
|
+
let(:context) { {context_key: 'context_value'} }
|
22
10
|
|
23
|
-
|
24
|
-
|
11
|
+
describe '#execute' do
|
12
|
+
it 'calls process on an instance of the processor class' do
|
13
|
+
expect(processor_class).to receive(:new).and_return(processor_instance)
|
14
|
+
expect(processor_instance).to receive(:process)
|
25
15
|
|
26
|
-
|
27
|
-
|
28
|
-
|
16
|
+
instruction.execute(context)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'invokes the middleware chain' do
|
20
|
+
expect(EXEL.middleware).to receive(:invoke).with(processor_class, context, args)
|
21
|
+
instruction.execute(context)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'does not pass a copy of the context' do
|
25
|
+
allow(processor_class).to receive(:new) do |context_arg|
|
26
|
+
expect(context_arg).to be(context)
|
27
|
+
processor_instance
|
29
28
|
end
|
30
29
|
|
31
|
-
context
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
instruction.execute(context)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'adds args to the context' do
|
34
|
+
instruction.execute(context)
|
35
|
+
expect(context.keys).to include(*args.keys)
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'with args' do
|
39
|
+
it 'passes the args to the processor' do
|
40
|
+
expect(processor_class).to receive(:new).with(hash_including(args))
|
41
|
+
instruction.execute(context)
|
36
42
|
end
|
43
|
+
end
|
37
44
|
|
38
|
-
|
39
|
-
|
45
|
+
context 'without args' do
|
46
|
+
let(:args) { nil }
|
40
47
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
48
|
+
it 'passes only the context to the processor' do
|
49
|
+
expect(processor_class).to receive(:new).with(context)
|
50
|
+
instruction.execute(context)
|
45
51
|
end
|
52
|
+
end
|
46
53
|
|
47
|
-
|
48
|
-
|
49
|
-
subject(:instruction) { EXEL::Instruction.new(processor_class, args, subtree) }
|
54
|
+
context 'with a subtree' do
|
55
|
+
subject(:instruction) { EXEL::Instruction.new(processor_class, args, subtree: subtree) }
|
50
56
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
57
|
+
let(:subtree) { double(:subtree) }
|
58
|
+
|
59
|
+
it 'passes the subtree to the processor' do
|
60
|
+
expect(processor_instance).to receive(:process).with(subtree)
|
61
|
+
instruction.execute(context)
|
55
62
|
end
|
56
63
|
end
|
57
64
|
end
|
data/spec/exel/job_spec.rb
CHANGED
@@ -1,104 +1,119 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe EXEL::Job do
|
4
|
+
describe '.define' do
|
5
|
+
let(:ast) { instance_double(EXEL::SequenceNode, run: nil, start: nil) }
|
6
|
+
let(:block) { proc {} }
|
7
|
+
|
8
|
+
after { EXEL::Job.registry.clear }
|
9
|
+
|
10
|
+
it 'registers job definitions' do
|
11
|
+
EXEL::Job.define :test_job, &block
|
12
|
+
expect(EXEL::Job.registry[:test_job]).to eq(block)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'raises an exception if a job name is already in use' do
|
16
|
+
EXEL::Job.define :test_job, &block
|
17
|
+
expect { EXEL::Job.define :test_job, &block }.to raise_error 'Job :test_job is already defined'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.run' do
|
22
|
+
let(:ast) { instance_double(EXEL::SequenceNode, run: nil, start: nil) }
|
23
|
+
let(:context) { instance_double(EXEL::Context) }
|
6
24
|
|
7
|
-
|
25
|
+
context 'with a string of DSL code' do
|
26
|
+
it 'parses the code' do
|
27
|
+
dsl_code = 'code'
|
28
|
+
expect(EXEL::Job::Parser).to receive(:parse).with(dsl_code).and_return(ast)
|
29
|
+
EXEL::Job.run(dsl_code, context)
|
30
|
+
end
|
8
31
|
|
9
|
-
it '
|
10
|
-
Job.
|
11
|
-
expect(
|
32
|
+
it 'runs the AST returned by the parser' do
|
33
|
+
allow(EXEL::Job::Parser).to receive(:parse).and_return(ast)
|
34
|
+
expect(ast).to receive(:start).with(context)
|
35
|
+
EXEL::Job.run('code', context)
|
12
36
|
end
|
13
37
|
|
14
|
-
it '
|
15
|
-
Job.
|
16
|
-
|
38
|
+
it 'returns the context' do
|
39
|
+
allow(EXEL::Job::Parser).to receive(:parse).and_return(ast)
|
40
|
+
result = EXEL::Job.run('code', context)
|
41
|
+
expect(result).to be(context)
|
17
42
|
end
|
18
43
|
end
|
19
44
|
|
20
|
-
|
21
|
-
|
22
|
-
|
45
|
+
context 'with a job name' do
|
46
|
+
context 'of a defined job' do
|
47
|
+
let(:block) { proc {} }
|
23
48
|
|
24
|
-
|
25
|
-
|
26
|
-
dsl_code = 'code'
|
27
|
-
expect(Job::Parser).to receive(:parse).with(dsl_code).and_return(ast)
|
28
|
-
Job.run(dsl_code, context)
|
49
|
+
before do
|
50
|
+
allow(EXEL::Job).to receive(:registry).and_return(test_job: block)
|
29
51
|
end
|
30
52
|
|
31
|
-
it 'runs the
|
32
|
-
|
53
|
+
it 'runs the job' do
|
54
|
+
expect(EXEL::Job::Parser).to receive(:parse).with(block).and_return(ast)
|
33
55
|
expect(ast).to receive(:start).with(context)
|
34
|
-
Job.run(
|
56
|
+
EXEL::Job.run(:test_job, context)
|
35
57
|
end
|
36
|
-
end
|
37
|
-
|
38
|
-
context 'with a job name' do
|
39
|
-
context 'of a defined job' do
|
40
|
-
let(:block) { proc {} }
|
41
58
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
it 'runs the job' do
|
47
|
-
expect(Job::Parser).to receive(:parse).with(block).and_return(ast)
|
48
|
-
expect(ast).to receive(:start).with(context)
|
49
|
-
Job.run(:test_job, context)
|
50
|
-
end
|
59
|
+
it 'returns the context' do
|
60
|
+
result = EXEL::Job.run(:test_job, context)
|
61
|
+
expect(result).to be(context)
|
51
62
|
end
|
63
|
+
end
|
52
64
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
65
|
+
context 'of a undefined job' do
|
66
|
+
it 'returns nil' do
|
67
|
+
expect { EXEL::Job.run(:test_job, context) }.to raise_error('Job "test_job" not found')
|
57
68
|
end
|
58
69
|
end
|
59
70
|
end
|
71
|
+
end
|
60
72
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
73
|
+
describe 'mutation of arguments' do
|
74
|
+
module EXEL
|
75
|
+
module Processors
|
76
|
+
class TestProcessor
|
77
|
+
def initialize(context)
|
78
|
+
context[:array] << context[:arg]
|
79
|
+
end
|
66
80
|
|
67
|
-
|
81
|
+
def process(_callback)
|
82
|
+
end
|
68
83
|
end
|
69
84
|
end
|
85
|
+
end
|
70
86
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
87
|
+
it 'does not persist between runs' do
|
88
|
+
EXEL::Job.define :test do
|
89
|
+
process with: EXEL::Processors::TestProcessor, array: [], arg: context[:value]
|
90
|
+
end
|
75
91
|
|
76
|
-
|
77
|
-
|
78
|
-
|
92
|
+
context = EXEL::Context.new(value: 1)
|
93
|
+
EXEL::Job.run(:test, context)
|
94
|
+
expect(context[:array]).to eq([1])
|
79
95
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
end
|
96
|
+
context = EXEL::Context.new(value: 2)
|
97
|
+
EXEL::Job.run(:test, context)
|
98
|
+
expect(context[:array]).to eq([2])
|
84
99
|
end
|
85
100
|
end
|
86
101
|
|
87
|
-
describe Job::Parser do
|
88
|
-
let(:parser) { Job::Parser.new }
|
89
|
-
let(:ast) { instance_double(SequenceNode, run: nil) }
|
102
|
+
describe EXEL::Job::Parser do
|
103
|
+
let(:parser) { EXEL::Job::Parser.new }
|
104
|
+
let(:ast) { instance_double(EXEL::SequenceNode, run: nil) }
|
90
105
|
|
91
106
|
describe '#initialize' do
|
92
107
|
it 'initializes a sequence node' do
|
93
|
-
expect(parser.ast).to be_kind_of(SequenceNode)
|
108
|
+
expect(parser.ast).to be_kind_of(EXEL::SequenceNode)
|
94
109
|
end
|
95
110
|
end
|
96
111
|
|
97
112
|
describe '.parse' do
|
98
|
-
let(:parser) { instance_double(Job::Parser, ast: ast, instance_eval: nil) }
|
113
|
+
let(:parser) { instance_double(EXEL::Job::Parser, ast: ast, instance_eval: nil) }
|
99
114
|
|
100
115
|
before do
|
101
|
-
allow(Job::Parser).to receive(:new).and_return(parser)
|
116
|
+
allow(EXEL::Job::Parser).to receive(:new).and_return(parser)
|
102
117
|
end
|
103
118
|
|
104
119
|
context 'given DSL code as a proc' do
|
@@ -108,7 +123,7 @@ module EXEL
|
|
108
123
|
expect(block).to eq(dsl_proc)
|
109
124
|
end
|
110
125
|
|
111
|
-
Job::Parser.parse(dsl_proc)
|
126
|
+
EXEL::Job::Parser.parse(dsl_proc)
|
112
127
|
end
|
113
128
|
end
|
114
129
|
|
@@ -117,12 +132,12 @@ module EXEL
|
|
117
132
|
dsl_code = 'code'
|
118
133
|
expect(parser).to receive(:instance_eval).with(dsl_code)
|
119
134
|
|
120
|
-
Job::Parser.parse(dsl_code)
|
135
|
+
EXEL::Job::Parser.parse(dsl_code)
|
121
136
|
end
|
122
137
|
end
|
123
138
|
|
124
139
|
it 'returns the parsed AST' do
|
125
|
-
expect(Job::Parser.parse(proc {})).to eq(ast)
|
140
|
+
expect(EXEL::Job::Parser.parse(proc {})).to eq(ast)
|
126
141
|
end
|
127
142
|
end
|
128
143
|
|
@@ -130,18 +145,18 @@ module EXEL
|
|
130
145
|
let(:block) { proc {} }
|
131
146
|
let(:processor_class) { class_double(Class) }
|
132
147
|
|
133
|
-
before { allow(Job::Parser).to receive(:parse).and_return(ast) }
|
148
|
+
before { allow(EXEL::Job::Parser).to receive(:parse).and_return(ast) }
|
134
149
|
|
135
150
|
context 'without a block' do
|
136
151
|
it 'creates a process instruction' do
|
137
|
-
expect(Instruction).to receive(:new).with(processor_class, {arg1: 'arg1_value'}, nil)
|
152
|
+
expect(EXEL::Instruction).to receive(:new).with(processor_class, {arg1: 'arg1_value'}, subtree: nil)
|
138
153
|
|
139
154
|
parser.process with: processor_class, arg1: 'arg1_value'
|
140
155
|
end
|
141
156
|
|
142
157
|
it 'appends an instruction node to the AST with no children' do
|
143
158
|
expect(parser.ast).to receive(:add_child) do |node|
|
144
|
-
expect(node).to be_a_kind_of(InstructionNode)
|
159
|
+
expect(node).to be_a_kind_of(EXEL::InstructionNode)
|
145
160
|
expect(node.children).to eq([])
|
146
161
|
end
|
147
162
|
|
@@ -151,15 +166,15 @@ module EXEL
|
|
151
166
|
|
152
167
|
context 'with a block' do
|
153
168
|
it 'passes the parsed subtree to the instruction' do
|
154
|
-
expect(Job::Parser).to receive(:parse).with(block).and_return(ast)
|
155
|
-
expect(Instruction).to receive(:new).with(processor_class, {arg1: 'arg1_value'}, ast)
|
169
|
+
expect(EXEL::Job::Parser).to receive(:parse).with(block).and_return(ast)
|
170
|
+
expect(EXEL::Instruction).to receive(:new).with(processor_class, {arg1: 'arg1_value'}, subtree: ast)
|
156
171
|
|
157
172
|
parser.process with: processor_class, arg1: 'arg1_value', &block
|
158
173
|
end
|
159
174
|
|
160
175
|
it 'appends an instruction node to the AST with the parsed block as its subtree' do
|
161
176
|
expect(parser.ast).to receive(:add_child) do |node|
|
162
|
-
expect(node).to be_a_kind_of(InstructionNode)
|
177
|
+
expect(node).to be_a_kind_of(EXEL::InstructionNode)
|
163
178
|
expect(node.children).to eq([ast])
|
164
179
|
end
|
165
180
|
|
@@ -169,30 +184,30 @@ module EXEL
|
|
169
184
|
end
|
170
185
|
|
171
186
|
[
|
172
|
-
|
173
|
-
|
174
|
-
|
187
|
+
{method: :async, processor: EXEL::Processors::AsyncProcessor},
|
188
|
+
{method: :split, processor: EXEL::Processors::SplitProcessor},
|
189
|
+
{method: :run, processor: EXEL::Processors::RunProcessor},
|
175
190
|
].each do |data|
|
176
191
|
describe "##{data[:method]}" do
|
177
192
|
before do
|
178
|
-
allow(Job::Parser).to receive(:parse).and_return(ast)
|
193
|
+
allow(EXEL::Job::Parser).to receive(:parse).and_return(ast)
|
179
194
|
end
|
180
195
|
|
181
196
|
it "creates a #{data[:method]} instruction" do
|
182
|
-
expect(Instruction).to receive(:new).with(data[:processor], {arg1: 'arg1_value'}, ast)
|
197
|
+
expect(EXEL::Instruction).to receive(:new).with(data[:processor], {arg1: 'arg1_value'}, subtree: ast)
|
183
198
|
parser.send(data[:method], arg1: 'arg1_value') {}
|
184
199
|
end
|
185
200
|
|
186
201
|
it 'parses the block given' do
|
187
202
|
block = -> {}
|
188
|
-
expect(Job::Parser).to receive(:parse).with(block).and_return(ast)
|
203
|
+
expect(EXEL::Job::Parser).to receive(:parse).with(block).and_return(ast)
|
189
204
|
|
190
205
|
parser.send(data[:method], &block)
|
191
206
|
end
|
192
207
|
|
193
208
|
it 'adds parsed subtree and instruction to the AST' do
|
194
209
|
expect(parser.ast).to receive(:add_child) do |node|
|
195
|
-
expect(node).to be_a_kind_of(InstructionNode)
|
210
|
+
expect(node).to be_a_kind_of(EXEL::InstructionNode)
|
196
211
|
expect(node.children).to eq([ast])
|
197
212
|
end
|
198
213
|
|
@@ -203,7 +218,7 @@ module EXEL
|
|
203
218
|
|
204
219
|
describe '#context' do
|
205
220
|
it 'returns a DeferredContextValue' do
|
206
|
-
expect(parser.context).to be_a_kind_of(DeferredContextValue)
|
221
|
+
expect(parser.context).to be_a_kind_of(EXEL::DeferredContextValue)
|
207
222
|
end
|
208
223
|
end
|
209
224
|
|
@@ -211,15 +226,15 @@ module EXEL
|
|
211
226
|
let(:listener_class) { class_double(Class) }
|
212
227
|
|
213
228
|
it 'creates a listen instruction' do
|
214
|
-
expect(ListenInstruction).to receive(:new).with(:event, listener_class)
|
229
|
+
expect(EXEL::ListenInstruction).to receive(:new).with(:event, listener_class)
|
215
230
|
parser.listen for: :event, with: listener_class
|
216
231
|
end
|
217
232
|
|
218
233
|
it 'adds an InstructionNode containing the listen instruction' do
|
219
234
|
parser.listen for: :event, with: listener_class
|
220
235
|
node = parser.ast.children.first
|
221
|
-
expect(node).to be_a_kind_of(InstructionNode)
|
222
|
-
expect(node.instruction).to be_a_kind_of(ListenInstruction)
|
236
|
+
expect(node).to be_a_kind_of(EXEL::InstructionNode)
|
237
|
+
expect(node.instruction).to be_a_kind_of(EXEL::ListenInstruction)
|
223
238
|
end
|
224
239
|
end
|
225
240
|
end
|