This repository has been archived by the owner on Dec 5, 2019. It is now read-only.
/
index.js
141 lines (113 loc) · 3.03 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
var tape = require('tape')
var fsm = require('../')
var simple = {START: {ok: 'END'}, END: {}}
var stream =
{
START: {
data : 'START',
pause : 'PAUSED',
end : 'END',
error : 'ERROR'
},
PAUSED: {
pause : 'PAUSED',
resume : 'START',
error : 'ERROR'
},
ERROR: {},
END: {}
}
var update =
{
START: {
need_read: 'READY',
end: 'END'
},
READY: { need_read: 'READY', reading: 'START' },
END: {}
}
var updown =
{
UP: {down: 'DOWN'},
DOWN: {up: 'UP'}
}
//(up,down)*
var liftsafe =
{
SAFE: {
error: 'FAIL',
up: 'SAFE',
down: 'SAFE'
},
FAIL: {
repair: 'SAFE'
}
}
//((up|down)*|(error,repair))*
var lift =
{
'UP-SAFE': {down: 'DOWN-SAFE', error: 'UP-FAIL'},
'DOWN-SAFE': {up: 'UP-SAFE', error: 'DOWN-FAIL'},
'UP-FAIL': {repair: 'UP-SAFE'},
'DOWN-FAIL': {repair: 'DOWN-SAFE'}
}
var valids = [simple, stream, update]
var invalids = [
{START: {ok: 'NOT_A_STATE'}},
]
tape('valid', function (t) {
valids.forEach(function (e) {
t.ok(fsm.validate(e))
})
t.end()
})
tape('invalid', function (t) {
invalids.forEach(function (e) {
t.throws(function () {
fsm.validate(e)
})
})
t.end()
})
tape('deadlock', function (t) {
t.deepEqual(fsm.deadlock(stream), ['ERROR', 'END'])
t.deepEqual(fsm.deadlock(update), ['END'])
t.end()
})
var livelock = {
START: {ok: 'START'},
END: {}
}
//what information should livelock return?
//the states that cannot reach the given terminal states.
tape('livelock', function (t) {
t.deepEqual(fsm.livelock(livelock, ['END']), ['START'])
t.end()
})
//take 2 fsm, and combine them into one, so that reachability etc
//can be calculated. they must share start and terimanal states
// when ever there is an event that both fsms share,
// they can only take that transition when they both allow it.
// Enforce that 'data' cannot occur after 'end'.
// {START: {data: START, end: END}, END: {}}
// Enforce that 'data' cannot occur when paused
// {START: {data: START, pause: PAUSED}, PAUSED: {resume: START}}
// Hmm, this would allow end to happen when paused.
// take a starting state, then expand all shared events from that state,
// then expand all non-shared states, creating split states.
//Enforce up and down must alternate.
// {UP: {down: DOWN}, DOWN: {up: UP}}
//if the lift breaks, it must not move, until repaired.
//this means it can actually fail in the UP or DOWN position,
//and when repaired, it must continue from there...
//but to express that in fsm it's easier to express the two aspects separately.
// now, in with some combinations of fsms, certain moves may become impossible.
// this is an error!
tape('combine', function (t) {
var combined = fsm.combine(updown, liftsafe, 'DOWN', 'SAFE')
console.log(combined)
t.deepEqual(combined, lift)
t.end()
})
// now, it's possible to combine two fsms in a way that breaks one of them.
// if there is a state missing in the new one, or a transition that is now impossible?