PageRenderTime 51ms CodeModel.GetById 6ms RepoModel.GetById 7ms app.codeStats 0ms

/test/functional/ft_20_storage_participant.rb

http://github.com/jmettraux/ruote
Ruby | 800 lines | 499 code | 261 blank | 40 comment | 5 complexity | bb6352289e2ee12154205e3036bbb237 MD5 | raw file
  1. #
  2. # testing ruote
  3. #
  4. # Thu Dec 3 22:39:03 JST 2009
  5. #
  6. require File.expand_path('../base', __FILE__)
  7. require 'ruote/part/storage_participant'
  8. class FtStorageParticipantTest < Test::Unit::TestCase
  9. include FunctionalBase
  10. def test_participant
  11. pdef = Ruote.process_definition :name => 'def0' do
  12. alpha
  13. end
  14. @dashboard.register_participant :alpha, Ruote::StorageParticipant
  15. wfid = @dashboard.launch(pdef)
  16. wait_for(:alpha)
  17. assert_equal 1, @dashboard.storage.get_many('workitems').size
  18. alpha = Ruote::StorageParticipant.new
  19. alpha.context = @dashboard.context
  20. wi = alpha.first
  21. assert_equal Ruote::Workitem, wi.class
  22. wi = alpha[alpha.first.fei]
  23. assert_equal Ruote::Workitem, wi.class
  24. alpha.proceed(wi)
  25. wait_for(wfid)
  26. assert_nil @dashboard.process(wfid)
  27. end
  28. def test_purge
  29. pdef = Ruote.process_definition :name => 'def0' do
  30. alpha
  31. end
  32. @dashboard.register_participant :alpha, Ruote::StorageParticipant
  33. wfid = @dashboard.launch(pdef)
  34. wait_for(:alpha)
  35. assert_equal 1, @dashboard.storage.get_many('workitems').size
  36. alpha = Ruote::StorageParticipant.new
  37. alpha.context = @dashboard.context
  38. assert !alpha.first.nil?
  39. alpha.purge!
  40. assert alpha.first.nil?
  41. end
  42. def test_all
  43. n = 3
  44. pdef = Ruote.process_definition :name => 'def0' do
  45. alpha
  46. end
  47. @dashboard.register_participant :alpha, Ruote::StorageParticipant
  48. wfids = []
  49. n.times { wfids << @dashboard.launch(pdef) }
  50. while @dashboard.storage_participant.size < n
  51. sleep 0.400
  52. end
  53. assert_equal(
  54. [ Ruote::Workitem ] * 3,
  55. @dashboard.storage_participant.all.collect { |wi| wi.class })
  56. assert_equal 3, @dashboard.storage_participant.size
  57. assert_equal 3, @dashboard.storage_participant.all(:count => true)
  58. end
  59. def test_by_wfid
  60. pdef = Ruote.process_definition :name => 'def0' do
  61. concurrence do
  62. alpha
  63. alpha
  64. end
  65. end
  66. @dashboard.register_participant :alpha, Ruote::StorageParticipant
  67. wfid = @dashboard.launch(pdef)
  68. wait_for(:alpha)
  69. wait_for(:alpha)
  70. # wait for the two workitems
  71. alpha = Ruote::StorageParticipant.new
  72. alpha.context = @dashboard.context
  73. assert_equal 2, alpha.size
  74. assert_equal 2, alpha.by_wfid(wfid).size
  75. assert_equal 2, alpha.by_wfid(wfid, :count => true)
  76. end
  77. CON_AL_BRAVO = Ruote.process_definition :name => 'con_al_bravo' do
  78. set 'f:place' => 'heiankyou'
  79. concurrence do
  80. sequence do
  81. set 'f:character' => 'minamoto no hirosama'
  82. alpha
  83. end
  84. sequence do
  85. set 'f:character' => 'seimei'
  86. set 'f:adversary' => 'doson'
  87. bravo
  88. end
  89. end
  90. end
  91. def prepare_al_bravo
  92. @dashboard.register_participant :alpha, Ruote::StorageParticipant
  93. @dashboard.register_participant :bravo, Ruote::StorageParticipant
  94. @wfid = @dashboard.launch(CON_AL_BRAVO)
  95. wait_for(:bravo)
  96. @part = Ruote::StorageParticipant.new
  97. @part.context = @dashboard.context
  98. end
  99. def test_by_participant
  100. prepare_al_bravo
  101. assert_equal 2, @part.size
  102. #@part.by_participant('alpha').each { |wi| p wi }
  103. assert_equal Ruote::Workitem, @part.by_participant('alpha').first.class
  104. assert_equal 1, @part.by_participant('alpha').size
  105. assert_equal 1, @part.by_participant('bravo').size
  106. assert_equal 1, @part.by_participant('alpha', :count => true)
  107. assert_equal 1, @part.by_participant('bravo', :count => true)
  108. end
  109. def test_by_participant_and_limit
  110. 3.times do |i|
  111. @dashboard.storage.put(
  112. 'type' => 'workitems',
  113. '_id' => "0_#{i}!ffffff!20101219-yamamba",
  114. 'participant_name' => 'al',
  115. 'wfid' => '20101220-yamamba',
  116. 'fields' => {})
  117. end
  118. 3.times do |i|
  119. @dashboard.storage.put(
  120. 'type' => 'workitems',
  121. '_id' => "1_#{i}!eeeeee!20101219-yamamba",
  122. 'participant_name' => 'bob',
  123. 'wfid' => '20101220-yamamba',
  124. 'fields' => {})
  125. end
  126. sp = @dashboard.storage_participant
  127. assert_equal 6, sp.size
  128. assert_equal 0, sp.by_participant('nada', :limit => 2).size
  129. assert_equal 2, sp.by_participant('al', :limit => 2).size
  130. assert_equal 2, sp.by_participant('al', :skip => 0, :limit => 2).size
  131. assert_equal 2, sp.by_participant('al', :skip => 1, :limit => 2).size
  132. assert_equal 2, sp.by_participant('bob', :skip => 0, :limit => 2).size
  133. assert_equal 1, sp.by_participant('bob', :skip => 2, :limit => 2).size
  134. end
  135. def test_by_field
  136. prepare_al_bravo
  137. assert_equal 2, @part.size
  138. assert_equal Ruote::Workitem, @part.by_field('place').first.class
  139. assert_equal 2, @part.by_field('place').size
  140. assert_equal 2, @part.by_field('character').size
  141. assert_equal 1, @part.by_field('adversary').size
  142. assert_equal 2, @part.by_field('character', :count => true)
  143. end
  144. def test_by_field_and_limit
  145. prepare_al_bravo
  146. assert_equal(
  147. %w[ bravo ],
  148. @part.by_field(
  149. 'character', :skip => 1, :limit => 2
  150. ).collect { |wi| wi.participant_name })
  151. end
  152. def test_by_field_and_value
  153. prepare_al_bravo
  154. assert_equal 2, @part.size
  155. assert_equal 0, @part.by_field('place', 'nara').size
  156. assert_equal 2, @part.by_field('place', 'heiankyou').size
  157. assert_equal 1, @part.by_field('character', 'minamoto no hirosama').size
  158. assert_equal 2, @part.by_field('place', 'heiankyou', :count => true)
  159. end
  160. def test_query
  161. prepare_al_bravo
  162. wfid2 = @dashboard.launch(CON_AL_BRAVO, 'adversary' => 'B')
  163. wait_for(:bravo)
  164. #@part.query({}).each { |wi| puts '-' * 80; p wi }
  165. assert_equal 4, @part.size
  166. assert_equal 4, @part.query({}).size
  167. assert_equal Ruote::Workitem, @part.query({}).first.class
  168. assert_equal 2, @part.query(:wfid => @wfid).size
  169. assert_equal 0, @part.query('place' => 'nara').size
  170. assert_equal 4, @part.query('place' => 'heiankyou').size
  171. assert_equal 2, @part.query(:wfid => @wfid, :place => 'heiankyou').size
  172. assert_equal(
  173. 1,
  174. @part.query(:adversary => 'B', :place => 'heiankyou').size)
  175. assert_equal 2, @part.query('place' => 'heiankyou', :limit => 2).size
  176. assert_equal 4, @part.query('place' => 'heiankyou', :limit => 20).size
  177. assert_equal 4, @part.query(:count => true)
  178. page0 =
  179. @part.query('place' => 'heiankyou', :limit => 2).collect { |wi|
  180. "#{wi.fei.wfid}-#{wi.participant_name}" }
  181. page1 =
  182. @part.query('place' => 'heiankyou', :offset => 2, :limit => 2).collect { |wi|
  183. "#{wi.fei.wfid}-#{wi.participant_name}" }
  184. assert_equal 4, (page0 + page1).sort.uniq.size
  185. assert_equal(
  186. 2, @part.query('place' => 'heiankyou', :participant => 'alpha').size)
  187. assert_equal 2, @part.query(:participant => 'alpha').size
  188. assert_equal 2, @part.query(:participant => 'alpha', :count => true)
  189. end
  190. # Issue reported in
  191. # http://groups.google.com/group/openwferu-users/browse_thread/thread/d0557c58f8636c9
  192. #
  193. def test_query_and_limit
  194. n = 7
  195. n.times do |i|
  196. @dashboard.storage.put(
  197. 'type' => 'workitems',
  198. '_id' => "0_#{i}!ffffff!20101219-yamamba",
  199. 'participant_name' => 'al',
  200. 'wfid' => '20101219-yamamba',
  201. 'fields' => {})
  202. end
  203. n.times do |i|
  204. @dashboard.storage.put(
  205. 'type' => 'workitems',
  206. '_id' => "1_#{i}!ffffff!20101219-yamamba",
  207. 'participant_name' => 'bob',
  208. 'wfid' => '20101219-yamamba',
  209. 'fields' => {})
  210. end
  211. sp = @dashboard.storage_participant
  212. assert_equal n * 2, sp.query({}).size
  213. assert_equal n * 2, sp.query(:offset => 0, :limit => 100).size
  214. assert_equal n * 2, sp.query(:skip => 0, :limit => 100).size
  215. assert_equal n / 2, sp.query(:offset => 0, :limit => n / 2).size
  216. assert_equal n / 2, sp.query(:skip => 0, :limit => n / 2).size
  217. assert_equal(
  218. n / 2,
  219. sp.query(:participant_name => 'al', :offset => 0, :limit => n / 2).size)
  220. assert_equal(
  221. n / 2,
  222. sp.query(:participant_name => 'al', :skip => 0, :limit => n / 2).size)
  223. assert_equal(
  224. [ 'al' ] * (n / 2),
  225. sp.query(
  226. :participant_name => 'al', :skip => 0, :limit => n / 2
  227. ).collect { |wi| wi.participant_name })
  228. end
  229. def test_initialize_engine_then_opts
  230. @dashboard.register_participant :alpha, Ruote::StorageParticipant
  231. wfid = @dashboard.launch(Ruote.process_definition do
  232. alpha
  233. end)
  234. wait_for(:alpha)
  235. part = Ruote::StorageParticipant.new(@dashboard)
  236. assert_equal 1, part.size
  237. end
  238. def test_cancel
  239. pdef = Ruote.process_definition :name => 'def0' do
  240. alpha
  241. end
  242. @dashboard.register_participant :alpha, Ruote::StorageParticipant
  243. wfid = @dashboard.launch(pdef)
  244. wait_for(:alpha)
  245. @dashboard.cancel_process(wfid)
  246. wait_for(wfid)
  247. assert_nil @dashboard.process(wfid)
  248. assert_equal 0, Ruote::StorageParticipant.new(@dashboard).size
  249. end
  250. def test_shared_participant
  251. @dashboard.register_participant 'step_.*', Ruote::StorageParticipant
  252. wfid = @dashboard.launch(
  253. Ruote.process_definition { sequence { step_one; step_two } })
  254. wait_for(:step_one)
  255. participant = Ruote::StorageParticipant.new(@dashboard)
  256. items = participant.by_wfid(wfid)
  257. assert_equal 1, participant.size
  258. assert_equal 1, items.size
  259. assert_equal 'step_one', items.first.participant_name
  260. participant.proceed(items.first)
  261. wait_for(:step_two)
  262. items = participant.by_wfid(wfid)
  263. assert_equal 1, participant.size
  264. assert_equal 1, items.size
  265. assert_equal 'step_two', items.first.participant_name
  266. participant.proceed(items.first)
  267. wait_for(wfid)
  268. assert_nil @dashboard.process(wfid)
  269. end
  270. def test_update_workitem
  271. @dashboard.register_participant 'alpha', Ruote::StorageParticipant
  272. wfid = @dashboard.launch(Ruote.process_definition { alpha })
  273. alpha = Ruote::StorageParticipant.new(@dashboard)
  274. wait_for(:alpha)
  275. wi = alpha.first
  276. wi.fields['jidai'] = 'heian'
  277. alpha.update(wi)
  278. assert_equal 'heian', alpha.first.fields['jidai']
  279. end
  280. def test_registration
  281. pa = @dashboard.register_participant 'alpha', Ruote::StorageParticipant
  282. assert_equal Ruote::StorageParticipant, pa.class
  283. assert_equal [], pa.all
  284. end
  285. def test_various_args
  286. sp = @dashboard.register_participant 'alpha', Ruote::StorageParticipant
  287. wfid = @dashboard.launch(Ruote.process_definition { alpha })
  288. wait_for(:alpha)
  289. wi = sp.first
  290. assert_equal wi, sp[wi]
  291. assert_equal wi, sp[wi.fei]
  292. assert_equal wi, sp[wi.to_h]
  293. assert_equal wi, sp[wi.fei.to_h]
  294. assert_equal wi, sp[wi.fei.to_storage_id]
  295. end
  296. def test_by_fei
  297. sp = @dashboard.register_participant 'alpha', Ruote::StorageParticipant
  298. wfid = @dashboard.launch(Ruote.process_definition { alpha })
  299. wait_for(:alpha)
  300. wi = sp.first
  301. assert_equal wi, sp.by_fei(wi)
  302. assert_equal wi, sp.by_fei(wi.fei)
  303. assert_equal wi, sp.by_fei(wi.to_h)
  304. assert_equal wi, sp.by_fei(wi.fei.to_h)
  305. assert_equal wi, sp.by_fei(wi.fei.to_storage_id)
  306. end
  307. def test_engine_storage_participant
  308. @dashboard.register_participant 'step_.*', Ruote::StorageParticipant
  309. wfid = @dashboard.launch(Ruote.process_definition { step_one })
  310. wait_for(:step_one)
  311. assert_equal 1, @dashboard.storage_participant.size
  312. assert_equal 'step_one', @dashboard.storage_participant.first.participant_name
  313. end
  314. class MyParticipant < Ruote::StorageParticipant
  315. def on_workitem
  316. @context.tracer << "on_workitem\n"
  317. super
  318. end
  319. #def update(wi)
  320. # @context.tracer << "update\n"
  321. # super
  322. #end
  323. end
  324. def test_override_update
  325. pdef = Ruote.define do
  326. alpha
  327. end
  328. @dashboard.register do
  329. alpha MyParticipant
  330. end
  331. @dashboard.launch(pdef)
  332. @dashboard.wait_for(:alpha)
  333. part = @dashboard.participant(:alpha)
  334. initial_rev = part.first.h['_rev']
  335. part.update(part.first)
  336. assert_not_equal initial_rev, part.first.h['_rev']
  337. assert_equal %w[ on_workitem ], @tracer.to_a
  338. end
  339. def test_fetch
  340. @dashboard.register do
  341. catchall
  342. end
  343. @dashboard.launch(Ruote.define do
  344. alpha
  345. end)
  346. @dashboard.wait_for(:alpha)
  347. fei = @dashboard.storage_participant.first.fei
  348. wi = @dashboard.storage_participant.send(:fetch, fei)
  349. assert wi.kind_of?(Hash)
  350. end
  351. # StorageParticipant includes Enumerable, therefore, it should respond
  352. # to select...
  353. #
  354. # http://groups.google.com/group/openwferu-users/t/6b594fd141f5d4b1
  355. #
  356. def test_select
  357. @dashboard.register { catchall }
  358. @dashboard.launch(Ruote.define do
  359. concurrence { alpha; bravo; charly }
  360. end)
  361. while @dashboard.storage_participant.size < 3; end
  362. assert_equal(
  363. 1,
  364. @dashboard.storage_participant.select { |wi|
  365. wi.participant_name == 'bravo'
  366. }.size)
  367. end
  368. def test_reserve
  369. @dashboard.register { catchall }
  370. wfid = @dashboard.launch(Ruote.define do
  371. alpha
  372. end)
  373. while @dashboard.storage_participant.size < 1; end
  374. wi0 = @dashboard.storage_participant.first
  375. # #reserve yields the [updated] workitem when successful
  376. wi = @dashboard.storage_participant.first
  377. wi = @dashboard.storage_participant.reserve(wi, 'user0')
  378. assert_equal 'user0', wi.owner
  379. assert_not_equal wi0.h._rev, wi.h._rev # it's not the same wi
  380. # #reserve yields nil when failing
  381. wi = @dashboard.storage_participant.first
  382. wi = @dashboard.storage_participant.reserve(wi, 'user1')
  383. assert_equal nil, wi
  384. # #proceed raises when the owner is not the right one
  385. assert_raise(ArgumentError) do
  386. @dashboard.storage_participant.proceed(wi0)
  387. end
  388. wi = @dashboard.storage_participant.first
  389. @dashboard.storage_participant.proceed(wi)
  390. @dashboard.wait_for('terminated')
  391. # #proceed raises when the workitem is gone
  392. assert_raise(ArgumentError) do
  393. @dashboard.storage_participant.proceed(wi)
  394. end
  395. end
  396. def test_delegate
  397. @dashboard.register { catchall }
  398. wfid = @dashboard.launch(Ruote.define do
  399. alpha
  400. end)
  401. while @dashboard.storage_participant.size < 1; end
  402. wi0 = @dashboard.storage_participant.first
  403. # can't delegate when there is no owner
  404. assert_raise(ArgumentError) do
  405. @dashboard.storage_participant.delegate(wi0, 'user0')
  406. end
  407. # can't delegate if the owner is not the right one
  408. wi1 = @dashboard.storage_participant.reserve(wi0, 'user0')
  409. wi1.h.owner = 'user9'
  410. assert_raise(ArgumentError) do
  411. @dashboard.storage_participant.delegate(wi1, 'user0')
  412. end
  413. # it delegates alrighty
  414. wi1.h.owner = 'user0'
  415. wi2 = @dashboard.storage_participant.delegate(wi1, 'user1')
  416. assert_equal 'user1', wi2.h.owner
  417. # it's ok to delegate to nil (disowns workitem)
  418. wi = @dashboard.storage_participant.first
  419. x = @dashboard.storage_participant.delegate(wi, nil)
  420. wi = @dashboard.storage_participant.first
  421. assert_equal nil, wi.h.owner
  422. end
  423. def test_worklist
  424. assert_equal Ruote::StorageParticipant, @dashboard.storage_participant.class
  425. assert_equal Ruote::StorageParticipant, @dashboard.worklist.class
  426. end
  427. def test_flunk
  428. @dashboard.register :alpha, Ruote::StorageParticipant
  429. wfid = @dashboard.launch(Ruote.define do
  430. alpha
  431. end)
  432. @dashboard.wait_for('dispatched')
  433. assert_equal 1, @dashboard.storage_participant.size
  434. wi = @dashboard.storage_participant.first
  435. @dashboard.storage_participant.flunk(wi, ArgumentError, 'sorry?')
  436. r = @dashboard.wait_for(wfid)
  437. assert_equal 'error_intercepted', r['action']
  438. assert_equal 'ArgumentError', r['error']['class']
  439. assert_equal 'sorry?', r['error']['message']
  440. assert_match __FILE__, r['error']['trace'][1]
  441. assert_equal 0, @dashboard.storage_participant.size
  442. end
  443. def test_flunk_error_instance
  444. @dashboard.register :alpha, Ruote::StorageParticipant
  445. wfid = @dashboard.launch(Ruote.define do
  446. alpha
  447. end)
  448. @dashboard.wait_for('dispatched')
  449. assert_equal 1, @dashboard.storage_participant.size
  450. wi = @dashboard.storage_participant.first
  451. begin
  452. raise 'nada'
  453. rescue => e
  454. @dashboard.storage_participant.flunk(wi, e)
  455. end
  456. r = @dashboard.wait_for(wfid)
  457. assert_equal 'error_intercepted', r['action']
  458. assert_equal 'RuntimeError', r['error']['class']
  459. assert_equal 'nada', r['error']['message']
  460. assert_match __FILE__, r['error']['trace'].first
  461. assert_equal 0, @dashboard.storage_participant.size
  462. end
  463. def test_flunk_with_on_error
  464. @dashboard.register :alpha, Ruote::StorageParticipant
  465. wfid = @dashboard.launch(Ruote.define do
  466. sequence :on_error => 'report_error' do
  467. alpha
  468. end
  469. define 'report_error' do
  470. echo 'error...'
  471. end
  472. end)
  473. @dashboard.wait_for('dispatched')
  474. assert_equal 1, @dashboard.storage_participant.size
  475. wi = @dashboard.storage_participant.first
  476. @dashboard.storage_participant.flunk(wi, ArgumentError, 'pure fail')
  477. r = @dashboard.wait_for(wfid)
  478. assert_equal 'terminated', r['action']
  479. assert_equal 'error...', @tracer.to_s
  480. assert_equal 0, @dashboard.storage_participant.size
  481. end
  482. class IuriParticipant < Ruote::StorageParticipant
  483. def on_workitem
  484. super
  485. workitem.fields['count'] = 777
  486. do_update
  487. end
  488. end
  489. def test_do_update
  490. @dashboard.register :alpha, IuriParticipant
  491. wfid = @dashboard.launch(
  492. Ruote.define do
  493. alpha
  494. end)
  495. @dashboard.wait_for('dispatched')
  496. sleep 0.350
  497. wi = @dashboard.storage_participant.first
  498. assert_equal(777, wi.fields['count'])
  499. end
  500. # Originally written by Doug Bryant in
  501. # https://groups.google.com/forum/?fromgroups#!topic/openwferu-users/u9NZOurZxXk
  502. #
  503. def test_update_workitem_alt
  504. @dashboard.register_participant 'alpha', Ruote::StorageParticipant
  505. wfid = @dashboard.launch(Ruote.process_definition { alpha })
  506. wait_for(:alpha)
  507. #wi = @dashboard.process(wfid).workitems.first
  508. # doesn't work: the returned workitem isn't a workite document, it's
  509. # just a fragment of info
  510. wi = @dashboard.process(wfid).stored_workitems.first
  511. # works OK
  512. #wi = alpha.first
  513. # works OK, but you have to grab alpha first...
  514. alpha = @dashboard.participant(wi.participant_name)
  515. wi.set_field('my_field', 'abc123')
  516. alpha.update(wi)
  517. assert_equal nil, @dashboard.process(wfid).workitems.first.fields['my_field']
  518. assert_equal 'abc123', alpha.first.fields['my_field']
  519. end
  520. #
  521. # fighting the issue in
  522. # https://groups.google.com/forum/#!topic/openwferu-users/J2LfW2Bk6Hk
  523. class MyStorageParticipant < Ruote::StorageParticipant
  524. def on_workitem
  525. super
  526. workitem.fields['toto'] = 'nada'
  527. update(workitem)
  528. workitem.fields['toto'] = 'nada2'
  529. update(workitem)
  530. end
  531. end
  532. def test_update_workitem_in_in_workitem
  533. @dashboard.register 'msp', MyStorageParticipant
  534. wfid = @dashboard.launch(Ruote.define do; msp; end)
  535. wait_for(:msp)
  536. wi = @dashboard.process(wfid).stored_workitems.first
  537. assert_equal 'nada2', wi.fields['toto']
  538. end
  539. end