BPM-Engine
view release on metacpan or search on metacpan
t/04-run/01-transition.t view on Meta::CPAN
use DateTime;
use Data::Dumper;
my ($engine, $process);
# samples.xpdl
#-----------------------------------------------
$engine = BPM::Engine->new(schema => schema());
$engine->create_package('./t/var/08-samples.xpdl');
# unstructured-inclusive-tasks - OR split/join
if(1) {
my ($r,$p,$i) = runner($engine, 'unstructured-inclusive-tasks', { splitA => 'B1', splitB => undef });
my $activity = $p->start_activities->[0];
my $ai_A = #$r->_create_activity_instance($activity);
$activity->new_instance({
process_instance_id => $i->id
});
# main path (before splitted or after joined) doesn't have a parent_token
# OR any ai not directly after a split doesn't have a parent_token, use ->prev instead ??
#ok(!$ai_A->parent_token_id, 'A has no parent');
#ok(!$ai_A->prev, 'A has no previous');
# B1-JOIN
#- follow transition A-B1 (split->join)
#-----------------------------------------
ok(my $t_A_B1 = $activity->transitions->find({ transition_uid => 'ex4.A-B1'}));
ok(my $a_B1 = $t_A_B1->to_activity);
ok(my $t_A_B = $activity->transitions->find({ transition_uid => 'ex4.A-B'}));
ok(my $a_B = $t_A_B->to_activity);
ok(my $t_B_B1 = $a_B->transitions->find({ transition_uid => 'ex4.B-B1'}));
ok(my $t_B1_B2 = $a_B1->transitions->find({ transition_uid => 'ex4.B1-B2'}));
ok(my $a_B2 = $t_B1_B2->to_activity);
ok(my $t_B_C = $a_B->transitions->find({ transition_uid => 'ex4.B-C'}));
ok(my $t_B2_C = $a_B2->transitions->find({ transition_uid => 'ex4.B2-C'}));
ok(my $a_C = $t_B_C->to_activity);
ok(my $t_B2_D = $a_B2->transitions->find({ transition_uid => 'ex4.B2-D'}));
ok(my $t_C_D = $a_C->transitions->find({ transition_uid => 'ex4.C-D'}));
ok(my $a_D = $t_B2_D->to_activity);
my $attrs = { activity => $a_B1, };
my @args = ();
my $ai_B1 = $t_A_B1->derive_and_accept_instance($ai_A, $attrs, @args);
is($ai_B1->activity->activity_uid, 'ex4.B1','derive_and_accept results in B1');
# transition in joinA set to 'taken' since we're coming from a split
is($ai_A->split->states->{$t_A_B1->id}, 'taken', "Transition A-B1 state is 'taken'");
# after a split, the parent_token of the new ai is set to the split-ai
#is($ai_B1->parent_token_id, $ai_A->id, 'Parent matches');
#is($ai_B1->parent->id, $ai_A->id, 'Parent matches');
is($ai_B1->prev->id, $ai_A->id, 'Prev matches');
# join B1 should not fire, since although we didn't follow the path from A to B, A-B was not blocked either
# TODO: verify this is not a problem in runner!!
ok(!$ai_B1->is_enabled(), 'Join B1 should not fire');
# set A-B blocked, and see B1 enabled
$ai_A->split->discard_changes();
my $states = $ai_A->split->states;
$states->{$t_A_B->id} = 'blocked';
$ai_A->split->update({ states => $states })->discard_changes;
$ai_A->update({ completed => DateTime->now() });
ok($ai_B1->is_enabled(), 'Join B1 should fire');
is($ai_A->split->states->{$t_A_B->id}, 'blocked', "Transition A-B state is 'blocked'");
is($ai_A->split->states->{$t_A_B1->id}, 'taken', "Transition A-B1 state is 'taken'");
is($ai_B1->prev->split->states->{$t_A_B1->id}, 'taken', "Transition A-B1 state is 'taken'");
$ai_A->update({ completed => \'NULL' })->discard_changes;
delete $states->{$t_A_B->id};
$ai_A->split->update({ states => $states })->discard_changes;
ok(!$ai_B1->is_enabled(), 'Join B1 should not fire');
$ai_B1->update({ deferred => DateTime->now() });
#- follow transition A-B (split->split)
#-----------------------------------------
$attrs = { activity => $a_B };
@args = ();
$ai_A->update({ completed => DateTime->now() });
my $ai_B = $t_A_B->derive_and_accept_instance($ai_A, $attrs, @args);
is($ai_B->activity->activity_uid, 'ex4.B','derive_and_accept results in B');
# transition in joinA set to 'taken' since we're coming from a split
$ai_A->split->discard_changes();
is($ai_A->split->states->{$t_A_B->id}, 'taken', "Transition A-B state is 'taken'");
is($ai_A->split->states->{$t_A_B1->id}, 'taken', "Transition A-B1 state is 'taken'");
# now join B1 should NOT fire, since the path from A to B didn't come in yet
ok(!$ai_B1->is_enabled(), 'Join B1 should not fire anymore');
#- follow transition B-B1 (split->join)
#-----------------------------------------
$attrs = { activity => $a_B1 }; # $t_B_B1->to_activity
@args = ();
$ai_B->update({ completed => DateTime->now() });
my $ai_B1b = $t_B_B1->derive_and_accept_instance($ai_B, $attrs, @args);
is($ai_B1b->activity->activity_uid, 'ex4.B1','derive_and_accept results in B1');
# transition in join-for-split set to 'taken'
is($ai_B->split->states->{$t_B_B1->id}, 'taken');
# join B1 should now fire, as seen from all sides
ok($ai_B1b->is_enabled(), 'Join B1b should also fire');
#ok($ai_B1->is_enabled(), 'Join B1 should now fire again');
# fire the join
ok($ai_B1->is_deferred);
ok($ai_B1b->is_active);
#$ai_B1->fire_join();
$ai_B1b->fire_join();
#is($ai_A->split->states->{$t_A_B->id}, 'joined', "Transition A-B state is 'joined'");
#is($ai_A->split->states->{$t_A_B1->id}, 'joined', "Transition A-B1 state is 'joined'");
#is($ai_B1->prev->split->states->{$t_A_B1->id}, 'joined', "Transition A-B1 state is 'joined'");
#is($ai_B->split->states->{$t_B_B1->id}, 'joined');
ok($ai_B->is_completed);
#ok($ai_B1->is_completed);
ok($ai_B1b->is_active);
# C-JOIN
#- follow transition B1-B2 (join->split)
#-----------------------------------------
t/04-run/01-transition.t view on Meta::CPAN
# split not complete yet, this should not make sense at this point
ok(!$ai_A->split->should_fire($tAB, 1)); # not joined yet
# A-B1
my $ai_B1a = $tAB1->derive_and_accept_instance($ai_A, { activity => $aB1 }, @args);
is($ai_B1a->activity->activity_uid, 'ex4.B1','derive_and_accept results in B1');
is($ai_A->split->states->{$tAB1->id}, 'taken');
is($ai_A->split->states->{$tAB->id}, 'taken');
ok(!$ai_B1a->is_enabled(), 'Join B1 should not fire');
$ai_B1a->update({ deferred => DateTime->now });
# trans A-B1 set to 'taken'
$ai_A->split->discard_changes;
#is($ai_A->split->states->{$tAB1->id}, 'joined');
is($ai_A->split->states->{$tAB->id}, 'taken');
ok(!$ai_A->split->should_fire($tAB1, 1));
ok(!$ai_A->split->should_fire($tAB, 1));
# B-B1
$ai_B->update({ completed => DateTime->now() });
my $ai_B1b = $tBB1->derive_and_accept_instance($ai_B, { activity => $aB1 }, @args);
is($ai_B1b->activity->activity_uid, 'ex4.B1','derive_and_accept results in B1');
is($ai_B->split->states->{$tBB1->id}, 'taken');
ok($ai_B1b->is_enabled(), 'Join B1 should fire');
$ai_B1b->fire_join;
is($ai_B->split->discard_changes->states->{$tBB1->id}, 'joined');
is(scalar keys %{ $ai_B->split->states }, 1);
# this is never called in real life
ok($ai_B->split->should_fire($tBB1, 1)); # only one token
# B-C
my $ai_C = $tBC->derive_and_accept_instance($ai_B, { activity => $aC }, @args);
is($ai_C->activity->activity_uid, 'ex4.C','derive_and_accept results in C');
ok(!$ai_B->split->should_fire($tBB1, 1));
ok(!$ai_B->split->should_fire($tBC, 1));
ok(!$ai_C->is_enabled(), 'Join C should not fire');
#ok($ai_B1b->is_enabled(), 'Join B1 should still fire');
$ai_C->update({ deferred => DateTime->now });
# B1-B2
ok(!$ai_C->is_enabled(), 'Join C should not fire');
$ai_B1b->update({ completed => DateTime->now() });
my $ai_B2 = $tB1B2->derive_and_accept_instance($ai_B1b, { activity => $aB2 }, @args);
is($ai_B2->activity->activity_uid, 'ex4.B2','derive_and_accept results in B2');
# B2-D
$ai_B2->update({ completed => DateTime->now() });
ok($ai_B2->is_completed);
ok(my $ai_D = $tB2D->derive_and_accept_instance($ai_B2, { activity => $aD }, @args));
# Block B2-C
#ok(!$ai_C->is_enabled(), 'Join C should not fire'); # needs block when B2 completed
my $split = $ai_B2->split or die("No join found for split");
$split->set_transition($tB2C->id, 'blocked');
ok($ai_C->is_enabled(), 'Join C should fire');
$ai_C->update({ deferred => undef })->discard_changes;
$ai_C->fire_join;
ok(!$ai_D->is_enabled(), 'Join D should not fire');
$ai_D->update({ deferred => DateTime->now });
# C-D
$ai_C->update({ completed => DateTime->now() });
my $ai_D2 = $tCD->derive_and_accept_instance($ai_C, { activity => $aD }, @args);
#ok($ai_D->is_enabled(), 'Join D should fire');
ok($ai_D2->is_enabled(), 'Join D should fire');
}
#-- follow some transitions
else {
my $ai_A = $aA->new_instance({
process_instance_id => $i->id
});
# A-B
$ai_A->update({ completed => DateTime->now() }); # normally done in processrunner complete_activity
my $ai_B = $tAB->derive_and_accept_instance($ai_A, { activity => $aB }, @args);
# B-B1
$ai_B->update({ completed => DateTime->now() });
my $ai_B1b = $tBB1->derive_and_accept_instance($ai_B, { activity => $aB1 }, @args);
ok(!$ai_B1b->is_enabled(), 'Join B1 should not fire');
my $split = $ai_A->split or die("No join found for split");
$split->set_transition($tAB1->id, 'blocked');
ok($ai_B1b->is_enabled(), 'Join B1 should fire');
}
}
# patterns: 06-iteration.xpdl
#-----------------------------------------------
# WCP10: Arbitrary Cycles (nested-loops) - test tokensets
if(1) {
$engine->create_package('./t/var/06-iteration.xpdl');
my ($r,$p,$i) = runner($engine, 'wcp10b2', { inner_loop => '1', outer_loop => 1 });
my @args = ();
ok(my $t0A = $p->transitions->find({ transition_uid => 'wcp10b.Start-A-XOR-Join' }));
ok(my $tAB = $p->transitions->find({ transition_uid => 'wcp10b.A-XOR-Join-B-OR-Join' }));
ok(my $tBC = $p->transitions->find({ transition_uid => 'wcp10b.B-OR-Join-C-OR-Split' }));
ok(my $tCB = $p->transitions->find({ transition_uid => 'wcp10b.C-OR-Split-B-OR-Join' }));
ok(my $tCD = $p->transitions->find({ transition_uid => 'wcp10b.C-OR-Split-D-XOR-Split' }));
ok(my $tDA = $p->transitions->find({ transition_uid => 'wcp10b.D-XOR-Split-A-XOR-Join' }));
ok(my $tD0 = $p->transitions->find({ transition_uid => 'wcp10b.D-XOR-Split-End' }));
ok(my $aS = $p->activities->find({ activity_uid => 'wcp10b.Start' }));
ok(my $aA = $p->activities->find({ activity_uid => 'wcp10b.A-XOR-Join' }));
ok(my $aB = $p->activities->find({ activity_uid => 'wcp10b.B-OR-Join' }));
ok(my $aC = $p->activities->find({ activity_uid => 'wcp10b.C-OR-Split' }));
ok(my $aD = $p->activities->find({ activity_uid => 'wcp10b.D-XOR-Split' }));
ok(my $aE = $p->activities->find({ activity_uid => 'wcp10b.End' }));
my $ai_S = $aS->new_instance({ process_instance_id => $i->id });
# Start-A
$ai_S->update({ completed => DateTime->now() });
my $ai_A = $t0A->derive_and_accept_instance($ai_S, { activity => $aA }, @args);
ok($ai_A->is_enabled(), 'Join1 should fire');
# A-B (Join1-Join2)
$ai_A->update({ completed => DateTime->now() });
my $ai_B1 = $tAB->derive_and_accept_instance($ai_A, { activity => $aB }, @args);
ok($ai_B1->is_enabled(), 'Join2 should fire');
# B-C : Split2 loops back to Join2 AND goes downstream to Split1
$ai_B1->update({ completed => DateTime->now() });
my $ai_C1 = $tBC->derive_and_accept_instance($ai_B1, { activity => $aC }, @args);
$ai_C1->update({ completed => DateTime->now() });
# C-B
my $ai_B2 = $tCB->derive_and_accept_instance($ai_C1, { activity => $aB }, @args);
# C-D
my $ai_D = $tCD->derive_and_accept_instance($ai_C1, { activity => $aD }, @args);
# D-A : Split1 creates another cycle through Join1
$ai_D->update({ completed => DateTime->now() });
my $ai_A2 = $tDA->derive_and_accept_instance($ai_D, { activity => $aA }, @args);
ok($ai_A2->is_enabled(), 'Join1 should fire');
# B and C have active instances
( run in 1.778 second using v1.01-cache-2.11-cpan-98e64b0badf )