From 4a50890e4fefb94d9f33a313121cd5503987599e Mon Sep 17 00:00:00 2001 From: Gabriel Arjones Date: Sun, 24 May 2020 00:44:14 -0300 Subject: [PATCH] add at_least_until to the maintain expectation --- lib/roby/test/execution_expectations.rb | 58 ++++++++++++++++++++---- test/test/test_execution_expectations.rb | 37 +++++++++++++++ 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/lib/roby/test/execution_expectations.rb b/lib/roby/test/execution_expectations.rb index f7a7e6b94..564475970 100644 --- a/lib/roby/test/execution_expectations.rb +++ b/lib/roby/test/execution_expectations.rb @@ -114,17 +114,36 @@ def not_become_unreachable(*generators, backtrace: caller(1)) # # @param [Float] at_least_during the minimum duration in seconds. If # zero, the expectations will run at least one execution cycle. The - # exact duration depends on the other expectations. + # exact duration depends on the other expectations. Cannot be used + # with at_least_until. + # @param [Float] at_least_until the expected generator. The expectations + # will run until the generator is emitted. Cannot be used with + # at_least_during. # @yieldparam [ExecutionEngine::PropagationInfo] # all_propagation_info all that happened during the propagations # since the beginning of expect_execution block. It contains event # emissions and raised/caught errors. # @yieldreturn [Boolean] expected to be true over duration seconds def maintain( - at_least_during: 0, description: nil, backtrace: caller(1), &block + at_least_during: nil, + at_least_until: nil, + description: nil, + backtrace: caller(1), + &block ) + if at_least_during && at_least_until + raise ArgumentError, "at_least_until and at_least_during "\ + "are mutually exclusive" + end + + at_least_during = 0 unless at_least_during || at_least_until add_expectation( - Maintain.new(at_least_during, block, description, backtrace) + Maintain.new( + at_least_during || at_least_until, + block, + description, + backtrace + ) ) end @@ -1145,30 +1164,49 @@ def to_s end class Maintain < Expectation - def initialize(at_least_during, block, description, backtrace) + def initialize(at_least, block, description, backtrace) super(backtrace) - @at_least_during = at_least_during + + if at_least.kind_of? EventGenerator + @at_least_until = at_least + else + @at_least_during = at_least + @deadline = Time.now + at_least + end + @description = description || @backtrace[0].to_s @block = block - @deadline = Time.now + at_least_during @failed = false end + def emitted?(propagation_info) + return false unless @at_least_until + + @emitted_events = + propagation_info + .emitted_events + .find_all { |ev| ev.generator == @at_least_until } + !@emitted_events.empty? + end + def update_match(propagation_info) if !@block.call(propagation_info) @failed = true false - elsif Time.now > @deadline - true + else + emitted?(propagation_info) || + (@at_least_during && Time.now > @deadline) end end def unachievable?(_propagation_info) - @failed + @failed || @at_least_until&.unreachable? end def explain_unachievable(_propagation_info) - "#{self} returned false" + return "#{self} returned false" if @failed + + @at_least_until&.unreachability_reason end def to_s diff --git a/test/test/test_execution_expectations.rb b/test/test/test_execution_expectations.rb index d3fe5bdf6..149f832c2 100644 --- a/test/test/test_execution_expectations.rb +++ b/test/test/test_execution_expectations.rb @@ -663,6 +663,43 @@ def return_object assert_equal "10", expectation.to_s end + it "validates when the event is emitted" do + plan.add(generator = EventGenerator.new) + expect_execution { generator.emit } + .to { maintain(at_least_until: generator) { true } } + end + it "fails if the event is not emitted within the given timeout" do + plan.add(generator = EventGenerator.new) + assert_raises(ExecutionExpectations::Unmet) do + expect_execution + .timeout(0.2) + .to { maintain(at_least_until: generator) { true } } + end + end + it "fails if the block evaluates to false" do + plan.add(generator = EventGenerator.new) + assert_raises(ExecutionExpectations::Unmet) do + expect_execution + .to { maintain(at_least_until: generator) { false } } + end + end + it "fails if at_least_during and at_least_until are used together" do + plan.add(generator = EventGenerator.new) + assert_raises(ArgumentError) do + expect_execution.to do + maintain(at_least_until: generator, + at_least_during: 1) { true } + end + end + end + it "fails if the generator becomes unreachable" do + plan.add(generator = EventGenerator.new) + assert_raises(ExecutionExpectations::Unmet) do + expect_execution { generator.unreachable! } + .timeout(0) + .to { maintain(at_least_until: generator) { true } } + end + end end describe "#achieve" do