producer-core 0.1.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 (65) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile +5 -0
  3. data/Guardfile +11 -0
  4. data/LICENSE +30 -0
  5. data/Rakefile +13 -0
  6. data/bin/producer +5 -0
  7. data/features/actions/echo.feature +12 -0
  8. data/features/actions/sh.feature +39 -0
  9. data/features/cli/usage.feature +9 -0
  10. data/features/recipes/env.feature +9 -0
  11. data/features/recipes/evaluation.feature +10 -0
  12. data/features/recipes/source.feature +16 -0
  13. data/features/recipes/target.feature +12 -0
  14. data/features/steps/recipe_steps.rb +7 -0
  15. data/features/support/env.rb +0 -0
  16. data/features/support/env_aruba.rb +16 -0
  17. data/features/support/env_cucumber-doc_string.rb +23 -0
  18. data/features/support/ssh.rb +106 -0
  19. data/features/tasks/condition.feature +14 -0
  20. data/features/tasks/evaluation.feature +12 -0
  21. data/features/tests/has_env.feature +32 -0
  22. data/lib/producer/core/action.rb +12 -0
  23. data/lib/producer/core/actions/echo.rb +11 -0
  24. data/lib/producer/core/actions/shell_command.rb +11 -0
  25. data/lib/producer/core/cli.rb +43 -0
  26. data/lib/producer/core/condition/dsl.rb +35 -0
  27. data/lib/producer/core/condition.rb +26 -0
  28. data/lib/producer/core/env.rb +21 -0
  29. data/lib/producer/core/errors.rb +7 -0
  30. data/lib/producer/core/interpreter.rb +13 -0
  31. data/lib/producer/core/recipe/dsl.rb +48 -0
  32. data/lib/producer/core/recipe.rb +15 -0
  33. data/lib/producer/core/remote/environment.rb +27 -0
  34. data/lib/producer/core/remote.rb +40 -0
  35. data/lib/producer/core/task/dsl.rb +42 -0
  36. data/lib/producer/core/task.rb +21 -0
  37. data/lib/producer/core/test.rb +12 -0
  38. data/lib/producer/core/tests/has_env.rb +11 -0
  39. data/lib/producer/core/version.rb +5 -0
  40. data/lib/producer/core.rb +22 -0
  41. data/producer-core.gemspec +28 -0
  42. data/spec/fixtures/recipes/empty.rb +1 -0
  43. data/spec/fixtures/recipes/throw.rb +1 -0
  44. data/spec/producer/core/action_spec.rb +21 -0
  45. data/spec/producer/core/actions/echo_spec.rb +21 -0
  46. data/spec/producer/core/actions/shell_command_spec.rb +27 -0
  47. data/spec/producer/core/cli_spec.rb +102 -0
  48. data/spec/producer/core/condition/dsl_spec.rb +102 -0
  49. data/spec/producer/core/condition_spec.rb +96 -0
  50. data/spec/producer/core/env_spec.rb +54 -0
  51. data/spec/producer/core/interpreter_spec.rb +41 -0
  52. data/spec/producer/core/recipe/dsl_spec.rb +131 -0
  53. data/spec/producer/core/recipe_spec.rb +43 -0
  54. data/spec/producer/core/remote/environment_spec.rb +34 -0
  55. data/spec/producer/core/remote_spec.rb +87 -0
  56. data/spec/producer/core/task/dsl_spec.rb +131 -0
  57. data/spec/producer/core/task_spec.rb +91 -0
  58. data/spec/producer/core/test_spec.rb +30 -0
  59. data/spec/producer/core/tests/has_env_spec.rb +41 -0
  60. data/spec/spec_helper.rb +16 -0
  61. data/spec/support/exit_helpers.rb +6 -0
  62. data/spec/support/fixtures_helpers.rb +7 -0
  63. data/spec/support/net_ssh_story_helpers.rb +17 -0
  64. data/spec/support/tests_helpers.rb +9 -0
  65. metadata +230 -0
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Recipe::DSL do
5
+ include FixturesHelpers
6
+
7
+ let(:code) { proc { } }
8
+ let(:env) { double('env').as_null_object }
9
+ subject(:dsl) { Recipe::DSL.new &code }
10
+
11
+ describe '.evaluate' do
12
+ let(:code) { 'nil' }
13
+
14
+ it 'builds a new DSL sandbox with given code' do
15
+ expect(Recipe::DSL).to receive(:new).once.with(code).and_call_original
16
+ Recipe::DSL.evaluate(code, env)
17
+ end
18
+
19
+ it 'evaluates the DSL sandbox code with given environment' do
20
+ dsl = double('dsl').as_null_object
21
+ allow(Recipe::DSL).to receive(:new) { dsl }
22
+ expect(dsl).to receive(:evaluate).with(env)
23
+ Recipe::DSL.evaluate(code, env)
24
+ end
25
+
26
+ it 'builds a recipe with evaluated tasks' do
27
+ dsl = Recipe::DSL.new('task(:some_task) { }')
28
+ allow(Recipe::DSL).to receive(:new) { dsl }
29
+ expect(Recipe).to receive(:new).with(dsl.tasks)
30
+ Recipe::DSL.evaluate(code, env)
31
+ end
32
+
33
+ it 'returns the recipe' do
34
+ recipe = double('recipe').as_null_object
35
+ allow(Recipe).to receive(:new) { recipe }
36
+ expect(Recipe::DSL.evaluate(code, env)).to be recipe
37
+ end
38
+ end
39
+
40
+ describe '#initialize' do
41
+ it 'assigns no task' do
42
+ expect(dsl.instance_eval { @tasks }).to be_empty
43
+ end
44
+
45
+ context 'when a string of code is given as argument' do
46
+ let(:code) { 'some_code' }
47
+ subject(:dsl) { Recipe::DSL.new(code) }
48
+
49
+ it 'assigns the string of code' do
50
+ expect(dsl.instance_eval { @code }).to eq code
51
+ end
52
+ end
53
+
54
+ context 'when a code block is given as argument' do
55
+ it 'assigns the code block' do
56
+ expect(dsl.instance_eval { @block }).to be code
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '#tasks' do
62
+ let(:code) { proc { task(:some_task) { } } }
63
+
64
+ it 'returns registered tasks' do
65
+ dsl.evaluate(env)
66
+ expect(dsl.tasks[0].name).to eq :some_task
67
+ end
68
+ end
69
+
70
+ describe '#evaluate' do
71
+ it 'evaluates its code' do
72
+ dsl = Recipe::DSL.new { throw :recipe_code }
73
+ expect { dsl.evaluate(env) }.to throw_symbol :recipe_code
74
+ end
75
+
76
+ it 'returns itself' do
77
+ expect(dsl.evaluate(env)).to eq dsl
78
+ end
79
+ end
80
+
81
+ context 'DSL specific methods' do
82
+ subject(:dsl) { Recipe::DSL.new(&code).evaluate(env) }
83
+
84
+ describe '#env' do
85
+ let(:code) { proc { env.some_message } }
86
+
87
+ it 'returns the current environment' do
88
+ expect(env).to receive(:some_message)
89
+ dsl.evaluate(env)
90
+ end
91
+ end
92
+
93
+ describe '#source' do
94
+ let(:filepath) { fixture_path_for 'recipes/throw' }
95
+ let(:code) { "source '#{filepath}'" }
96
+ subject(:dsl) { Recipe::DSL.new code }
97
+
98
+ it 'sources the recipe given as argument' do
99
+ expect { dsl.evaluate(env) }.to throw_symbol :recipe_code
100
+ end
101
+ end
102
+
103
+ describe '#target' do
104
+ let(:code) { proc { target 'some_host.example' } }
105
+
106
+ it 'registers the target host in the env' do
107
+ expect(env).to receive(:target=).with('some_host.example')
108
+ dsl
109
+ end
110
+ end
111
+
112
+ describe '#task' do
113
+ let(:code) { proc { task(:some_task) { :some_value } } }
114
+
115
+ it 'builds a new evaluated task' do
116
+ expect(Task)
117
+ .to receive(:evaluate).with(:some_task, env) do |&block|
118
+ expect(block.call).to eq :some_value
119
+ end
120
+ dsl
121
+ end
122
+
123
+ it 'registers the new task' do
124
+ task = double('task').as_null_object
125
+ allow(Task).to receive(:new) { task }
126
+ expect(dsl.tasks).to include(task)
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Recipe do
5
+ include FixturesHelpers
6
+
7
+ subject(:recipe) { Recipe.new }
8
+
9
+ describe '.evaluate_from_file' do
10
+ let(:env) { double('env') }
11
+ let(:filepath) { fixture_path_for 'recipes/empty.rb' }
12
+
13
+ it 'delegates to DSL.evaluate with the recipe file content' do
14
+ expect(Recipe::DSL)
15
+ .to receive(:evaluate).with(File.read(filepath), env)
16
+ Recipe.evaluate_from_file(filepath, env)
17
+ end
18
+
19
+ it 'returns the evaluated recipe' do
20
+ recipe = double('recipe')
21
+ allow(Recipe::DSL).to receive(:evaluate) { recipe }
22
+ expect(Recipe.evaluate_from_file(filepath, env)).to be recipe
23
+ end
24
+ end
25
+
26
+ describe '#initialize' do
27
+ context 'without arguments' do
28
+ it 'assigns no task' do
29
+ expect(recipe.tasks).to be_empty
30
+ end
31
+ end
32
+
33
+ context 'when tasks are given as argument' do
34
+ let(:tasks) { [Task.new(:some_task)] }
35
+ let(:recipe) { Recipe.new(tasks) }
36
+
37
+ it 'assigns the tasks' do
38
+ expect(recipe.tasks).to eq tasks
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Remote::Environment do
5
+ let(:variables) { { 'FOO' => 'bar', 'BAZ' => 'qux' } }
6
+ subject(:environment) { Remote::Environment.new(variables) }
7
+
8
+ describe '#initialize' do
9
+ context 'when a hash is given' do
10
+ it 'assigns the key/value pairs' do
11
+ expect(environment.instance_eval { @variables }).to eq variables
12
+ end
13
+ end
14
+
15
+ context 'when a string is given' do
16
+ subject(:environment) { Remote::Environment.new("FOO=bar\nBAZ=qux") }
17
+
18
+ it 'assigns the key/value pairs' do
19
+ expect(environment.instance_eval { @variables }).to eq variables
20
+ end
21
+ end
22
+ end
23
+
24
+ describe '#has_key?' do
25
+ let(:key) { 'SOME_KEY' }
26
+
27
+ it 'forwards the message to @variables' do
28
+ expect(environment.instance_eval { @variables })
29
+ .to receive(:has_key?).with(key)
30
+ environment.has_key? key
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Remote do
5
+ let(:hostname) { 'some_host.example' }
6
+ subject(:remote) { Remote.new(hostname) }
7
+
8
+ describe '#hostname' do
9
+ it 'returns the assignated hostname' do
10
+ expect(remote.hostname).to be hostname
11
+ end
12
+ end
13
+
14
+ describe '#session' do
15
+ it 'builds a new SSH session to the remote host' do
16
+ expect(Net::SSH).to receive(:start).with(hostname, Etc.getlogin)
17
+ remote.session
18
+ end
19
+
20
+ it 'returns the session' do
21
+ session = double('SSH session')
22
+ allow(Net::SSH).to receive(:start) { session }
23
+ expect(remote.session).to eq session
24
+ end
25
+
26
+ it 'memoizes the session' do
27
+ allow(Net::SSH).to receive(:start) { Object.new }
28
+ expect(remote.session).to be remote.session
29
+ end
30
+ end
31
+
32
+ describe '#execute', :ssh do
33
+ let(:arguments) { 'some remote command' }
34
+ let(:command) { "echo #{arguments}" }
35
+
36
+ it 'executes the given command in a new channel' do
37
+ story_with_new_channel do |ch|
38
+ ch.sends_exec command
39
+ ch.gets_data arguments
40
+ end
41
+ remote.execute command
42
+ expect(story_completed?).to be
43
+ end
44
+
45
+ it 'returns the output' do
46
+ story_with_new_channel do |ch|
47
+ ch.sends_exec command
48
+ ch.gets_data arguments
49
+ end
50
+ expect(remote.execute(command)).to eq arguments
51
+ end
52
+
53
+ it 'raises an exception when the exit status code is not 0' do
54
+ story_with_new_channel do |ch|
55
+ ch.sends_exec command
56
+ ch.gets_data arguments
57
+ ch.gets_exit_status 1
58
+ end
59
+ expect { remote.execute(command) }
60
+ .to raise_error(RemoteCommandExecutionError)
61
+ end
62
+ end
63
+
64
+ describe '#environment', :ssh do
65
+ let(:command) { 'env' }
66
+ let(:output) { "FOO=bar\nBAZ=qux" }
67
+
68
+ before do
69
+ story_with_new_channel do |ch|
70
+ ch.sends_exec command
71
+ ch.gets_data output
72
+ end
73
+ end
74
+
75
+ it 'builds a remote environment with the result of `env` command' do
76
+ expect(Remote::Environment).to receive(:new).with(output)
77
+ remote.environment
78
+ end
79
+
80
+ it 'returns the environment' do
81
+ environment = double('environment')
82
+ allow(Remote::Environment).to receive(:new) { environment }
83
+ expect(remote.environment).to be environment
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Task::DSL do
5
+ let(:block) { proc { } }
6
+ let(:env) { double('env') }
7
+ subject(:dsl) { Task::DSL.new &block }
8
+
9
+ %w[echo sh].each do |action|
10
+ it "has `#{action}' action defined" do
11
+ expect(dsl).to respond_to action.to_sym
12
+ end
13
+ end
14
+
15
+ describe '.evaluate' do
16
+ let(:name) { :some_task }
17
+
18
+ it 'builds a new DSL sandbox with given code' do
19
+ expect(Task::DSL).to receive(:new).once.with(&block).and_call_original
20
+ Task::DSL.evaluate(name, env, &block)
21
+ end
22
+
23
+ it 'evaluates the DSL sandbox code with given environment' do
24
+ dsl = double('dsl').as_null_object
25
+ allow(Task::DSL).to receive(:new) { dsl }
26
+ expect(dsl).to receive(:evaluate).with(env)
27
+ Task::DSL.evaluate(name, env, &block)
28
+ end
29
+
30
+ it 'builds a task with its name, actions and condition' do
31
+ dsl = double('dsl').as_null_object
32
+ allow(Task::DSL).to receive(:new) { dsl }
33
+ allow(dsl).to receive(:actions) { [:some_action] }
34
+ allow(dsl).to receive(:condition) { :some_condition }
35
+ expect(Task)
36
+ .to receive(:new).with(:some_task, [:some_action], :some_condition)
37
+ Task::DSL.evaluate(name, env, &block)
38
+ end
39
+
40
+ it 'returns the task' do
41
+ task = double('task')
42
+ allow(Task).to receive(:new) { task }
43
+ expect(Task::DSL.evaluate(name, env, &block)).to be task
44
+ end
45
+ end
46
+
47
+ describe '.define_action' do
48
+ it 'defines a new action keyword' do
49
+ Task::DSL.define_action(:some_action, Object)
50
+ expect(dsl).to respond_to :some_action
51
+ end
52
+ end
53
+
54
+ describe '#initialize' do
55
+ it 'assigns no action' do
56
+ expect(dsl.actions).to be_empty
57
+ end
58
+
59
+ it 'assigns true as the condition' do
60
+ expect(dsl.instance_eval { @condition }).to be_true
61
+ end
62
+ end
63
+
64
+ describe '#actions' do
65
+ it 'returns the assigned actions' do
66
+ dsl.instance_eval { @actions = [:some_action] }
67
+ expect(dsl.actions).to eq [:some_action]
68
+ end
69
+ end
70
+
71
+ describe '#evaluate' do
72
+ let(:block) { proc { throw :task_code } }
73
+
74
+ it 'evaluates its code' do
75
+ expect { dsl.evaluate(env) }
76
+ .to throw_symbol :task_code
77
+ end
78
+
79
+ context 'when a defined keyword action is called' do
80
+ let(:some_action_class) { Class.new(Action) }
81
+ let(:block) { proc { some_action } }
82
+
83
+ before do
84
+ Task::DSL.define_action(:some_action, some_action_class)
85
+ dsl.evaluate(env)
86
+ end
87
+
88
+ it 'registers the action' do
89
+ expect(dsl.actions.first).to be_an Action
90
+ end
91
+
92
+ it 'provides the env to the registered action' do
93
+ expect(dsl.actions.first.env).to eq env
94
+ end
95
+ end
96
+ end
97
+
98
+ context 'DSL specific methods' do
99
+ subject(:dsl) { Task::DSL.new(&block).evaluate(env) }
100
+
101
+ describe '#condition' do
102
+ context 'when a block is given' do
103
+ let(:block) { proc { condition { :some_value } } }
104
+
105
+ it 'builds a new evaluated condition' do
106
+ expect(Condition)
107
+ .to receive(:evaluate).with(env) do |&b|
108
+ expect(b.call).to eq :some_value
109
+ end
110
+ dsl
111
+ end
112
+
113
+ it 'assigns the new condition' do
114
+ condition = double('condition').as_null_object
115
+ allow(Condition).to receive(:evaluate) { condition }
116
+ expect(dsl.condition).to be condition
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ describe '#condition' do
123
+ context 'without block' do
124
+ it 'returns the assigned condition' do
125
+ dsl.instance_eval { @condition = :some_condition }
126
+ expect(dsl.condition).to be :some_condition
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Task do
5
+ let(:name) { :some_task }
6
+ let(:action) { double('action') }
7
+ let(:condition) { double('condition') }
8
+ subject(:task) { Task.new(name, [action], condition) }
9
+
10
+ describe '.evaluate' do
11
+ let(:env) { double('env') }
12
+ let(:block) { proc { :some_value } }
13
+
14
+ it 'delegates to DSL.evaluate' do
15
+ expect(Task::DSL)
16
+ .to receive(:evaluate).with(name, env) do |&b|
17
+ expect(b.call).to eq :some_value
18
+ end
19
+ Task.evaluate(name, env, &block)
20
+ end
21
+
22
+ it 'returns the evaluated task' do
23
+ task = double('task')
24
+ allow(Task::DSL).to receive(:evaluate) { task }
25
+ expect(Task.evaluate(name, env, &block)).to be task
26
+ end
27
+ end
28
+
29
+ describe '#initialize' do
30
+ it 'assigns the name' do
31
+ expect(task.instance_eval { @name }).to eq name
32
+ end
33
+
34
+ it 'assigns the actions' do
35
+ expect(task.instance_eval { @actions }).to eq [action]
36
+ end
37
+
38
+ it 'assigns the condition' do
39
+ expect(task.instance_eval { @condition }).to eq condition
40
+ end
41
+
42
+ context 'when only the name is given as argument' do
43
+ subject(:task) { Task.new(name) }
44
+
45
+ it 'assigns no action' do
46
+ expect(task.actions).to be_empty
47
+ end
48
+
49
+ it 'assigns a truthy condition' do
50
+ expect(task.condition).to be_true
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '#name' do
56
+ it 'returns its name' do
57
+ expect(task.name).to eq name
58
+ end
59
+ end
60
+
61
+ describe '#actions' do
62
+ it 'returns the assigned actions' do
63
+ expect(task.actions).to eq [action]
64
+ end
65
+ end
66
+
67
+ describe '#condition' do
68
+ it 'returns the assigned condition' do
69
+ expect(task.condition).to be condition
70
+ end
71
+ end
72
+
73
+ describe '#condition_met?' do
74
+ context 'when condition is truthy' do
75
+ let(:condition) { Condition.new([], true) }
76
+
77
+ it 'returns true' do
78
+ expect(task.condition_met?).to be true
79
+ end
80
+ end
81
+
82
+ context 'when condition is falsy' do
83
+ let(:condition) { Condition.new([], false) }
84
+
85
+ it 'returns false' do
86
+ expect(task.condition_met?).to be false
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Test do
5
+ let(:env) { double 'env' }
6
+ let(:arguments) { [:some, :arguments] }
7
+ subject(:action) { Test.new(env, *arguments) }
8
+
9
+ describe '#initialize' do
10
+ it 'assigns the env' do
11
+ expect(action.instance_eval { @env }).to be env
12
+ end
13
+ it 'assigns the arguments' do
14
+ expect(action.instance_eval { @arguments }).to eq arguments
15
+ end
16
+ end
17
+
18
+ describe '#env' do
19
+ it 'returns the assigned env' do
20
+ expect(action.env).to be env
21
+ end
22
+ end
23
+
24
+ describe '#arguments' do
25
+ it 'returns the assigned arguments' do
26
+ expect(action.arguments).to eq arguments
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Tests::HasEnv do
5
+ let(:env) { Env.new }
6
+ let(:variable_name) { :some_variable_name }
7
+ subject(:has_env) { Tests::HasEnv.new(env, variable_name) }
8
+
9
+ it 'is a kind of test' do
10
+ expect(has_env).to be_a Test
11
+ end
12
+
13
+ describe '#success?' do
14
+ let(:environment) { double('environment') }
15
+
16
+ before do
17
+ allow(env.remote).to receive(:environment) { environment }
18
+ end
19
+
20
+ it 'stringifies the queried variable name' do
21
+ expect(environment).to receive(:has_key?).with(kind_of(String))
22
+ has_env.success?
23
+ end
24
+
25
+ it 'upcases the queried variable name' do
26
+ expect(environment).to receive(:has_key?).with('SOME_VARIABLE_NAME')
27
+ has_env.success?
28
+ end
29
+
30
+ it 'returns true when remote environment var is defined' do
31
+ allow(environment).to receive(:has_key?) { true }
32
+ expect(has_env.success?).to be true
33
+ end
34
+
35
+ it 'returns false when remote environment var is not defined' do
36
+ allow(environment).to receive(:has_key?) { false }
37
+ expect(has_env.success?).to be false
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,16 @@
1
+ require 'producer/core'
2
+
3
+ require 'support/exit_helpers'
4
+ require 'support/fixtures_helpers'
5
+ require 'support/net_ssh_story_helpers'
6
+ require 'support/tests_helpers'
7
+
8
+
9
+ RSpec.configure do |c|
10
+ c.treat_symbols_as_metadata_keys_with_true_values = true
11
+
12
+ c.include NetSSHStoryHelpers, :ssh
13
+ c.before(:each, :ssh) do
14
+ allow(remote).to receive(:session) { connection }
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ module ExitHelpers
2
+ def trap_exit
3
+ yield
4
+ rescue SystemExit
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ module FixturesHelpers
2
+ FIXTURES_PATH = 'spec/fixtures'
3
+
4
+ def fixture_path_for(path)
5
+ File.join(FIXTURES_PATH, path)
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module NetSSHStoryHelpers
2
+ require 'net/ssh/test'
3
+ include Net::SSH::Test
4
+
5
+ def story_with_new_channel
6
+ story do |session|
7
+ ch = session.opens_channel
8
+ yield ch
9
+ ch.gets_close
10
+ ch.sends_close
11
+ end
12
+ end
13
+
14
+ def story_completed?
15
+ socket.script.events.empty?
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ module TestsHelpers
2
+ def test_ok
3
+ double('test', success?: true)
4
+ end
5
+
6
+ def test_ko
7
+ double('test', success?: false)
8
+ end
9
+ end