github.com/ergo-services/ergo@v1.999.224/tests/supervisor_sofo_test.go (about)

     1  package tests
     2  
     3  // - Supervisor
     4  
     5  //  - simple one for one (permanent)
     6  //    start node1
     7  //    start supevisor sv1 with genservers gs1,gs2,gs3
     8  //     .... TODO: describe
     9  
    10  import (
    11  	"fmt"
    12  	"testing"
    13  
    14  	"github.com/ergo-services/ergo"
    15  	"github.com/ergo-services/ergo/etf"
    16  	"github.com/ergo-services/ergo/gen"
    17  	"github.com/ergo-services/ergo/node"
    18  )
    19  
    20  type testSupervisorSimpleOneForOne struct {
    21  	gen.Supervisor
    22  	ch chan interface{}
    23  }
    24  
    25  func TestSupervisorSimpleOneForOne(t *testing.T) {
    26  	fmt.Printf("\n=== Test Supervisor - simple one for one\n")
    27  	fmt.Printf("Starting node nodeSvSimpleOneForOne@localhost: ")
    28  	node1, _ := ergo.StartNode("nodeSvSimpleOneForOne@localhost", "cookies", node.Options{})
    29  	if node1 == nil {
    30  		t.Fatal("can't start node")
    31  	} else {
    32  		fmt.Println("OK")
    33  	}
    34  	sv := &testSupervisorSimpleOneForOne{
    35  		ch: make(chan interface{}, 10),
    36  	}
    37  
    38  	// ===================================================================================================
    39  	// test SupervisorStrategyRestartPermanent
    40  	testCases := []ChildrenTestCase{
    41  		{
    42  			reason:   "abnormal",
    43  			statuses: []string{"new", "new", "new", "new", "new", "new"},
    44  			events:   12, // waiting for 6 terminates and 6 restarts
    45  		},
    46  		{
    47  			reason:   "normal",
    48  			statuses: []string{"new", "new", "new", "new", "new", "new"},
    49  			events:   12, // waiting for 6 terminates and 6 restarts
    50  		},
    51  		{
    52  			reason:   "shutdown",
    53  			statuses: []string{"new", "new", "new", "new", "new", "new"},
    54  			events:   12, // waiting for 6 terminates and 6 restarts
    55  		},
    56  	}
    57  
    58  	for c := range testCases {
    59  		fmt.Printf("Starting supervisor 'testSupervisorPermanent' (%s)... ", gen.SupervisorStrategyRestartPermanent)
    60  		processSV, err := node1.Spawn("testSupervisorPermanent", gen.ProcessOptions{}, sv, gen.SupervisorStrategyRestartPermanent)
    61  		if err != nil {
    62  			t.Fatal(err)
    63  		}
    64  
    65  		children := make([]etf.Pid, 6)
    66  		// starting supervisor shouldn't cause start its children
    67  		children1, err := waitNeventsSupervisorChildren(sv.ch, 0, children)
    68  		if err != nil {
    69  			t.Fatal(err)
    70  		} else {
    71  			// must be equal
    72  			statuses := []string{"empty", "empty", "empty", "empty", "empty", "empty"}
    73  			if checkExpectedChildrenStatus(children, children1, statuses) {
    74  				fmt.Println("OK")
    75  				children = children1
    76  			} else {
    77  				e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", statuses, children, children1)
    78  				t.Fatal(e)
    79  			}
    80  		}
    81  		fmt.Printf("... starting 6 children  ... ")
    82  
    83  		// start children
    84  		for i := 0; i < 6; i = i + 2 {
    85  			p, e := sv.StartChild(processSV, fmt.Sprintf("testGS%d", i/2+1), sv.ch, i)
    86  			if e != nil {
    87  				t.Fatal(e)
    88  			}
    89  			children[i] = p.Self()
    90  			// start twice. must be able to start any number of child processes
    91  			// as it doesn't register this process with the given name.
    92  			p, e = sv.StartChild(processSV, fmt.Sprintf("testGS%d", i/2+1), sv.ch, i+1)
    93  			if e != nil {
    94  				t.Fatal(e)
    95  			}
    96  			children[i+1] = p.Self()
    97  		}
    98  		if children1, err := waitNeventsSupervisorChildren(sv.ch, 6, children); err != nil {
    99  			t.Fatal(err)
   100  		} else {
   101  			// they should be equal after start
   102  			statuses := []string{"old", "old", "old", "old", "old", "old"}
   103  			if checkExpectedChildrenStatus(children, children1, statuses) {
   104  				fmt.Println("OK")
   105  			} else {
   106  				e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", statuses, children, children1)
   107  				t.Fatal(e)
   108  			}
   109  		}
   110  
   111  		// kill them all with reason = testCases[c].reason
   112  		fmt.Printf("... stopping children with '%s' reason and waiting for restarting all of them ... ", testCases[c].reason)
   113  
   114  		for k := range children {
   115  			processSV.Send(children[k], testCases[c].reason)
   116  		}
   117  
   118  		if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[c].events, children); err != nil {
   119  			t.Fatal(err)
   120  		} else {
   121  			if checkExpectedChildrenStatus(children, children1, testCases[c].statuses) {
   122  				fmt.Println("OK")
   123  				children = children1
   124  			} else {
   125  				e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", testCases[c].statuses, children, children1)
   126  				t.Fatal(e)
   127  			}
   128  		}
   129  
   130  		fmt.Printf("Stopping supervisor 'testSupervisor' (reason: %s)... ", testCases[c].reason)
   131  		processSV.Exit(testCases[c].reason)
   132  		if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[c].events-len(children), children); err != nil {
   133  			t.Fatal(err)
   134  		} else {
   135  			statuses := []string{"empty", "empty", "empty", "empty", "empty", "empty"}
   136  			if checkExpectedChildrenStatus(children, children1, statuses) {
   137  				fmt.Println("OK")
   138  			} else {
   139  				e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", statuses, children, children1)
   140  				t.Fatal(e)
   141  			}
   142  		}
   143  
   144  	}
   145  
   146  	// ===================================================================================================
   147  	// test SupervisorStrategyRestartTransient
   148  	testCases = []ChildrenTestCase{
   149  		{
   150  			reason:   "abnormal",
   151  			statuses: []string{"new", "new", "new", "new", "new", "new"},
   152  			events:   12, // waiting for 6 terminates and 6 restarts
   153  		},
   154  		{
   155  			reason:   "normal",
   156  			statuses: []string{"empty", "empty", "empty", "empty", "empty", "empty"},
   157  			events:   6, // waiting for 6 terminates
   158  		},
   159  		{
   160  			reason:   "shutdown",
   161  			statuses: []string{"empty", "empty", "empty", "empty", "empty", "empty"},
   162  			events:   6, // waiting for 6 terminates
   163  		},
   164  	}
   165  
   166  	for c := range testCases {
   167  		fmt.Printf("Starting supervisor 'testSupervisorTransient' (%s)... ", gen.SupervisorStrategyRestartTransient)
   168  		processSV, err := node1.Spawn("testSupervisorTransient", gen.ProcessOptions{}, sv, gen.SupervisorStrategyRestartTransient)
   169  		if err != nil {
   170  			t.Fatal(err)
   171  		}
   172  
   173  		children := make([]etf.Pid, 6)
   174  		// starting supervisor shouldn't cause start its children
   175  		children1, err := waitNeventsSupervisorChildren(sv.ch, 0, children)
   176  		if err != nil {
   177  			t.Fatal(err)
   178  		} else {
   179  			// must be equal
   180  			statuses := []string{"empty", "empty", "empty", "empty", "empty", "empty"}
   181  			if checkExpectedChildrenStatus(children, children1, 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", statuses, children, children1)
   186  				t.Fatal(e)
   187  			}
   188  		}
   189  		fmt.Printf("... starting 6 children  ... ")
   190  
   191  		// start children
   192  		for i := 0; i < 6; i = i + 2 {
   193  			p, e := sv.StartChild(processSV, fmt.Sprintf("testGS%d", i/2+1), sv.ch, i)
   194  			if e != nil {
   195  				t.Fatal(e)
   196  			}
   197  			children[i] = p.Self()
   198  			// start twice. must be able to start any number of child processes
   199  			// as it doesn't register this process with the given name.
   200  			p, e = sv.StartChild(processSV, fmt.Sprintf("testGS%d", i/2+1), sv.ch, i+1)
   201  			if e != nil {
   202  				t.Fatal(e)
   203  			}
   204  			children[i+1] = p.Self()
   205  		}
   206  		if children1, err := waitNeventsSupervisorChildren(sv.ch, 6, children); err != nil {
   207  			t.Fatal(err)
   208  		} else {
   209  			// they should be equal after start
   210  			statuses := []string{"old", "old", "old", "old", "old", "old"}
   211  			if checkExpectedChildrenStatus(children, children1, statuses) {
   212  				fmt.Println("OK")
   213  			} else {
   214  				e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", statuses, children, children1)
   215  				t.Fatal(e)
   216  			}
   217  		}
   218  
   219  		// kill them all with reason = testCases[c].reason
   220  		fmt.Printf("... stopping children with '%s' reason and waiting for restarting some of them ... ", testCases[c].reason)
   221  
   222  		for k := range children {
   223  			processSV.Send(children[k], testCases[c].reason)
   224  		}
   225  
   226  		if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[c].events, children); err != nil {
   227  			t.Fatal(err)
   228  		} else {
   229  			if checkExpectedChildrenStatus(children, children1, testCases[c].statuses) {
   230  				fmt.Println("OK")
   231  				children = children1
   232  			} else {
   233  				e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", testCases[c].statuses, children, children1)
   234  				t.Fatal(e)
   235  			}
   236  		}
   237  
   238  		fmt.Printf("Stopping supervisor 'testSupervisor' (reason: %s)... ", testCases[c].reason)
   239  		processSV.Exit(testCases[c].reason)
   240  		if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[c].events-len(children), children); err != nil {
   241  			t.Fatal(err)
   242  		} else {
   243  			statuses := []string{"empty", "empty", "empty", "empty", "empty", "empty"}
   244  			if checkExpectedChildrenStatus(children, children1, statuses) {
   245  				fmt.Println("OK")
   246  			} else {
   247  				e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", statuses, children, children1)
   248  				t.Fatal(e)
   249  			}
   250  		}
   251  
   252  	}
   253  
   254  	// ===================================================================================================
   255  	// test SupervisorStrategyRestartTemporary
   256  	testCases = []ChildrenTestCase{
   257  		{
   258  			reason:   "abnormal",
   259  			statuses: []string{"empty", "empty", "empty", "empty", "empty", "empty"},
   260  			events:   6, // waiting for 6 terminates
   261  		},
   262  		{
   263  			reason:   "normal",
   264  			statuses: []string{"empty", "empty", "empty", "empty", "empty", "empty"},
   265  			events:   6, // waiting for 6 terminates
   266  		},
   267  		{
   268  			reason:   "shutdown",
   269  			statuses: []string{"empty", "empty", "empty", "empty", "empty", "empty"},
   270  			events:   6, // waiting for 6 terminates
   271  		},
   272  	}
   273  
   274  	for c := range testCases {
   275  		fmt.Printf("Starting supervisor 'testSupervisorTemporary' (%s)... ", gen.SupervisorStrategyRestartTemporary)
   276  		processSV, err := node1.Spawn("testSupervisorTemporary", gen.ProcessOptions{}, sv, gen.SupervisorStrategyRestartTemporary)
   277  		if err != nil {
   278  			t.Fatal(err)
   279  		}
   280  
   281  		children := make([]etf.Pid, 6)
   282  		// starting supervisor shouldn't cause start its children
   283  		children1, err := waitNeventsSupervisorChildren(sv.ch, 0, children)
   284  		if err != nil {
   285  			t.Fatal(err)
   286  		} else {
   287  			// must be equal
   288  			statuses := []string{"empty", "empty", "empty", "empty", "empty", "empty"}
   289  			if checkExpectedChildrenStatus(children, children1, statuses) {
   290  				fmt.Println("OK")
   291  				children = children1
   292  			} else {
   293  				e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", statuses, children, children1)
   294  				t.Fatal(e)
   295  			}
   296  		}
   297  		fmt.Printf("... starting 6 children  ... ")
   298  
   299  		// start children
   300  		for i := 0; i < 6; i = i + 2 {
   301  			p, e := sv.StartChild(processSV, fmt.Sprintf("testGS%d", i/2+1), sv.ch, i)
   302  			if e != nil {
   303  				t.Fatal(e)
   304  			}
   305  			children[i] = p.Self()
   306  			// start twice. must be able to start any number of child processes
   307  			// as it doesn't register this process with the given name.
   308  			p, e = sv.StartChild(processSV, fmt.Sprintf("testGS%d", i/2+1), sv.ch, i+1)
   309  			if e != nil {
   310  				t.Fatal(e)
   311  			}
   312  			children[i+1] = p.Self()
   313  		}
   314  		if children1, err := waitNeventsSupervisorChildren(sv.ch, 6, children); err != nil {
   315  			t.Fatal(err)
   316  		} else {
   317  			// they should be equal after start
   318  			statuses := []string{"old", "old", "old", "old", "old", "old"}
   319  			if checkExpectedChildrenStatus(children, children1, statuses) {
   320  				fmt.Println("OK")
   321  			} else {
   322  				e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", statuses, children, children1)
   323  				t.Fatal(e)
   324  			}
   325  		}
   326  
   327  		// kill them all with reason = testCases[c].reason
   328  		fmt.Printf("... stopping children with '%s' reason and waiting for exiting all of them ... ", testCases[c].reason)
   329  
   330  		for k := range children {
   331  			processSV.Send(children[k], testCases[c].reason)
   332  		}
   333  
   334  		if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[c].events, children); err != nil {
   335  			t.Fatal(err)
   336  		} else {
   337  			if checkExpectedChildrenStatus(children, children1, testCases[c].statuses) {
   338  				fmt.Println("OK")
   339  				children = children1
   340  			} else {
   341  				e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", testCases[c].statuses, children, children1)
   342  				t.Fatal(e)
   343  			}
   344  		}
   345  
   346  		fmt.Printf("Stopping supervisor 'testSupervisor' (reason: %s)... ", testCases[c].reason)
   347  		processSV.Exit(testCases[c].reason)
   348  		if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[c].events-len(children), children); err != nil {
   349  			t.Fatal(err)
   350  		} else {
   351  			statuses := []string{"empty", "empty", "empty", "empty", "empty", "empty"}
   352  			if checkExpectedChildrenStatus(children, children1, statuses) {
   353  				fmt.Println("OK")
   354  			} else {
   355  				e := fmt.Errorf("got something else except we expected (%v). old: %v new: %v", statuses, children, children1)
   356  				t.Fatal(e)
   357  			}
   358  		}
   359  
   360  	}
   361  }
   362  
   363  func (ts *testSupervisorSimpleOneForOne) Init(args ...etf.Term) (gen.SupervisorSpec, error) {
   364  	restart := args[0].(string)
   365  	return gen.SupervisorSpec{
   366  		Children: []gen.SupervisorChildSpec{
   367  			{
   368  				Name:  "testGS1",
   369  				Child: &testSupervisorGenServer{},
   370  			},
   371  			{
   372  				Name:  "testGS2",
   373  				Child: &testSupervisorGenServer{},
   374  			},
   375  			{
   376  				Name:  "testGS3",
   377  				Child: &testSupervisorGenServer{},
   378  			},
   379  		},
   380  		Strategy: gen.SupervisorStrategy{
   381  			Type:      gen.SupervisorStrategySimpleOneForOne,
   382  			Intensity: 10,
   383  			Period:    5,
   384  			Restart:   restart,
   385  		},
   386  	}, nil
   387  }