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