Skip to content

Commit 6a1ae07

Browse files
knopers8teo
authored andcommitted
[core] add safestate unit test, demonstrate two bugs
1 parent 0fefbb3 commit 6a1ae07

1 file changed

Lines changed: 158 additions & 0 deletions

File tree

core/workflow/safestate_test.go

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package workflow
2+
3+
import (
4+
"github.com/AliceO2Group/Control/core/task"
5+
. "github.com/onsi/ginkgo/v2"
6+
. "github.com/onsi/gomega"
7+
"testing"
8+
)
9+
10+
var _ = Describe("safe state", func() {
11+
Describe("merging states", func() {
12+
When("the state we are updating belongs to a role which is a leaf in the tree", func() {
13+
It("should be overwritten", func() {
14+
cr := &callRole{
15+
roleBase: roleBase{state: SafeState{state: task.CONFIGURED}},
16+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: true},
17+
}
18+
cr.state.merge(task.RUNNING, cr)
19+
Expect(cr.GetState()).To(Equal(task.RUNNING))
20+
21+
tr := &taskRole{
22+
roleBase: roleBase{state: SafeState{state: task.CONFIGURED}},
23+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: true},
24+
}
25+
tr.state.merge(task.RUNNING, tr)
26+
Expect(tr.GetState()).To(Equal(task.RUNNING))
27+
})
28+
})
29+
When("the state is healthy and is merged with ERROR state", func() {
30+
It("should become ERROR", func() {
31+
ar := &aggregatorRole{roleBase: roleBase{state: SafeState{state: task.CONFIGURED}}}
32+
ar.state.merge(task.ERROR, ar)
33+
Expect(ar.GetState()).To(Equal(task.ERROR))
34+
})
35+
})
36+
When("the state is MIXED and is merged with ERROR state", func() {
37+
It("should become ERROR", func() {
38+
ar := &aggregatorRole{roleBase: roleBase{state: SafeState{state: task.MIXED}}}
39+
ar.state.merge(task.ERROR, ar)
40+
Expect(ar.GetState()).To(Equal(task.ERROR))
41+
})
42+
})
43+
When("the role has at least two sub-roles, the state is ERROR and is merged with MIXED state", func() {
44+
It("should stay ERROR", func() {
45+
// because if we have two sub-roles A and B, where A is in ERROR and B enters MIXED,
46+
// it should not invalidate the ERROR state.
47+
subroles := make([]Role, 2)
48+
subroles[0] = &taskRole{
49+
roleBase: roleBase{state: SafeState{state: task.ERROR}},
50+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: true},
51+
}
52+
subroles[1] = &taskRole{
53+
roleBase: roleBase{state: SafeState{state: task.MIXED}},
54+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: true},
55+
}
56+
ar := &aggregatorRole{
57+
roleBase: roleBase{state: SafeState{state: task.ERROR}},
58+
aggregator: aggregator{subroles},
59+
}
60+
ar.state.merge(task.MIXED, ar)
61+
Expect(ar.GetState()).To(Equal(task.ERROR)) // FIXME: this fails
62+
})
63+
})
64+
When("the role has one sub-role, the state is ERROR and is merged with MIXED state", func() {
65+
It("should become MIXED", func() {
66+
subroles := make([]Role, 1)
67+
subroles[0] = &aggregatorRole{roleBase: roleBase{state: SafeState{state: task.MIXED}}}
68+
ar := &aggregatorRole{
69+
roleBase: roleBase{state: SafeState{state: task.ERROR}},
70+
aggregator: aggregator{subroles},
71+
}
72+
ar.state.merge(task.MIXED, ar)
73+
Expect(ar.GetState()).To(Equal(task.MIXED))
74+
})
75+
})
76+
When("the role has at least two sub-roles, state is ERROR and is merged with a healthy state", func() {
77+
It("move to the corresponding healthy state", func() {
78+
subroles := make([]Role, 2)
79+
subroles[0] = &taskRole{
80+
roleBase: roleBase{state: SafeState{state: task.CONFIGURED}},
81+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: true},
82+
}
83+
subroles[1] = &taskRole{
84+
roleBase: roleBase{state: SafeState{state: task.CONFIGURED}},
85+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: true},
86+
}
87+
ar := &aggregatorRole{
88+
roleBase: roleBase{state: SafeState{state: task.ERROR}},
89+
aggregator: aggregator{subroles},
90+
}
91+
ar.state.merge(task.CONFIGURED, ar)
92+
Expect(ar.GetState()).To(Equal(task.CONFIGURED))
93+
})
94+
})
95+
When("the role has at least two sub-roles, state is ERROR and is merged with a healthy state, but other sub-role stays in ERROR", func() {
96+
It("should stay in ERROR", func() {
97+
subroles := make([]Role, 2)
98+
subroles[0] = &taskRole{
99+
roleBase: roleBase{state: SafeState{state: task.ERROR}},
100+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: true},
101+
}
102+
subroles[1] = &taskRole{
103+
roleBase: roleBase{state: SafeState{state: task.CONFIGURED}},
104+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: true},
105+
}
106+
ar := &aggregatorRole{
107+
roleBase: roleBase{state: SafeState{state: task.ERROR}},
108+
aggregator: aggregator{subroles},
109+
}
110+
ar.state.merge(task.STANDBY, ar)
111+
Expect(ar.GetState()).To(Equal(task.ERROR))
112+
})
113+
})
114+
When("the role has at least two sub-roles, the state is healthy and one of non-critical sub-roles enters ERROR", func() {
115+
It("should remain in the same state", func() {
116+
subroles := make([]Role, 2)
117+
subroles[0] = &taskRole{
118+
roleBase: roleBase{state: SafeState{state: task.ERROR}},
119+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: false},
120+
}
121+
subroles[1] = &taskRole{
122+
roleBase: roleBase{state: SafeState{state: task.CONFIGURED}},
123+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: true},
124+
}
125+
ar := &aggregatorRole{
126+
roleBase: roleBase{state: SafeState{state: task.CONFIGURED}},
127+
aggregator: aggregator{subroles},
128+
}
129+
ar.state.merge(task.ERROR, ar)
130+
Expect(ar.GetState()).To(Equal(task.CONFIGURED)) // fixme: this fails
131+
})
132+
})
133+
When("the role has at least two sub-roles, the state is healthy and one of critical sub-roles enters a different state than the other", func() {
134+
It("should enter MIXED", func() {
135+
subroles := make([]Role, 2)
136+
subroles[0] = &taskRole{
137+
roleBase: roleBase{state: SafeState{state: task.RUNNING}},
138+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: true},
139+
}
140+
subroles[1] = &taskRole{
141+
roleBase: roleBase{state: SafeState{state: task.DONE}},
142+
Traits: task.Traits{Trigger: "", Await: "", Timeout: "", Critical: true},
143+
}
144+
ar := &aggregatorRole{
145+
roleBase: roleBase{state: SafeState{state: task.RUNNING}},
146+
aggregator: aggregator{subroles},
147+
}
148+
ar.state.merge(task.DONE, ar)
149+
Expect(ar.GetState()).To(Equal(task.MIXED))
150+
})
151+
})
152+
})
153+
})
154+
155+
func TestSafeState(t *testing.T) {
156+
RegisterFailHandler(Fail)
157+
RunSpecs(t, "Safe State Test Suite")
158+
}

0 commit comments

Comments
 (0)