On Thu, May 27, 2010 at 05:27:38PM -0700, I. E. Smith-Heisters wrote:
> 
> I've tried Engine#wait_for, but none of the options work for me:
> passing a wfid won't work because the process isn't terminating,
> passing a participant just hangs the test process indefinitely, and an
> integer won't work because I've no idea how many messages need to be
> passed.

Hello Ian,

it's true that the wait_for(participant_name_as_a_symbol) might not be 
applicable in your case.

I use it with success in ruote's test suite, but it's using the 
Ruote::TestLogger instead of the Ruote::WaitLogger coming by default with the 
engine.

The TestLogger keeps track of seen messages, it's more reliable, for cases when 
the engine is faster than the wait_for() order. The symptom of "engine faster 
than wait_for()" is simply the wait_for() never returning since the message 
it's waiting for is gone.

To use the TestLogger, you have to make sure the worker/engine/storage uses it 
as the logger service, like in this example :

---8<---
  @engine =
    Ruote::Engine.new(
      Ruote::Worker.new(
        determine_storage(
          's_logger' => [ 'ruote/log/test_logger', 'Ruote::TestLogger' ])))
--->8---

The downside is that this TestLogger is only meant for testing, its log of seen 
messages is not bound, if no wait_for 'consumes' it, it may grow too large.


> I see two potential solutions:
> 
> 1. some way to "jump" the process instance to a given state, kind of
> like stubbing or database fixtures

There has already been demand for this kind of feature. It should be easy to 
wrap participants to force some of them to "fast forward". I will think about 
it, I think it's a necessary feature.

Somehow, it can already be realize by registering "fast forward" participant 
for the sake of the test.


> 2. some way to reliably detect and respond to engine events,
> effectively making my tests run synchronously with the engine (ie. get
> #wait_for working)

I could help if you tell me how (regex, absolute names) you register your 
participant and how you except to wait_for them.


> Unfortunately, I've no idea how I would approach either solution. Are
> there other solutions? Help approaching one of these?

There could be a third solution : since you are using StorageParticipant, you 
could extend it for your testing purposes.

see http://gist.github.com/416620 :

---8<---
class TestStorageParticipant < Ruote::StorageParticipant

  def initialize (options)

    super(options)

    @seen = []
  end

  def consume (workitem)

    @seen << workitem.dup
      # dup in order to return the workitem as 'received' by the participant

    super(workitem)

    check_waiting
  end

  def wait_for (*participant_names)

    @waiting = [ Thread.current, participant_names ]

    check_waiting

    Thread.stop if @waiting

    Thread.current['__result__']
      # return the waited for workitem as a result
  end

  protected

  def check_waiting

    return unless @waiting

    while workitem = @seen.shift

      break if check_workitem(workitem)
    end
  end

  def check_workitem (workitem)

    if @waiting[1].include?(workitem.participant_name)

      thread = @waiting[0]
      @waiting = nil
      thread['__result__'] = workitem
      thread.wakeup

      true
    else

      false
    end
  end
end
--->8---

Warning : this is not tested, it's been written during a train ride (right now).


Your email made me realize I'm using sleep instead of wait_for in ruote-cukes :

  http://github.com/jmettraux/ruote-cukes

I have to change that.


Glad to help, best regards,

-- 
John Mettraux - http://jmettraux.wordpress.com

-- 
you received this message because you are subscribed to the "ruote users" group.
to post : send email to [email protected]
to unsubscribe : send email to [email protected]
more options : http://groups.google.com/group/openwferu-users?hl=en

Reply via email to