} catch (Exception $e) {
    $t->pass($msg);
}
$t->diag('->process()');
$t->is($fsm->getState(), 'off', '->getState() returns the inital state');
$t->is($fsm->process('push')->getState(), 'on', '->process() changes the state according to the transitions');
$t->is($fsm->process('smash')->getState(), 'broken', '->process() changes the state according to the transitions');
$t->is($fsm->processMany(array('replace', 'push', 'short out'))->getState(), 'burned out', '->processMany() processes multiple states');
try {
    $msg = '->process() fails when there is no transition defined for an input';
    $fsm->process('twist');
    $t->fail($msg);
} catch (Exception $e) {
    $t->pass($msg);
}
$fsm->setDefaultTransition('broken');
$t->is($fsm->process('twist')->getState(), 'broken', '->process() uses the default transition if possible');
$fsm->setDefaultTransition(null);
$fsm->reset();
$t->is($fsm->getState(), 'off', '->reset() resets the state');
$t->diag('exit actions');
$fsm->reset();
$exit = new CounterAction();
$fsm->addExitAction('off', $exit);
$fsm->process('push');
$t->is($exit->counter, 1, '->process() calls an exit action when leaving a state');
$fsm->process('push');
$t->is($exit->counter, 1, '->process() does not call an exit action when not leaving the state');
$fsm->process('wait');
$t->is($exit->counter, 1, '->process() does not call an exit action when the state does not change');
$t->diag('entry actions');