github.com/ergo-services/ergo@v1.999.224/tests/supervisor_ofa_test.go (about) 1 package tests 2 3 // - Supervisor 4 5 // - one for all (permanent) 6 // start node1 7 // start supevisor sv1 with genservers gs1,gs2,gs3 8 // gs1.stop(normal) (sv1 stoping gs1) 9 // (sv1 stoping gs2,gs3) 10 // (sv1 starting gs1,gs2,gs3) 11 // gs2.stop(shutdown) (sv1 stoping gs2) 12 // (sv1 stoping gs1,gs3) 13 // (sv1 starting gs1,gs2,gs3) 14 // gs3.stop(panic) (sv1 stoping gs3) 15 // (sv1 stoping gs1,gs2) 16 // (sv1 starting gs1,gs2,gs3) 17 18 // - one for all (transient) 19 // start node1 20 // start supevisor sv1 with genservers gs1,gs2,gs3 21 // gs3.stop(panic) (sv1 stoping gs3) 22 // (sv1 stopping gs1, gs2) 23 // (sv1 starting gs1, gs2, gs3) 24 25 // gs1.stop(normal) (sv1 stoping gs1) 26 // ( gs2, gs3 - still working) 27 // gs2.stop(shutdown) (sv1 stoping gs2) 28 // (gs3 - still working) 29 30 // - one for all (temoporary) 31 // start node1 32 // start supevisor sv1 with genservers gs1,gs2,gs3 33 34 // gs3.stop(panic) (sv1 stoping gs3) 35 // (sv1 stopping gs1, gs2) 36 37 // start again gs1, gs2, gs3 via sv1 38 // gs1.stop(normal) (sv1 stopping gs1) 39 // (gs2, gs3 are still running) 40 // gs2.stop(shutdown) (sv1 stopping gs2) 41 // (gs3 are still running) 42 43 import ( 44 "fmt" 45 "testing" 46 47 "github.com/ergo-services/ergo" 48 "github.com/ergo-services/ergo/etf" 49 "github.com/ergo-services/ergo/gen" 50 "github.com/ergo-services/ergo/node" 51 ) 52 53 type testSupervisorOneForAll struct { 54 gen.Supervisor 55 ch chan interface{} 56 } 57 58 type ChildrenTestCase struct { 59 reason string 60 statuses []string 61 events int 62 } 63 64 func TestSupervisorOneForAll(t *testing.T) { 65 fmt.Printf("\n=== Test Supervisor - one for all\n") 66 fmt.Printf("Starting node nodeSvOneForAll@localhost: ") 67 node1, _ := ergo.StartNode("nodeSvOneForAll@localhost", "cookies", node.Options{}) 68 if node1 == nil { 69 t.Fatal("can't start node") 70 } else { 71 fmt.Println("OK") 72 } 73 74 // =================================================================================================== 75 // test SupervisorStrategyRestartPermanent 76 fmt.Printf("Starting supervisor 'testSupervisorPermanent' (%s)... ", gen.SupervisorStrategyRestartPermanent) 77 sv := &testSupervisorOneForAll{ 78 ch: make(chan interface{}, 10), 79 } 80 processSV, err := node1.Spawn("testSupervisorPermanent", gen.ProcessOptions{}, sv, gen.SupervisorStrategyRestartPermanent, sv.ch) 81 if err != nil { 82 t.Fatal(err) 83 } 84 children := make([]etf.Pid, 3) 85 children, err = waitNeventsSupervisorChildren(sv.ch, 3, children) 86 if err != nil { 87 t.Fatal(err) 88 } else { 89 fmt.Println("OK") 90 } 91 92 // testing permanent 93 testCases := []ChildrenTestCase{ 94 { 95 reason: "normal", 96 statuses: []string{"new", "new", "new"}, 97 events: 6, // waiting for 3 terminating and 3 starting 98 }, 99 { 100 reason: "abnormal", 101 statuses: []string{"new", "new", "new"}, 102 events: 6, 103 }, 104 { 105 reason: "shutdown", 106 statuses: []string{"new", "new", "new"}, 107 events: 6, 108 }, 109 } 110 for i := range children { 111 fmt.Printf("... stopping child %d with '%s' reason and waiting for restarting all of them ... ", i+1, testCases[i].reason) 112 processSV.Send(children[i], testCases[i].reason) // stopping child 113 114 if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[i].events, children); err != nil { 115 t.Fatal(err) 116 } else { 117 if checkExpectedChildrenStatus(children, children1, testCases[i].statuses) { 118 fmt.Println("OK") 119 children = children1 120 } else { 121 e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", testCases[i].statuses, children, children1) 122 t.Fatal(e) 123 } 124 } 125 } 126 127 fmt.Printf("Stopping supervisor 'testSupervisorPermanent' (%s)... ", gen.SupervisorStrategyRestartPermanent) 128 processSV.Exit("x") 129 if children1, err := waitNeventsSupervisorChildren(sv.ch, 3, children); err != nil { 130 t.Fatal(err) 131 } else { 132 statuses := []string{"empty", "empty", "empty"} 133 if checkExpectedChildrenStatus(children[:], children1[:], statuses) { 134 fmt.Println("OK") 135 children = children1 136 } else { 137 e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", statuses, children, children1) 138 t.Fatal(e) 139 } 140 } 141 142 // =================================================================================================== 143 // test SupervisorStrategyRestartTransient 144 fmt.Printf("Starting supervisor 'testSupervisorTransient' (%s)... ", gen.SupervisorStrategyRestartTransient) 145 sv = &testSupervisorOneForAll{ 146 ch: make(chan interface{}, 10), 147 } 148 processSV, _ = node1.Spawn("testSupervisorTransient", gen.ProcessOptions{}, sv, gen.SupervisorStrategyRestartTransient, sv.ch) 149 children, err = waitNeventsSupervisorChildren(sv.ch, 3, children) 150 if err != nil { 151 t.Fatal(err) 152 } else { 153 fmt.Println("OK") 154 } 155 156 // testing transient 157 testCases = []ChildrenTestCase{ 158 { 159 reason: "normal", 160 statuses: []string{"empty", "old", "old"}, 161 events: 1, // waiting for 1 terminate 162 }, 163 { 164 reason: "abnormal", 165 statuses: []string{"empty", "new", "new"}, 166 events: 4, // waiting for 2 terminates and 2 starts 167 }, 168 { 169 reason: "shutdown", 170 statuses: []string{"empty", "old", "empty"}, 171 events: 1, // waiting for 1 terminate 172 }, 173 } 174 for i := range children { 175 fmt.Printf("... stopping child %d with '%s' reason and waiting for restarting all of them if reason != normal ... ", i+1, testCases[i].reason) 176 processSV.Send(children[i], testCases[i].reason) // stopping child 177 178 if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[i].events, children); err != nil { 179 t.Fatal(err) 180 } else { 181 if checkExpectedChildrenStatus(children[:], children1[:], testCases[i].statuses) { 182 fmt.Println("OK") 183 children = children1 184 } else { 185 e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", testCases[i].statuses, children, children1) 186 t.Fatal(e) 187 } 188 } 189 } 190 191 fmt.Printf("Stopping supervisor 'testSupervisorTransient' (%s)... ", gen.SupervisorStrategyRestartTransient) 192 processSV.Exit("x") 193 if children1, err := waitNeventsSupervisorChildren(sv.ch, 1, children); err != nil { 194 t.Fatal(err) 195 } else { 196 statuses := []string{"empty", "empty", "empty"} 197 if checkExpectedChildrenStatus(children[:], children1[:], statuses) { 198 fmt.Println("OK") 199 children = children1 200 } else { 201 e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", statuses, children, children1) 202 t.Fatal(e) 203 } 204 } 205 206 // =================================================================================================== 207 // test SupervisorStrategyRestartTemporary 208 209 // testing temporary 210 // A temporary child process is never restarted (even when the supervisor's 211 // restart strategy is rest_for_one or one_for_all and a sibling's death 212 // causes the temporary process to be terminated). 213 testCases = []ChildrenTestCase{ 214 { 215 reason: "normal", 216 statuses: []string{"empty", "old", "old"}, 217 events: 1, // waiting for 1 terminate 218 }, 219 { 220 reason: "abnormal", 221 statuses: []string{"old", "empty", "old"}, 222 events: 1, // waiting for 1 terminate 223 }, 224 { 225 reason: "shutdown", 226 statuses: []string{"old", "old", "empty"}, 227 events: 1, // waiting for 1 terminate 228 }, 229 } 230 231 for i := range testCases { 232 fmt.Printf("Starting supervisor 'testSupervisorTemporary' (%s)... ", gen.SupervisorStrategyRestartTemporary) 233 sv = &testSupervisorOneForAll{ 234 ch: make(chan interface{}, 10), 235 } 236 processSV, _ = node1.Spawn("testSupervisorTemporary", gen.ProcessOptions{}, sv, gen.SupervisorStrategyRestartTemporary, sv.ch) 237 children, err = waitNeventsSupervisorChildren(sv.ch, 3, children) 238 if err != nil { 239 t.Fatal(err) 240 } else { 241 fmt.Println("OK") 242 } 243 244 fmt.Printf("... stopping child %d with '%s' reason and no one should be restarted ... ", i+1, testCases[i].reason) 245 processSV.Send(children[i], testCases[i].reason) // stopping child 246 247 if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[i].events, children); err != nil { 248 t.Fatal(err) 249 } else { 250 if checkExpectedChildrenStatus(children[:], children1[:], testCases[i].statuses) { 251 fmt.Println("OK") 252 children = children1 253 } else { 254 e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", testCases[i].statuses, children, children1) 255 t.Fatal(e) 256 } 257 } 258 259 fmt.Printf("Stopping supervisor 'testSupervisorTemporary' (%s)... ", gen.SupervisorStrategyRestartTemporary) 260 processSV.Exit("x") 261 if children1, err := waitNeventsSupervisorChildren(sv.ch, len(children)-testCases[i].events, children); err != nil { 262 t.Fatal(err) 263 } else { 264 statuses := []string{"empty", "empty", "empty"} 265 if checkExpectedChildrenStatus(children[:], children1[:], statuses) { 266 fmt.Println("OK") 267 children = children1 268 } else { 269 e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", statuses, children, children1) 270 t.Fatal(e) 271 } 272 } 273 } 274 275 } 276 277 func (ts *testSupervisorOneForAll) Init(args ...etf.Term) (gen.SupervisorSpec, error) { 278 restart := args[0].(string) 279 ch := args[1].(chan interface{}) 280 return gen.SupervisorSpec{ 281 Children: []gen.SupervisorChildSpec{ 282 { 283 Name: "testGS1", 284 Child: &testSupervisorGenServer{}, 285 Args: []etf.Term{ch, 0}, 286 }, 287 { 288 Name: "testGS2", 289 Child: &testSupervisorGenServer{}, 290 Args: []etf.Term{ch, 1}, 291 }, 292 { 293 Name: "testGS3", 294 Child: &testSupervisorGenServer{}, 295 Args: []etf.Term{ch, 2}, 296 }, 297 }, 298 Strategy: gen.SupervisorStrategy{ 299 Type: gen.SupervisorStrategyOneForAll, 300 Intensity: 10, 301 Period: 5, 302 Restart: restart, 303 }, 304 }, nil 305 }