Compare commits

...

2 Commits

1
.gitignore vendored

@ -1 +1,2 @@
node_modules node_modules
npm-debug.log*

@ -1,31 +1,102 @@
# machina-factory-bugcase # machina-factory-bugcase
A demonstration of a bug in machina v2.0.2, where a child FSM factory is called multiple times when specified as part of a config object. A demonstration of a bug in machina v2.0.2, where a child FSM factory is called erroneously during any `handle` command that's received by a child FSM, even if no state transition takes place in the parent.
What should happen: What should happen:
``` ```
(fsm.0) Parent state 1 reached (fsm.0) Parent state 1 reached
Creating child Creating child for state 2
(fsm.1) Child state A reached (fsm.1) Child state A reached
(fsm.0) Parent state 2 reached (fsm.0) Parent state 2 reached
Creating child (fsm.1) Child state B reached
Creating child for state 3
(fsm.2) Child state A reached (fsm.2) Child state A reached
(fsm.0) Parent state 3 reached
(fsm.2) Child state B reached (fsm.2) Child state B reached
Parent done! Returning to state 2 one last time...
Creating child for state 2
(fsm.3) Child state A reached
(fsm.0) Parent state 2 reached
(fsm.3) Child state B reached
``` ```
What happens instead: What happens instead:
``` ```
(fsm.0) Parent state 1 reached (fsm.0) Parent state 1 reached
Creating child Creating child for state 2
(fsm.1) Child state A reached (fsm.1) Child state A reached
Creating child (fsm.0) Parent state 2 reached
Creating child for state 2
(fsm.2) Child state A reached (fsm.2) Child state A reached
(fsm.2) Child state B reached
Creating child for state 2
(fsm.3) Child state A reached
Creating child for state 3
(fsm.4) Child state A reached
(fsm.0) Parent state 3 reached
Creating child for state 3
(fsm.5) Child state A reached
(fsm.5) Child state B reached
Creating child for state 3
(fsm.6) Child state A reached
Parent done! Returning to state 2 one last time...
Creating child for state 2
(fsm.7) Child state A reached
(fsm.0) Parent state 2 reached (fsm.0) Parent state 2 reached
Creating child Creating child for state 2
(fsm.8) Child state A reached
(fsm.8) Child state B reached
Creating child for state 2
(fsm.9) Child state A reached
```
The result is even more wrong when this bug is combined with the duplicate FSM creation bug (as demonstrated in the `master` branch of this repository):
```
(fsm.0) Parent state 1 reached
Creating child for state 2
(fsm.1) Child state A reached
Creating child for state 2
(fsm.2) Child state A reached
(fsm.0) Parent state 2 reached
Creating child for state 2
(fsm.3) Child state A reached (fsm.3) Child state A reached
Creating child Creating child for state 2
(fsm.4) Child state A reached (fsm.4) Child state A reached
(fsm.4) Child state B reached (fsm.4) Child state B reached
Creating child for state 2
(fsm.5) Child state A reached
Creating child for state 2
(fsm.6) Child state A reached
Creating child for state 3
(fsm.7) Child state A reached
Creating child for state 3
(fsm.8) Child state A reached
(fsm.0) Parent state 3 reached
Creating child for state 3
(fsm.9) Child state A reached
Creating child for state 3
(fsm.10) Child state A reached
(fsm.10) Child state B reached
Creating child for state 3
(fsm.11) Child state A reached
Creating child for state 3
(fsm.12) Child state A reached
Parent done! Returning to state 2 one last time...
Creating child for state 2
(fsm.13) Child state A reached
Creating child for state 2
(fsm.14) Child state A reached
(fsm.0) Parent state 2 reached
Creating child for state 2
(fsm.15) Child state A reached
Creating child for state 2
(fsm.16) Child state A reached
(fsm.16) Child state B reached
Creating child for state 2
(fsm.17) Child state A reached
Creating child for state 2
(fsm.18) Child state A reached
``` ```

@ -4,6 +4,9 @@ const machina = require("machina");
let parent = new machina.Fsm({ let parent = new machina.Fsm({
initialState: "one", initialState: "one",
memory: {
done: false
},
states: { states: {
one: { one: {
_onEnter: function () { _onEnter: function () {
@ -19,9 +22,32 @@ let parent = new machina.Fsm({
}, },
_child: { _child: {
factory: function () { factory: function () {
console.log("Creating child"); console.log("Creating child for state 2");
return createChild(); return createChild();
} }
},
done: function () {
if (!this.memory.done) {
return this.transition("three");
}
}
},
three: {
_onEnter: function () {
console.log(`(${this.namespace}) Parent state 3 reached`);
return this.handle("childAction");
},
_child: {
factory: function () {
console.log("Creating child for state 3");
return createChild();
}
},
done: function () {
this.memory.done = true;
console.log("Parent done! Returning to state 2 one last time...");
return this.transition("two");
} }
} }
} }
@ -42,6 +68,7 @@ function createChild() {
b: { b: {
_onEnter: function () { _onEnter: function () {
console.log(`(${this.namespace}) Child state B reached`); console.log(`(${this.namespace}) Child state B reached`);
return this.handle("done");
} }
} }
} }

Loading…
Cancel
Save