github.com/david-imola/snapd@v0.0.0-20210611180407-2de8ddeece6d/overlord/stateengine_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package overlord_test
    21  
    22  import (
    23  	"errors"
    24  
    25  	. "gopkg.in/check.v1"
    26  
    27  	"github.com/snapcore/snapd/overlord"
    28  	"github.com/snapcore/snapd/overlord/state"
    29  )
    30  
    31  type stateEngineSuite struct{}
    32  
    33  var _ = Suite(&stateEngineSuite{})
    34  
    35  func (ses *stateEngineSuite) TestNewAndState(c *C) {
    36  	s := state.New(nil)
    37  	se := overlord.NewStateEngine(s)
    38  
    39  	c.Check(se.State(), Equals, s)
    40  }
    41  
    42  type fakeManager struct {
    43  	name                      string
    44  	calls                     *[]string
    45  	ensureError, startupError error
    46  }
    47  
    48  func (fm *fakeManager) StartUp() error {
    49  	*fm.calls = append(*fm.calls, "startup:"+fm.name)
    50  	return fm.startupError
    51  }
    52  
    53  func (fm *fakeManager) Ensure() error {
    54  	*fm.calls = append(*fm.calls, "ensure:"+fm.name)
    55  	return fm.ensureError
    56  }
    57  
    58  func (fm *fakeManager) Stop() {
    59  	*fm.calls = append(*fm.calls, "stop:"+fm.name)
    60  }
    61  
    62  func (fm *fakeManager) Wait() {
    63  	*fm.calls = append(*fm.calls, "wait:"+fm.name)
    64  }
    65  
    66  var _ overlord.StateManager = (*fakeManager)(nil)
    67  
    68  func (ses *stateEngineSuite) TestStartUp(c *C) {
    69  	s := state.New(nil)
    70  	se := overlord.NewStateEngine(s)
    71  
    72  	calls := []string{}
    73  
    74  	mgr1 := &fakeManager{name: "mgr1", calls: &calls}
    75  	mgr2 := &fakeManager{name: "mgr2", calls: &calls}
    76  
    77  	se.AddManager(mgr1)
    78  	se.AddManager(mgr2)
    79  
    80  	err := se.StartUp()
    81  	c.Assert(err, IsNil)
    82  	c.Check(calls, DeepEquals, []string{"startup:mgr1", "startup:mgr2"})
    83  
    84  	// noop
    85  	err = se.StartUp()
    86  	c.Assert(err, IsNil)
    87  	c.Check(calls, HasLen, 2)
    88  }
    89  
    90  func (ses *stateEngineSuite) TestStartUpError(c *C) {
    91  	s := state.New(nil)
    92  	se := overlord.NewStateEngine(s)
    93  
    94  	calls := []string{}
    95  
    96  	err1 := errors.New("boom1")
    97  	err2 := errors.New("boom2")
    98  
    99  	mgr1 := &fakeManager{name: "mgr1", calls: &calls, startupError: err1}
   100  	mgr2 := &fakeManager{name: "mgr2", calls: &calls, startupError: err2}
   101  
   102  	se.AddManager(mgr1)
   103  	se.AddManager(mgr2)
   104  
   105  	err := se.StartUp()
   106  	c.Check(err.Error(), DeepEquals, "state startup errors: [boom1 boom2]")
   107  	c.Check(calls, DeepEquals, []string{"startup:mgr1", "startup:mgr2"})
   108  }
   109  
   110  func (ses *stateEngineSuite) TestEnsure(c *C) {
   111  	s := state.New(nil)
   112  	se := overlord.NewStateEngine(s)
   113  
   114  	calls := []string{}
   115  
   116  	mgr1 := &fakeManager{name: "mgr1", calls: &calls}
   117  	mgr2 := &fakeManager{name: "mgr2", calls: &calls}
   118  
   119  	se.AddManager(mgr1)
   120  	se.AddManager(mgr2)
   121  
   122  	err := se.Ensure()
   123  	c.Check(err, ErrorMatches, "state engine skipped startup")
   124  	c.Assert(se.StartUp(), IsNil)
   125  	calls = []string{}
   126  
   127  	err = se.Ensure()
   128  	c.Assert(err, IsNil)
   129  	c.Check(calls, DeepEquals, []string{"ensure:mgr1", "ensure:mgr2"})
   130  
   131  	err = se.Ensure()
   132  	c.Assert(err, IsNil)
   133  	c.Check(calls, DeepEquals, []string{"ensure:mgr1", "ensure:mgr2", "ensure:mgr1", "ensure:mgr2"})
   134  }
   135  
   136  func (ses *stateEngineSuite) TestEnsureError(c *C) {
   137  	s := state.New(nil)
   138  	se := overlord.NewStateEngine(s)
   139  
   140  	calls := []string{}
   141  
   142  	err1 := errors.New("boom1")
   143  	err2 := errors.New("boom2")
   144  
   145  	mgr1 := &fakeManager{name: "mgr1", calls: &calls, ensureError: err1}
   146  	mgr2 := &fakeManager{name: "mgr2", calls: &calls, ensureError: err2}
   147  
   148  	se.AddManager(mgr1)
   149  	se.AddManager(mgr2)
   150  
   151  	c.Assert(se.StartUp(), IsNil)
   152  	calls = []string{}
   153  
   154  	err := se.Ensure()
   155  	c.Check(err.Error(), DeepEquals, "state ensure errors: [boom1 boom2]")
   156  	c.Check(calls, DeepEquals, []string{"ensure:mgr1", "ensure:mgr2"})
   157  }
   158  
   159  func (ses *stateEngineSuite) TestStop(c *C) {
   160  	s := state.New(nil)
   161  	se := overlord.NewStateEngine(s)
   162  
   163  	calls := []string{}
   164  
   165  	mgr1 := &fakeManager{name: "mgr1", calls: &calls}
   166  	mgr2 := &fakeManager{name: "mgr2", calls: &calls}
   167  
   168  	se.AddManager(mgr1)
   169  	se.AddManager(mgr2)
   170  
   171  	c.Assert(se.StartUp(), IsNil)
   172  	calls = []string{}
   173  
   174  	se.Stop()
   175  	c.Check(calls, DeepEquals, []string{"stop:mgr1", "stop:mgr2"})
   176  	se.Stop()
   177  	c.Check(calls, HasLen, 2)
   178  
   179  	err := se.Ensure()
   180  	c.Check(err, ErrorMatches, "state engine already stopped")
   181  }