gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/overlord/overlord_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016-2017 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  	"encoding/json"
    24  	"errors"
    25  	"fmt"
    26  	"io/ioutil"
    27  	"os"
    28  	"path/filepath"
    29  	"syscall"
    30  	"testing"
    31  	"time"
    32  
    33  	. "gopkg.in/check.v1"
    34  	"gopkg.in/tomb.v2"
    35  
    36  	"github.com/snapcore/snapd/dirs"
    37  	"github.com/snapcore/snapd/osutil"
    38  	"github.com/snapcore/snapd/overlord"
    39  	"github.com/snapcore/snapd/overlord/auth"
    40  	"github.com/snapcore/snapd/overlord/devicestate/devicestatetest"
    41  	"github.com/snapcore/snapd/overlord/hookstate"
    42  	"github.com/snapcore/snapd/overlord/ifacestate"
    43  	"github.com/snapcore/snapd/overlord/patch"
    44  	"github.com/snapcore/snapd/overlord/snapstate"
    45  	"github.com/snapcore/snapd/overlord/state"
    46  	"github.com/snapcore/snapd/snap"
    47  	"github.com/snapcore/snapd/snapdenv"
    48  	"github.com/snapcore/snapd/snapdtool"
    49  	"github.com/snapcore/snapd/store"
    50  	"github.com/snapcore/snapd/testutil"
    51  	"github.com/snapcore/snapd/timings"
    52  )
    53  
    54  func TestOverlord(t *testing.T) { TestingT(t) }
    55  
    56  type overlordSuite struct {
    57  	testutil.BaseTest
    58  }
    59  
    60  var _ = Suite(&overlordSuite{})
    61  
    62  type ticker struct {
    63  	tickerChannel chan time.Time
    64  }
    65  
    66  func (w *ticker) tick(n int) {
    67  	for i := 0; i < n; i++ {
    68  		w.tickerChannel <- time.Now()
    69  	}
    70  }
    71  
    72  func fakePruneTicker() (w *ticker, restore func()) {
    73  	w = &ticker{
    74  		tickerChannel: make(chan time.Time),
    75  	}
    76  	restore = overlord.MockPruneTicker(func(t *time.Ticker) <-chan time.Time {
    77  		return w.tickerChannel
    78  	})
    79  	return w, restore
    80  }
    81  
    82  func (ovs *overlordSuite) SetUpTest(c *C) {
    83  	tmpdir := c.MkDir()
    84  	dirs.SetRootDir(tmpdir)
    85  	ovs.AddCleanup(func() { dirs.SetRootDir("") })
    86  	ovs.AddCleanup(osutil.MockMountInfo(""))
    87  
    88  	dirs.SnapStateFile = filepath.Join(tmpdir, "test.json")
    89  	snapstate.CanAutoRefresh = nil
    90  	ovs.AddCleanup(func() { ifacestate.MockSecurityBackends(nil) })
    91  }
    92  
    93  func (ovs *overlordSuite) TestNew(c *C) {
    94  	restore := patch.Mock(42, 2, nil)
    95  	defer restore()
    96  
    97  	var configstateInitCalled bool
    98  	overlord.MockConfigstateInit(func(*state.State, *hookstate.HookManager) error {
    99  		configstateInitCalled = true
   100  		return nil
   101  	})
   102  
   103  	o, err := overlord.New(nil)
   104  	c.Assert(err, IsNil)
   105  	c.Check(o, NotNil)
   106  
   107  	c.Check(o.StateEngine(), NotNil)
   108  	c.Check(o.TaskRunner(), NotNil)
   109  	c.Check(o.SnapManager(), NotNil)
   110  	c.Check(o.ServiceManager(), NotNil)
   111  	c.Check(o.AssertManager(), NotNil)
   112  	c.Check(o.InterfaceManager(), NotNil)
   113  	c.Check(o.HookManager(), NotNil)
   114  	c.Check(o.DeviceManager(), NotNil)
   115  	c.Check(o.CommandManager(), NotNil)
   116  	c.Check(o.SnapshotManager(), NotNil)
   117  	c.Check(configstateInitCalled, Equals, true)
   118  
   119  	o.InterfaceManager().DisableUDevMonitor()
   120  
   121  	s := o.State()
   122  	c.Check(s, NotNil)
   123  	c.Check(o.Engine().State(), Equals, s)
   124  
   125  	s.Lock()
   126  	defer s.Unlock()
   127  	var patchLevel, patchSublevel int
   128  	s.Get("patch-level", &patchLevel)
   129  	c.Check(patchLevel, Equals, 42)
   130  	s.Get("patch-sublevel", &patchSublevel)
   131  	c.Check(patchSublevel, Equals, 2)
   132  	var refreshPrivacyKey string
   133  	s.Get("refresh-privacy-key", &refreshPrivacyKey)
   134  	c.Check(refreshPrivacyKey, HasLen, 16)
   135  
   136  	// store is setup
   137  	sto := snapstate.Store(s, nil)
   138  	c.Check(sto, FitsTypeOf, &store.Store{})
   139  	c.Check(sto.(*store.Store).CacheDownloads(), Equals, 5)
   140  }
   141  
   142  func (ovs *overlordSuite) TestNewStore(c *C) {
   143  	// this is a shallow test, the deep testing happens in the
   144  	// remodeling tests in managers_test.go
   145  	o, err := overlord.New(nil)
   146  	c.Assert(err, IsNil)
   147  
   148  	devBE := o.DeviceManager().StoreContextBackend()
   149  
   150  	sto := o.NewStore(devBE)
   151  	c.Check(sto, FitsTypeOf, &store.Store{})
   152  	c.Check(sto.(*store.Store).CacheDownloads(), Equals, 5)
   153  }
   154  
   155  func (ovs *overlordSuite) TestNewWithGoodState(c *C) {
   156  	// ensure we don't write state load timing in the state on really
   157  	// slow architectures (e.g. risc-v)
   158  	oldDurationThreshold := timings.DurationThreshold
   159  	timings.DurationThreshold = time.Second * 30
   160  	defer func() { timings.DurationThreshold = oldDurationThreshold }()
   161  
   162  	fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"patch-sublevel-last-version":%q,"some":"data","refresh-privacy-key":"0123456789ABCDEF"},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel, snapdtool.Version))
   163  	err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600)
   164  	c.Assert(err, IsNil)
   165  
   166  	o, err := overlord.New(nil)
   167  	c.Assert(err, IsNil)
   168  
   169  	state := o.State()
   170  	c.Assert(err, IsNil)
   171  	state.Lock()
   172  	defer state.Unlock()
   173  
   174  	d, err := state.MarshalJSON()
   175  	c.Assert(err, IsNil)
   176  
   177  	var got, expected map[string]interface{}
   178  	err = json.Unmarshal(d, &got)
   179  	c.Assert(err, IsNil)
   180  	err = json.Unmarshal(fakeState, &expected)
   181  	c.Assert(err, IsNil)
   182  
   183  	data, _ := got["data"].(map[string]interface{})
   184  	c.Assert(data, NotNil)
   185  
   186  	c.Check(got, DeepEquals, expected)
   187  }
   188  
   189  func (ovs *overlordSuite) TestNewWithStateSnapmgrUpdate(c *C) {
   190  	fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"some":"data"},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level))
   191  	err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600)
   192  	c.Assert(err, IsNil)
   193  
   194  	o, err := overlord.New(nil)
   195  	c.Assert(err, IsNil)
   196  
   197  	state := o.State()
   198  	c.Assert(err, IsNil)
   199  	state.Lock()
   200  	defer state.Unlock()
   201  
   202  	var refreshPrivacyKey string
   203  	state.Get("refresh-privacy-key", &refreshPrivacyKey)
   204  	c.Check(refreshPrivacyKey, HasLen, 16)
   205  }
   206  
   207  func (ovs *overlordSuite) TestNewWithInvalidState(c *C) {
   208  	fakeState := []byte(``)
   209  	err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600)
   210  	c.Assert(err, IsNil)
   211  
   212  	_, err = overlord.New(nil)
   213  	c.Assert(err, ErrorMatches, "cannot read state: EOF")
   214  }
   215  
   216  func (ovs *overlordSuite) TestNewWithPatches(c *C) {
   217  	p := func(s *state.State) error {
   218  		s.Set("patched", true)
   219  		return nil
   220  	}
   221  	sp := func(s *state.State) error {
   222  		s.Set("patched2", true)
   223  		return nil
   224  	}
   225  	patch.Mock(1, 1, map[int][]patch.PatchFunc{1: {p, sp}})
   226  
   227  	fakeState := []byte(`{"data":{"patch-level":0, "patch-sublevel":0}}`)
   228  	err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600)
   229  	c.Assert(err, IsNil)
   230  
   231  	o, err := overlord.New(nil)
   232  	c.Assert(err, IsNil)
   233  
   234  	state := o.State()
   235  	c.Assert(err, IsNil)
   236  	state.Lock()
   237  	defer state.Unlock()
   238  
   239  	var level int
   240  	err = state.Get("patch-level", &level)
   241  	c.Assert(err, IsNil)
   242  	c.Check(level, Equals, 1)
   243  
   244  	var sublevel int
   245  	c.Assert(state.Get("patch-sublevel", &sublevel), IsNil)
   246  	c.Check(sublevel, Equals, 1)
   247  
   248  	var b bool
   249  	err = state.Get("patched", &b)
   250  	c.Assert(err, IsNil)
   251  	c.Check(b, Equals, true)
   252  
   253  	c.Assert(state.Get("patched2", &b), IsNil)
   254  	c.Check(b, Equals, true)
   255  }
   256  
   257  func (ovs *overlordSuite) TestNewFailedConfigstate(c *C) {
   258  	restore := patch.Mock(42, 2, nil)
   259  	defer restore()
   260  
   261  	var configstateInitCalled bool
   262  	restore = overlord.MockConfigstateInit(func(*state.State, *hookstate.HookManager) error {
   263  		configstateInitCalled = true
   264  		return fmt.Errorf("bad bad")
   265  	})
   266  	defer restore()
   267  
   268  	o, err := overlord.New(nil)
   269  	c.Assert(err, ErrorMatches, "bad bad")
   270  	c.Check(o, IsNil)
   271  	c.Check(configstateInitCalled, Equals, true)
   272  }
   273  
   274  type witnessManager struct {
   275  	state          *state.State
   276  	expectedEnsure int
   277  	ensureCalled   chan struct{}
   278  	ensureCallback func(s *state.State) error
   279  	startedUp      int
   280  }
   281  
   282  func (wm *witnessManager) StartUp() error {
   283  	wm.startedUp++
   284  	return nil
   285  }
   286  
   287  func (wm *witnessManager) Ensure() error {
   288  	if wm.expectedEnsure--; wm.expectedEnsure == 0 {
   289  		close(wm.ensureCalled)
   290  		return nil
   291  	}
   292  	if wm.ensureCallback != nil {
   293  		return wm.ensureCallback(wm.state)
   294  	}
   295  	return nil
   296  }
   297  
   298  // markSeeded flags the state under the overlord as seeded to avoid running the seeding code in these tests
   299  func markSeeded(o *overlord.Overlord) {
   300  	st := o.State()
   301  	st.Lock()
   302  	st.Set("seeded", true)
   303  	devicestatetest.SetDevice(st, &auth.DeviceState{
   304  		Brand:  "canonical",
   305  		Model:  "pc",
   306  		Serial: "serialserial",
   307  	})
   308  	st.Unlock()
   309  }
   310  
   311  func (ovs *overlordSuite) TestTrivialRunAndStop(c *C) {
   312  	o, err := overlord.New(nil)
   313  	c.Assert(err, IsNil)
   314  
   315  	markSeeded(o)
   316  	// make sure we don't try to talk to the store
   317  	snapstate.CanAutoRefresh = nil
   318  
   319  	err = o.StartUp()
   320  	c.Assert(err, IsNil)
   321  
   322  	o.Loop()
   323  
   324  	err = o.Stop()
   325  	c.Assert(err, IsNil)
   326  }
   327  
   328  func (ovs *overlordSuite) TestUnknownTasks(c *C) {
   329  	o, err := overlord.New(nil)
   330  	c.Assert(err, IsNil)
   331  	o.InterfaceManager().DisableUDevMonitor()
   332  
   333  	markSeeded(o)
   334  	// make sure we don't try to talk to the store
   335  	snapstate.CanAutoRefresh = nil
   336  
   337  	// unknown tasks are ignored and succeed
   338  	st := o.State()
   339  	st.Lock()
   340  	defer st.Unlock()
   341  	t := st.NewTask("unknown", "...")
   342  	chg := st.NewChange("change-w-unknown", "...")
   343  	chg.AddTask(t)
   344  
   345  	st.Unlock()
   346  	err = o.Settle(1 * time.Second)
   347  	st.Lock()
   348  	c.Assert(err, IsNil)
   349  
   350  	c.Check(chg.Status(), Equals, state.DoneStatus)
   351  }
   352  
   353  func (ovs *overlordSuite) TestEnsureLoopRunAndStop(c *C) {
   354  	restoreIntv := overlord.MockEnsureInterval(10 * time.Millisecond)
   355  	defer restoreIntv()
   356  	o := overlord.Mock()
   357  
   358  	witness := &witnessManager{
   359  		state:          o.State(),
   360  		expectedEnsure: 3,
   361  		ensureCalled:   make(chan struct{}),
   362  	}
   363  	o.AddManager(witness)
   364  
   365  	err := o.StartUp()
   366  	c.Assert(err, IsNil)
   367  
   368  	o.Loop()
   369  	defer o.Stop()
   370  
   371  	t0 := time.Now()
   372  	select {
   373  	case <-witness.ensureCalled:
   374  	case <-time.After(2 * time.Second):
   375  		c.Fatal("Ensure calls not happening")
   376  	}
   377  	c.Check(time.Since(t0) >= 10*time.Millisecond, Equals, true)
   378  
   379  	err = o.Stop()
   380  	c.Assert(err, IsNil)
   381  
   382  	c.Check(witness.startedUp, Equals, 1)
   383  }
   384  
   385  func (ovs *overlordSuite) TestEnsureLoopMediatedEnsureBeforeImmediate(c *C) {
   386  	restoreIntv := overlord.MockEnsureInterval(10 * time.Minute)
   387  	defer restoreIntv()
   388  	o := overlord.Mock()
   389  
   390  	ensure := func(s *state.State) error {
   391  		s.EnsureBefore(0)
   392  		return nil
   393  	}
   394  
   395  	witness := &witnessManager{
   396  		state:          o.State(),
   397  		expectedEnsure: 2,
   398  		ensureCalled:   make(chan struct{}),
   399  		ensureCallback: ensure,
   400  	}
   401  	o.AddManager(witness)
   402  
   403  	c.Assert(o.StartUp(), IsNil)
   404  
   405  	o.Loop()
   406  	defer o.Stop()
   407  
   408  	select {
   409  	case <-witness.ensureCalled:
   410  	case <-time.After(2 * time.Second):
   411  		c.Fatal("Ensure calls not happening")
   412  	}
   413  }
   414  
   415  func (ovs *overlordSuite) TestEnsureLoopMediatedEnsureBefore(c *C) {
   416  	restoreIntv := overlord.MockEnsureInterval(10 * time.Minute)
   417  	defer restoreIntv()
   418  	o := overlord.Mock()
   419  
   420  	ensure := func(s *state.State) error {
   421  		s.EnsureBefore(10 * time.Millisecond)
   422  		return nil
   423  	}
   424  
   425  	witness := &witnessManager{
   426  		state:          o.State(),
   427  		expectedEnsure: 2,
   428  		ensureCalled:   make(chan struct{}),
   429  		ensureCallback: ensure,
   430  	}
   431  	o.AddManager(witness)
   432  
   433  	c.Assert(o.StartUp(), IsNil)
   434  
   435  	o.Loop()
   436  	defer o.Stop()
   437  
   438  	select {
   439  	case <-witness.ensureCalled:
   440  	case <-time.After(2 * time.Second):
   441  		c.Fatal("Ensure calls not happening")
   442  	}
   443  }
   444  
   445  func (ovs *overlordSuite) TestEnsureBeforeSleepy(c *C) {
   446  	restoreIntv := overlord.MockEnsureInterval(10 * time.Minute)
   447  	defer restoreIntv()
   448  	o := overlord.Mock()
   449  
   450  	ensure := func(s *state.State) error {
   451  		overlord.MockEnsureNext(o, time.Now().Add(-10*time.Hour))
   452  		s.EnsureBefore(0)
   453  		return nil
   454  	}
   455  
   456  	witness := &witnessManager{
   457  		state:          o.State(),
   458  		expectedEnsure: 2,
   459  		ensureCalled:   make(chan struct{}),
   460  		ensureCallback: ensure,
   461  	}
   462  	o.AddManager(witness)
   463  
   464  	c.Assert(o.StartUp(), IsNil)
   465  
   466  	o.Loop()
   467  	defer o.Stop()
   468  
   469  	select {
   470  	case <-witness.ensureCalled:
   471  	case <-time.After(2 * time.Second):
   472  		c.Fatal("Ensure calls not happening")
   473  	}
   474  }
   475  
   476  func (ovs *overlordSuite) TestEnsureBeforeLater(c *C) {
   477  	restoreIntv := overlord.MockEnsureInterval(10 * time.Minute)
   478  	defer restoreIntv()
   479  	o := overlord.Mock()
   480  
   481  	ensure := func(s *state.State) error {
   482  		overlord.MockEnsureNext(o, time.Now().Add(-10*time.Hour))
   483  		s.EnsureBefore(time.Second * 5)
   484  		return nil
   485  	}
   486  
   487  	witness := &witnessManager{
   488  		state:          o.State(),
   489  		expectedEnsure: 2,
   490  		ensureCalled:   make(chan struct{}),
   491  		ensureCallback: ensure,
   492  	}
   493  	o.AddManager(witness)
   494  
   495  	c.Assert(o.StartUp(), IsNil)
   496  
   497  	o.Loop()
   498  	defer o.Stop()
   499  
   500  	select {
   501  	case <-witness.ensureCalled:
   502  	case <-time.After(2 * time.Second):
   503  		c.Fatal("Ensure calls not happening")
   504  	}
   505  }
   506  
   507  func (ovs *overlordSuite) TestEnsureLoopMediatedEnsureBeforeOutsideEnsure(c *C) {
   508  	restoreIntv := overlord.MockEnsureInterval(10 * time.Minute)
   509  	defer restoreIntv()
   510  	o := overlord.Mock()
   511  
   512  	ch := make(chan struct{})
   513  	ensure := func(s *state.State) error {
   514  		close(ch)
   515  		return nil
   516  	}
   517  
   518  	witness := &witnessManager{
   519  		state:          o.State(),
   520  		expectedEnsure: 2,
   521  		ensureCalled:   make(chan struct{}),
   522  		ensureCallback: ensure,
   523  	}
   524  	o.AddManager(witness)
   525  
   526  	c.Assert(o.StartUp(), IsNil)
   527  
   528  	o.Loop()
   529  	defer o.Stop()
   530  
   531  	select {
   532  	case <-ch:
   533  	case <-time.After(2 * time.Second):
   534  		c.Fatal("Ensure calls not happening")
   535  	}
   536  
   537  	o.State().EnsureBefore(0)
   538  
   539  	select {
   540  	case <-witness.ensureCalled:
   541  	case <-time.After(2 * time.Second):
   542  		c.Fatal("Ensure calls not happening")
   543  	}
   544  }
   545  
   546  func (ovs *overlordSuite) TestEnsureLoopPrune(c *C) {
   547  	restoreIntv := overlord.MockPruneInterval(200*time.Millisecond, 1000*time.Millisecond, 1000*time.Millisecond)
   548  	defer restoreIntv()
   549  	o := overlord.Mock()
   550  
   551  	st := o.State()
   552  	st.Lock()
   553  	t1 := st.NewTask("foo", "...")
   554  	chg1 := st.NewChange("abort", "...")
   555  	chg1.AddTask(t1)
   556  	chg2 := st.NewChange("prune", "...")
   557  	chg2.SetStatus(state.DoneStatus)
   558  	t0 := chg2.ReadyTime()
   559  	st.Unlock()
   560  
   561  	// observe the loop cycles to detect when prune should have happened
   562  	pruneHappened := make(chan struct{})
   563  	cycles := -1
   564  	waitForPrune := func(_ *state.State) error {
   565  		if cycles == -1 {
   566  			if time.Since(t0) > 1000*time.Millisecond {
   567  				cycles = 2 // wait a couple more loop cycles
   568  			}
   569  			return nil
   570  		}
   571  		if cycles > 0 {
   572  			cycles--
   573  			if cycles == 0 {
   574  				close(pruneHappened)
   575  			}
   576  		}
   577  		return nil
   578  	}
   579  	witness := &witnessManager{
   580  		ensureCallback: waitForPrune,
   581  	}
   582  	o.AddManager(witness)
   583  
   584  	c.Assert(o.StartUp(), IsNil)
   585  
   586  	o.Loop()
   587  
   588  	select {
   589  	case <-pruneHappened:
   590  	case <-time.After(2 * time.Second):
   591  		c.Fatal("Pruning should have happened by now")
   592  	}
   593  
   594  	err := o.Stop()
   595  	c.Assert(err, IsNil)
   596  
   597  	st.Lock()
   598  	defer st.Unlock()
   599  
   600  	c.Assert(st.Change(chg1.ID()), Equals, chg1)
   601  	c.Assert(st.Change(chg2.ID()), IsNil)
   602  
   603  	c.Assert(t1.Status(), Equals, state.HoldStatus)
   604  }
   605  
   606  func (ovs *overlordSuite) TestEnsureLoopPruneRunsMultipleTimes(c *C) {
   607  	restoreIntv := overlord.MockPruneInterval(100*time.Millisecond, 5*time.Millisecond, 1*time.Hour)
   608  	defer restoreIntv()
   609  	o := overlord.Mock()
   610  
   611  	// create two changes, one that can be pruned now, one in progress
   612  	st := o.State()
   613  	st.Lock()
   614  	t1 := st.NewTask("foo", "...")
   615  	chg1 := st.NewChange("pruneNow", "...")
   616  	chg1.AddTask(t1)
   617  	t1.SetStatus(state.DoneStatus)
   618  	t2 := st.NewTask("foo", "...")
   619  	chg2 := st.NewChange("pruneNext", "...")
   620  	chg2.AddTask(t2)
   621  	t2.SetStatus(state.DoStatus)
   622  	c.Check(st.Changes(), HasLen, 2)
   623  	st.Unlock()
   624  
   625  	w, restoreTicker := fakePruneTicker()
   626  	defer restoreTicker()
   627  
   628  	// start the loop that runs the prune ticker
   629  	o.Loop()
   630  
   631  	// this needs to be more than pruneWait=5ms mocked above
   632  	time.Sleep(10 * time.Millisecond)
   633  	w.tick(2)
   634  
   635  	st.Lock()
   636  	c.Check(st.Changes(), HasLen, 1)
   637  	chg2.SetStatus(state.DoneStatus)
   638  	st.Unlock()
   639  
   640  	// this needs to be more than pruneWait=5ms mocked above
   641  	time.Sleep(10 * time.Millisecond)
   642  	// tick twice for extra Ensure
   643  	w.tick(2)
   644  
   645  	st.Lock()
   646  	c.Check(st.Changes(), HasLen, 0)
   647  	st.Unlock()
   648  
   649  	// cleanup loop ticker
   650  	err := o.Stop()
   651  	c.Assert(err, IsNil)
   652  }
   653  
   654  func (ovs *overlordSuite) TestOverlordStartUpSetsStartOfOperation(c *C) {
   655  	restoreIntv := overlord.MockPruneInterval(100*time.Millisecond, 1000*time.Millisecond, 1*time.Hour)
   656  	defer restoreIntv()
   657  
   658  	// use real overlord, we need device manager to be there
   659  	o, err := overlord.New(nil)
   660  	c.Assert(err, IsNil)
   661  
   662  	st := o.State()
   663  	st.Lock()
   664  	defer st.Unlock()
   665  
   666  	// sanity check, not set
   667  	var opTime time.Time
   668  	c.Assert(st.Get("start-of-operation-time", &opTime), Equals, state.ErrNoState)
   669  	st.Unlock()
   670  
   671  	c.Assert(o.StartUp(), IsNil)
   672  
   673  	st.Lock()
   674  	c.Assert(st.Get("start-of-operation-time", &opTime), IsNil)
   675  }
   676  
   677  func (ovs *overlordSuite) TestEnsureLoopPruneDoesntAbortShortlyAfterStartOfOperation(c *C) {
   678  	w, restoreTicker := fakePruneTicker()
   679  	defer restoreTicker()
   680  
   681  	// use real overlord, we need device manager to be there
   682  	o, err := overlord.New(nil)
   683  	c.Assert(err, IsNil)
   684  
   685  	markSeeded(o)
   686  
   687  	// avoid immediate transition to Done due to unknown kind
   688  	o.TaskRunner().AddHandler("bar", func(t *state.Task, _ *tomb.Tomb) error {
   689  		return &state.Retry{}
   690  	}, nil)
   691  
   692  	st := o.State()
   693  	st.Lock()
   694  
   695  	// start of operation time is 50min ago, this is less then abort limit
   696  	opTime := time.Now().Add(-50 * time.Minute)
   697  	st.Set("start-of-operation-time", opTime)
   698  
   699  	// spawn time one month ago
   700  	spawnTime := time.Now().AddDate(0, -1, 0)
   701  	restoreTimeNow := state.MockTime(spawnTime)
   702  
   703  	t := st.NewTask("bar", "...")
   704  	chg := st.NewChange("other-change", "...")
   705  	chg.AddTask(t)
   706  
   707  	restoreTimeNow()
   708  
   709  	// sanity
   710  	c.Check(st.Changes(), HasLen, 1)
   711  
   712  	st.Unlock()
   713  	c.Assert(o.StartUp(), IsNil)
   714  
   715  	// start the loop that runs the prune ticker
   716  	o.Loop()
   717  	w.tick(2)
   718  
   719  	c.Assert(o.Stop(), IsNil)
   720  
   721  	st.Lock()
   722  	defer st.Unlock()
   723  	c.Assert(st.Changes(), HasLen, 1)
   724  	c.Check(chg.Status(), Equals, state.DoingStatus)
   725  }
   726  
   727  func (ovs *overlordSuite) TestEnsureLoopPruneAbortsOld(c *C) {
   728  	// Ensure interval is not relevant for this test
   729  	restoreEnsureIntv := overlord.MockEnsureInterval(10 * time.Hour)
   730  	defer restoreEnsureIntv()
   731  
   732  	w, restoreTicker := fakePruneTicker()
   733  	defer restoreTicker()
   734  
   735  	// use real overlord, we need device manager to be there
   736  	o, err := overlord.New(nil)
   737  	c.Assert(err, IsNil)
   738  
   739  	// avoid immediate transition to Done due to having unknown kind
   740  	o.TaskRunner().AddHandler("bar", func(t *state.Task, _ *tomb.Tomb) error {
   741  		return &state.Retry{}
   742  	}, nil)
   743  
   744  	markSeeded(o)
   745  
   746  	st := o.State()
   747  	st.Lock()
   748  
   749  	// start of operation time is a year ago
   750  	opTime := time.Now().AddDate(-1, 0, 0)
   751  	st.Set("start-of-operation-time", opTime)
   752  
   753  	st.Unlock()
   754  	c.Assert(o.StartUp(), IsNil)
   755  	st.Lock()
   756  
   757  	// spawn time one month ago
   758  	spawnTime := time.Now().AddDate(0, -1, 0)
   759  	restoreTimeNow := state.MockTime(spawnTime)
   760  	t := st.NewTask("bar", "...")
   761  	chg := st.NewChange("other-change", "...")
   762  	chg.AddTask(t)
   763  
   764  	restoreTimeNow()
   765  
   766  	// sanity
   767  	c.Check(st.Changes(), HasLen, 1)
   768  	st.Unlock()
   769  
   770  	// start the loop that runs the prune ticker
   771  	o.Loop()
   772  	w.tick(2)
   773  
   774  	c.Assert(o.Stop(), IsNil)
   775  
   776  	st.Lock()
   777  	defer st.Unlock()
   778  
   779  	// sanity
   780  	op, err := o.DeviceManager().StartOfOperationTime()
   781  	c.Assert(err, IsNil)
   782  	c.Check(op.Equal(opTime), Equals, true)
   783  
   784  	c.Assert(st.Changes(), HasLen, 1)
   785  	// change was aborted
   786  	c.Check(chg.Status(), Equals, state.HoldStatus)
   787  }
   788  
   789  func (ovs *overlordSuite) TestEnsureLoopNoPruneWhenPreseed(c *C) {
   790  	w, restoreTicker := fakePruneTicker()
   791  	defer restoreTicker()
   792  
   793  	restore := snapdenv.MockPreseeding(true)
   794  	defer restore()
   795  
   796  	restorePreseedExitWithErr := overlord.MockPreseedExitWithError(func(err error) {})
   797  	defer restorePreseedExitWithErr()
   798  
   799  	o, err := overlord.New(nil)
   800  	c.Assert(err, IsNil)
   801  	markSeeded(o)
   802  
   803  	// avoid immediate transition to Done due to unknown kind
   804  	o.TaskRunner().AddHandler("bar", func(t *state.Task, _ *tomb.Tomb) error {
   805  		return &state.Retry{}
   806  	}, nil)
   807  
   808  	// sanity
   809  	_, err = o.DeviceManager().StartOfOperationTime()
   810  	c.Assert(err, ErrorMatches, `internal error: unexpected call to StartOfOperationTime in preseed mode`)
   811  
   812  	c.Assert(o.StartUp(), IsNil)
   813  
   814  	st := o.State()
   815  	st.Lock()
   816  
   817  	// spawn time one month ago
   818  	spawnTime := time.Now().AddDate(0, -1, 0)
   819  	restoreTimeNow := state.MockTime(spawnTime)
   820  	t := st.NewTask("bar", "...")
   821  	chg := st.NewChange("change", "...")
   822  	chg.AddTask(t)
   823  	restoreTimeNow()
   824  
   825  	st.Unlock()
   826  	// start the loop that runs the prune ticker
   827  	o.Loop()
   828  	w.tick(2)
   829  
   830  	c.Assert(o.Stop(), IsNil)
   831  
   832  	st.Lock()
   833  	defer st.Unlock()
   834  
   835  	var opTime time.Time
   836  	c.Assert(st.Get("start-of-operation-time", &opTime), Equals, state.ErrNoState)
   837  	c.Check(chg.Status(), Equals, state.DoingStatus)
   838  }
   839  
   840  func (ovs *overlordSuite) TestCheckpoint(c *C) {
   841  	oldUmask := syscall.Umask(0)
   842  	defer syscall.Umask(oldUmask)
   843  
   844  	o, err := overlord.New(nil)
   845  	c.Assert(err, IsNil)
   846  
   847  	s := o.State()
   848  	s.Lock()
   849  	s.Set("mark", 1)
   850  	s.Unlock()
   851  
   852  	st, err := os.Stat(dirs.SnapStateFile)
   853  	c.Assert(err, IsNil)
   854  	c.Assert(st.Mode(), Equals, os.FileMode(0600))
   855  
   856  	c.Check(dirs.SnapStateFile, testutil.FileContains, `"mark":1`)
   857  }
   858  
   859  type sampleManager struct {
   860  	ensureCallback func()
   861  }
   862  
   863  func newSampleManager(s *state.State, runner *state.TaskRunner) *sampleManager {
   864  	sm := &sampleManager{}
   865  
   866  	runner.AddHandler("runMgr1", func(t *state.Task, _ *tomb.Tomb) error {
   867  		s := t.State()
   868  		s.Lock()
   869  		defer s.Unlock()
   870  		s.Set("runMgr1Mark", 1)
   871  		return nil
   872  	}, nil)
   873  	runner.AddHandler("runMgr2", func(t *state.Task, _ *tomb.Tomb) error {
   874  		s := t.State()
   875  		s.Lock()
   876  		defer s.Unlock()
   877  		s.Set("runMgr2Mark", 1)
   878  		return nil
   879  	}, nil)
   880  	runner.AddHandler("runMgrEnsureBefore", func(t *state.Task, _ *tomb.Tomb) error {
   881  		s := t.State()
   882  		s.Lock()
   883  		defer s.Unlock()
   884  		s.EnsureBefore(20 * time.Millisecond)
   885  		return nil
   886  	}, nil)
   887  	runner.AddHandler("runMgrForever", func(t *state.Task, _ *tomb.Tomb) error {
   888  		s := t.State()
   889  		s.Lock()
   890  		defer s.Unlock()
   891  		s.EnsureBefore(20 * time.Millisecond)
   892  		return &state.Retry{}
   893  	}, nil)
   894  	runner.AddHandler("runMgrWCleanup", func(t *state.Task, _ *tomb.Tomb) error {
   895  		s := t.State()
   896  		s.Lock()
   897  		defer s.Unlock()
   898  		s.Set("runMgrWCleanupMark", 1)
   899  		return nil
   900  	}, nil)
   901  	runner.AddCleanup("runMgrWCleanup", func(t *state.Task, _ *tomb.Tomb) error {
   902  		s := t.State()
   903  		s.Lock()
   904  		defer s.Unlock()
   905  		s.Set("runMgrWCleanupCleanedUp", 1)
   906  		return nil
   907  	})
   908  
   909  	return sm
   910  }
   911  
   912  func (sm *sampleManager) Ensure() error {
   913  	if sm.ensureCallback != nil {
   914  		sm.ensureCallback()
   915  	}
   916  	return nil
   917  }
   918  
   919  func (ovs *overlordSuite) TestTrivialSettle(c *C) {
   920  	restoreIntv := overlord.MockEnsureInterval(1 * time.Minute)
   921  	defer restoreIntv()
   922  	o := overlord.Mock()
   923  
   924  	s := o.State()
   925  	sm1 := newSampleManager(s, o.TaskRunner())
   926  	o.AddManager(sm1)
   927  	o.AddManager(o.TaskRunner())
   928  
   929  	defer o.Engine().Stop()
   930  
   931  	s.Lock()
   932  	defer s.Unlock()
   933  
   934  	chg := s.NewChange("chg", "...")
   935  	t1 := s.NewTask("runMgr1", "1...")
   936  	chg.AddTask(t1)
   937  
   938  	s.Unlock()
   939  	o.Settle(5 * time.Second)
   940  	s.Lock()
   941  	c.Check(t1.Status(), Equals, state.DoneStatus)
   942  
   943  	var v int
   944  	err := s.Get("runMgr1Mark", &v)
   945  	c.Check(err, IsNil)
   946  }
   947  
   948  func (ovs *overlordSuite) TestSettleNotConverging(c *C) {
   949  	restoreIntv := overlord.MockEnsureInterval(1 * time.Minute)
   950  	defer restoreIntv()
   951  	o := overlord.Mock()
   952  
   953  	s := o.State()
   954  	sm1 := newSampleManager(s, o.TaskRunner())
   955  	o.AddManager(sm1)
   956  	o.AddManager(o.TaskRunner())
   957  
   958  	defer o.Engine().Stop()
   959  
   960  	s.Lock()
   961  	defer s.Unlock()
   962  
   963  	chg := s.NewChange("chg", "...")
   964  	t1 := s.NewTask("runMgrForever", "1...")
   965  	chg.AddTask(t1)
   966  
   967  	s.Unlock()
   968  	err := o.Settle(250 * time.Millisecond)
   969  	s.Lock()
   970  
   971  	c.Check(err, ErrorMatches, `Settle is not converging`)
   972  
   973  }
   974  
   975  func (ovs *overlordSuite) TestSettleChain(c *C) {
   976  	restoreIntv := overlord.MockEnsureInterval(1 * time.Minute)
   977  	defer restoreIntv()
   978  	o := overlord.Mock()
   979  
   980  	s := o.State()
   981  	sm1 := newSampleManager(s, o.TaskRunner())
   982  	o.AddManager(sm1)
   983  	o.AddManager(o.TaskRunner())
   984  
   985  	defer o.Engine().Stop()
   986  
   987  	s.Lock()
   988  	defer s.Unlock()
   989  
   990  	chg := s.NewChange("chg", "...")
   991  	t1 := s.NewTask("runMgr1", "1...")
   992  	t2 := s.NewTask("runMgr2", "2...")
   993  	t2.WaitFor(t1)
   994  	chg.AddAll(state.NewTaskSet(t1, t2))
   995  
   996  	s.Unlock()
   997  	o.Settle(5 * time.Second)
   998  	s.Lock()
   999  	c.Check(t1.Status(), Equals, state.DoneStatus)
  1000  	c.Check(t2.Status(), Equals, state.DoneStatus)
  1001  
  1002  	var v int
  1003  	err := s.Get("runMgr1Mark", &v)
  1004  	c.Check(err, IsNil)
  1005  	err = s.Get("runMgr2Mark", &v)
  1006  	c.Check(err, IsNil)
  1007  }
  1008  
  1009  func (ovs *overlordSuite) TestSettleChainWCleanup(c *C) {
  1010  	restoreIntv := overlord.MockEnsureInterval(1 * time.Minute)
  1011  	defer restoreIntv()
  1012  	o := overlord.Mock()
  1013  
  1014  	s := o.State()
  1015  	sm1 := newSampleManager(s, o.TaskRunner())
  1016  	o.AddManager(sm1)
  1017  	o.AddManager(o.TaskRunner())
  1018  
  1019  	defer o.Engine().Stop()
  1020  
  1021  	s.Lock()
  1022  	defer s.Unlock()
  1023  
  1024  	chg := s.NewChange("chg", "...")
  1025  	t1 := s.NewTask("runMgrWCleanup", "1...")
  1026  	t2 := s.NewTask("runMgr2", "2...")
  1027  	t2.WaitFor(t1)
  1028  	chg.AddAll(state.NewTaskSet(t1, t2))
  1029  
  1030  	s.Unlock()
  1031  	o.Settle(5 * time.Second)
  1032  	s.Lock()
  1033  	c.Check(t1.Status(), Equals, state.DoneStatus)
  1034  	c.Check(t2.Status(), Equals, state.DoneStatus)
  1035  
  1036  	var v int
  1037  	err := s.Get("runMgrWCleanupMark", &v)
  1038  	c.Check(err, IsNil)
  1039  	err = s.Get("runMgr2Mark", &v)
  1040  	c.Check(err, IsNil)
  1041  
  1042  	err = s.Get("runMgrWCleanupCleanedUp", &v)
  1043  	c.Check(err, IsNil)
  1044  }
  1045  
  1046  func (ovs *overlordSuite) TestSettleExplicitEnsureBefore(c *C) {
  1047  	restoreIntv := overlord.MockEnsureInterval(1 * time.Minute)
  1048  	defer restoreIntv()
  1049  	o := overlord.Mock()
  1050  
  1051  	s := o.State()
  1052  	sm1 := newSampleManager(s, o.TaskRunner())
  1053  	sm1.ensureCallback = func() {
  1054  		s.Lock()
  1055  		defer s.Unlock()
  1056  		v := 0
  1057  		s.Get("ensureCount", &v)
  1058  		s.Set("ensureCount", v+1)
  1059  	}
  1060  
  1061  	o.AddManager(sm1)
  1062  	o.AddManager(o.TaskRunner())
  1063  
  1064  	defer o.Engine().Stop()
  1065  
  1066  	s.Lock()
  1067  	defer s.Unlock()
  1068  
  1069  	chg := s.NewChange("chg", "...")
  1070  	t := s.NewTask("runMgrEnsureBefore", "...")
  1071  	chg.AddTask(t)
  1072  
  1073  	s.Unlock()
  1074  	o.Settle(5 * time.Second)
  1075  	s.Lock()
  1076  	c.Check(t.Status(), Equals, state.DoneStatus)
  1077  
  1078  	var v int
  1079  	err := s.Get("ensureCount", &v)
  1080  	c.Check(err, IsNil)
  1081  	c.Check(v, Equals, 2)
  1082  }
  1083  
  1084  func (ovs *overlordSuite) TestEnsureErrorWhenPreseeding(c *C) {
  1085  	restore := snapdenv.MockPreseeding(true)
  1086  	defer restore()
  1087  
  1088  	restoreIntv := overlord.MockEnsureInterval(1 * time.Millisecond)
  1089  	defer restoreIntv()
  1090  
  1091  	var errorCallbackError error
  1092  	restoreExitWithErr := overlord.MockPreseedExitWithError(func(err error) {
  1093  		errorCallbackError = err
  1094  	})
  1095  	defer restoreExitWithErr()
  1096  
  1097  	o, err := overlord.New(nil)
  1098  	c.Assert(err, IsNil)
  1099  	markSeeded(o)
  1100  
  1101  	err = o.StartUp()
  1102  	c.Assert(err, IsNil)
  1103  
  1104  	o.TaskRunner().AddHandler("bar", func(t *state.Task, _ *tomb.Tomb) error {
  1105  		return fmt.Errorf("bar error")
  1106  	}, nil)
  1107  
  1108  	s := o.State()
  1109  	s.Lock()
  1110  	defer s.Unlock()
  1111  
  1112  	chg := s.NewChange("chg", "...")
  1113  	t := s.NewTask("bar", "...")
  1114  	chg.AddTask(t)
  1115  
  1116  	s.Unlock()
  1117  	o.Loop()
  1118  	time.Sleep(1 * time.Second)
  1119  	o.Stop()
  1120  
  1121  	s.Lock()
  1122  	c.Check(t.Status(), Equals, state.ErrorStatus)
  1123  	c.Check(errorCallbackError, ErrorMatches, "bar error")
  1124  }
  1125  
  1126  func (ovs *overlordSuite) TestRequestRestartNoHandler(c *C) {
  1127  	o, err := overlord.New(nil)
  1128  	c.Assert(err, IsNil)
  1129  
  1130  	o.State().RequestRestart(state.RestartDaemon)
  1131  }
  1132  
  1133  type testRestartBehavior struct {
  1134  	restartRequested  state.RestartType
  1135  	rebootState       string
  1136  	rebootVerifiedErr error
  1137  }
  1138  
  1139  func (rb *testRestartBehavior) HandleRestart(t state.RestartType) {
  1140  	rb.restartRequested = t
  1141  }
  1142  
  1143  func (rb *testRestartBehavior) RebootAsExpected(_ *state.State) error {
  1144  	rb.rebootState = "as-expected"
  1145  	return rb.rebootVerifiedErr
  1146  }
  1147  
  1148  func (rb *testRestartBehavior) RebootDidNotHappen(_ *state.State) error {
  1149  	rb.rebootState = "did-not-happen"
  1150  	return rb.rebootVerifiedErr
  1151  }
  1152  
  1153  func (ovs *overlordSuite) TestRequestRestartHandler(c *C) {
  1154  	rb := &testRestartBehavior{}
  1155  
  1156  	o, err := overlord.New(rb)
  1157  	c.Assert(err, IsNil)
  1158  
  1159  	o.State().RequestRestart(state.RestartDaemon)
  1160  
  1161  	c.Check(rb.restartRequested, Equals, state.RestartDaemon)
  1162  }
  1163  
  1164  func (ovs *overlordSuite) TestVerifyRebootNoPendingReboot(c *C) {
  1165  	fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"some":"data","refresh-privacy-key":"0123456789ABCDEF"},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel))
  1166  	err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600)
  1167  	c.Assert(err, IsNil)
  1168  
  1169  	rb := &testRestartBehavior{}
  1170  
  1171  	_, err = overlord.New(rb)
  1172  	c.Assert(err, IsNil)
  1173  
  1174  	c.Check(rb.rebootState, Equals, "as-expected")
  1175  }
  1176  
  1177  func (ovs *overlordSuite) TestVerifyRebootOK(c *C) {
  1178  	fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"some":"data","refresh-privacy-key":"0123456789ABCDEF","system-restart-from-boot-id":%q},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel, "boot-id-prev"))
  1179  	err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600)
  1180  	c.Assert(err, IsNil)
  1181  
  1182  	rb := &testRestartBehavior{}
  1183  
  1184  	_, err = overlord.New(rb)
  1185  	c.Assert(err, IsNil)
  1186  
  1187  	c.Check(rb.rebootState, Equals, "as-expected")
  1188  }
  1189  
  1190  func (ovs *overlordSuite) TestVerifyRebootOKButError(c *C) {
  1191  	fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"some":"data","refresh-privacy-key":"0123456789ABCDEF","system-restart-from-boot-id":%q},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel, "boot-id-prev"))
  1192  	err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600)
  1193  	c.Assert(err, IsNil)
  1194  
  1195  	e := errors.New("boom")
  1196  	rb := &testRestartBehavior{rebootVerifiedErr: e}
  1197  
  1198  	_, err = overlord.New(rb)
  1199  	c.Assert(err, Equals, e)
  1200  
  1201  	c.Check(rb.rebootState, Equals, "as-expected")
  1202  }
  1203  
  1204  func (ovs *overlordSuite) TestVerifyRebootDidNotHappen(c *C) {
  1205  	curBootID, err := osutil.BootID()
  1206  	c.Assert(err, IsNil)
  1207  
  1208  	fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"some":"data","refresh-privacy-key":"0123456789ABCDEF","system-restart-from-boot-id":%q},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel, curBootID))
  1209  	err = ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600)
  1210  	c.Assert(err, IsNil)
  1211  
  1212  	rb := &testRestartBehavior{}
  1213  
  1214  	_, err = overlord.New(rb)
  1215  	c.Assert(err, IsNil)
  1216  
  1217  	c.Check(rb.rebootState, Equals, "did-not-happen")
  1218  }
  1219  
  1220  func (ovs *overlordSuite) TestVerifyRebootDidNotHappenError(c *C) {
  1221  	curBootID, err := osutil.BootID()
  1222  	c.Assert(err, IsNil)
  1223  
  1224  	fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"some":"data","refresh-privacy-key":"0123456789ABCDEF","system-restart-from-boot-id":%q},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel, curBootID))
  1225  	err = ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600)
  1226  	c.Assert(err, IsNil)
  1227  
  1228  	e := errors.New("boom")
  1229  	rb := &testRestartBehavior{rebootVerifiedErr: e}
  1230  
  1231  	_, err = overlord.New(rb)
  1232  	c.Assert(err, Equals, e)
  1233  
  1234  	c.Check(rb.rebootState, Equals, "did-not-happen")
  1235  }
  1236  
  1237  func (ovs *overlordSuite) TestOverlordCanStandby(c *C) {
  1238  	restoreIntv := overlord.MockEnsureInterval(10 * time.Millisecond)
  1239  	defer restoreIntv()
  1240  	o := overlord.Mock()
  1241  	witness := &witnessManager{
  1242  		state:          o.State(),
  1243  		expectedEnsure: 3,
  1244  		ensureCalled:   make(chan struct{}),
  1245  	}
  1246  	o.AddManager(witness)
  1247  
  1248  	c.Assert(o.StartUp(), IsNil)
  1249  
  1250  	// can only standby after loop ran once
  1251  	c.Assert(o.CanStandby(), Equals, false)
  1252  
  1253  	o.Loop()
  1254  	defer o.Stop()
  1255  
  1256  	select {
  1257  	case <-witness.ensureCalled:
  1258  	case <-time.After(2 * time.Second):
  1259  		c.Fatal("Ensure calls not happening")
  1260  	}
  1261  
  1262  	c.Assert(o.CanStandby(), Equals, true)
  1263  }
  1264  
  1265  func (ovs *overlordSuite) TestStartupTimeout(c *C) {
  1266  	o, err := overlord.New(nil)
  1267  	c.Assert(err, IsNil)
  1268  
  1269  	to, _, err := o.StartupTimeout()
  1270  	c.Assert(err, IsNil)
  1271  	c.Check(to, Equals, 30*time.Second)
  1272  
  1273  	st := o.State()
  1274  	st.Lock()
  1275  	defer st.Unlock()
  1276  
  1277  	// have two snaps
  1278  	snapstate.Set(st, "core18", &snapstate.SnapState{
  1279  		Active: true,
  1280  		Sequence: []*snap.SideInfo{
  1281  			{RealName: "core18", Revision: snap.R(1)},
  1282  		},
  1283  		Current:  snap.R(1),
  1284  		SnapType: "base",
  1285  	})
  1286  	snapstate.Set(st, "foo", &snapstate.SnapState{
  1287  		Active: true,
  1288  		Sequence: []*snap.SideInfo{
  1289  			{RealName: "foo", Revision: snap.R(1)},
  1290  		},
  1291  		Current:  snap.R(1),
  1292  		SnapType: "app",
  1293  	})
  1294  
  1295  	st.Unlock()
  1296  	to, reasoning, err := o.StartupTimeout()
  1297  	st.Lock()
  1298  	c.Assert(err, IsNil)
  1299  
  1300  	c.Check(to, Equals, (30+5+5)*time.Second)
  1301  	c.Check(reasoning, Equals, "pessimistic estimate of 30s plus 5s per snap")
  1302  }