From ed99c191e0b506b1bfc9c39f900ea6e01c9af2a3 Mon Sep 17 00:00:00 2001 From: Thibault Jouan Date: Sat, 17 Aug 2013 22:06:07 +0000 Subject: [PATCH] Build conditions with DSL evaluated tests: In Condition: * Modify constructor to accepts tests and a default return value; * Implement #met?; * Modify #! so that it return the negated value returned by #met?. In Condition::DSL: * Modify .evaluate to build the condition with tests and the value returned by a the evaluated condition block. Add a basic Test base class, with env and arguments as attributes. Add some spec helpers to build some easily testable kind of Test instances (as test doubles). --- lib/producer/core.rb | 5 ++ lib/producer/core/condition.rb | 13 +++-- lib/producer/core/condition/dsl.rb | 3 +- lib/producer/core/test.rb | 12 +++++ spec/producer/core/condition/dsl_spec.rb | 6 +-- spec/producer/core/condition_spec.rb | 69 +++++++++++++++++++++--- spec/producer/core/task_spec.rb | 4 +- spec/producer/core/test_spec.rb | 30 +++++++++++ spec/spec_helper.rb | 1 + spec/support/tests_helpers.rb | 9 ++++ 10 files changed, 137 insertions(+), 15 deletions(-) create mode 100644 lib/producer/core/test.rb create mode 100644 spec/producer/core/test_spec.rb create mode 100644 spec/support/tests_helpers.rb diff --git a/lib/producer/core.rb b/lib/producer/core.rb index 8215060..18f75ea 100644 --- a/lib/producer/core.rb +++ b/lib/producer/core.rb @@ -1,6 +1,11 @@ +# task actions require 'producer/core/action' require 'producer/core/actions/echo' require 'producer/core/actions/shell_command' + +# condition tests (need to be defined before the condition DSL) +require 'producer/core/test' + require 'producer/core/cli' require 'producer/core/condition' require 'producer/core/condition/dsl' diff --git a/lib/producer/core/condition.rb b/lib/producer/core/condition.rb index 73f0779..c74b8ba 100644 --- a/lib/producer/core/condition.rb +++ b/lib/producer/core/condition.rb @@ -7,12 +7,19 @@ module Producer end end - def initialize(expression) - @expression = expression + def initialize(tests, return_value = nil) + @tests = tests + @return_value = return_value + end + + def met? + return !!@return_value if @tests.empty? + @tests.each { |t| return false unless t.success? } + true end def ! - !@expression + !met? end end end diff --git a/lib/producer/core/condition/dsl.rb b/lib/producer/core/condition/dsl.rb index 9d0709c..0b1aa2b 100644 --- a/lib/producer/core/condition/dsl.rb +++ b/lib/producer/core/condition/dsl.rb @@ -5,7 +5,8 @@ module Producer class << self def evaluate(env, &block) dsl = new(env, &block) - Condition.new(dsl.evaluate) + return_value = dsl.evaluate + Condition.new(dsl.tests, return_value) end def define_test(keyword, klass) diff --git a/lib/producer/core/test.rb b/lib/producer/core/test.rb new file mode 100644 index 0000000..4183b3a --- /dev/null +++ b/lib/producer/core/test.rb @@ -0,0 +1,12 @@ +module Producer + module Core + class Test + attr_reader :env, :arguments + + def initialize(env, *arguments) + @env = env + @arguments = arguments + end + end + end +end diff --git a/spec/producer/core/condition/dsl_spec.rb b/spec/producer/core/condition/dsl_spec.rb index 348e874..dc80a02 100644 --- a/spec/producer/core/condition/dsl_spec.rb +++ b/spec/producer/core/condition/dsl_spec.rb @@ -14,15 +14,15 @@ module Producer::Core end it 'evaluates the DSL sandbox code' do - dsl = double('dsl') + dsl = double('dsl').as_null_object allow(Condition::DSL).to receive(:new) { dsl } expect(dsl).to receive(:evaluate) Condition::DSL.evaluate(env, &block) end - it 'builds a condition with value returned from DSL evaluation' do + it 'builds a condition with its test and block return value' do expect(Condition) - .to receive(:new).with(dsl.evaluate) + .to receive(:new).with(dsl.tests, :some_condition_code) Condition::DSL.evaluate(env, &block) end diff --git a/spec/producer/core/condition_spec.rb b/spec/producer/core/condition_spec.rb index 057fb64..5d969aa 100644 --- a/spec/producer/core/condition_spec.rb +++ b/spec/producer/core/condition_spec.rb @@ -2,8 +2,10 @@ require 'spec_helper' module Producer::Core describe Condition do - let(:expression) { double('expression') } - let(:condition) { Condition.new(expression) } + include TestsHelpers + + let(:tests) { [test_ok, test_ko] } + subject(:condition) { Condition.new(tests) } describe '.evaluate' do let(:env) { double('env') } @@ -25,14 +27,69 @@ module Producer::Core end describe '#initialize' do - it 'assigns the expression' do - expect(condition.instance_eval { @expression }).to be expression + it 'assigns the tests' do + expect(condition.instance_eval { @tests }).to eq tests + end + + it 'assigns nil as a default return value' do + expect(condition.instance_eval { @return_value }).to be nil + end + + context 'when a return value is given as argument' do + let(:return_value) { :some_return_value } + subject(:condition) { Condition.new(tests, return_value) } + + it 'assigns the return value' do + expect(condition.instance_eval { @return_value }).to eq return_value + end + end + end + + describe '#met?' do + context 'when all tests are successful' do + let(:tests) { [test_ok, test_ok] } + + it 'returns true' do + expect(condition.met?).to be true + end + end + + context 'when one test is unsuccessful' do + let(:tests) { [test_ok, test_ko] } + + it 'returns false' do + expect(condition.met?).to be false + end + end + + context 'when there are no test' do + subject(:condition) { Condition.new([], return_value) } + + context 'and return value is truthy' do + let(:return_value) { :some_truthy_value } + + it 'returns true' do + expect(condition.met?).to be true + end + end + + context 'and return value is falsy' do + let(:return_value) { nil } + + it 'returns false' do + expect(condition.met?).to be false + end + end end end describe '#!' do - it 'returns the negated expression' do - expect(condition.!).to be !expression + %w[true false].each do |b| + context "when #met? return #{b}" do + it 'returns the negated #met?' do + expect(condition.!).to be !condition.met? + end + end end end end diff --git a/spec/producer/core/task_spec.rb b/spec/producer/core/task_spec.rb index 41cd7e0..d4d6887 100644 --- a/spec/producer/core/task_spec.rb +++ b/spec/producer/core/task_spec.rb @@ -72,7 +72,7 @@ module Producer::Core describe '#condition_met?' do context 'when condition is truthy' do - let(:condition) { Condition.new(true) } + let(:condition) { Condition.new([], true) } it 'returns true' do expect(task.condition_met?).to be true @@ -80,7 +80,7 @@ module Producer::Core end context 'when condition is falsy' do - let(:condition) { Condition.new(false) } + let(:condition) { Condition.new([], false) } it 'returns false' do expect(task.condition_met?).to be false diff --git a/spec/producer/core/test_spec.rb b/spec/producer/core/test_spec.rb new file mode 100644 index 0000000..39ac19c --- /dev/null +++ b/spec/producer/core/test_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +module Producer::Core + describe Test do + let(:env) { double 'env' } + let(:arguments) { [:some, :arguments] } + subject(:action) { Test.new(env, *arguments) } + + describe '#initialize' do + it 'assigns the env' do + expect(action.instance_eval { @env }).to be env + end + it 'assigns the arguments' do + expect(action.instance_eval { @arguments }).to eq arguments + end + end + + describe '#env' do + it 'returns the assigned env' do + expect(action.env).to be env + end + end + + describe '#arguments' do + it 'returns the assigned arguments' do + expect(action.arguments).to eq arguments + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 85d1639..ae328a1 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,6 +3,7 @@ require 'producer/core' require 'support/exit_helpers' require 'support/fixtures_helpers' require 'support/net_ssh_story_helpers' +require 'support/tests_helpers' RSpec.configure do |c| diff --git a/spec/support/tests_helpers.rb b/spec/support/tests_helpers.rb new file mode 100644 index 0000000..61494b5 --- /dev/null +++ b/spec/support/tests_helpers.rb @@ -0,0 +1,9 @@ +module TestsHelpers + def test_ok + double('test', success?: true) + end + + def test_ko + double('test', success?: false) + end +end