try {
    $msg = '->addTransition() fails if the target source does not exist.';
    $fsm->addTransition('off', 'explode', 'exploded');
    $t->fail($msg);
} catch (Exception $e) {
    $t->pass($msg);
}
try {
    $msg = '->addTransition() fails if the transition already exists.';
    $fsm->addTransition('on', 'push', 'broken');
    $t->fail($msg);
} catch (Exception $e) {
    $t->pass($msg);
}
$t->diag('->setState()');
$fsm->setState('on');
$t->is($fsm->getState(), 'on', '->setState() changes the state');
$fsm->setState(null);
$t->is($fsm->getState(), 'off', '->setState() to null sets the initial state');
try {
    $msg = '->setState() fails if the state does not exist.';
    $fsm->setState('exploded');
    $t->fail($msg);
} 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');