github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/overlord/configstate/configcore/corecfg_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 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 configcore_test
    21  
    22  import (
    23  	"fmt"
    24  	"reflect"
    25  	"testing"
    26  
    27  	. "gopkg.in/check.v1"
    28  
    29  	"github.com/snapcore/snapd/dirs"
    30  	"github.com/snapcore/snapd/overlord/configstate/config"
    31  	"github.com/snapcore/snapd/overlord/configstate/configcore"
    32  	"github.com/snapcore/snapd/overlord/state"
    33  	"github.com/snapcore/snapd/snap"
    34  	"github.com/snapcore/snapd/systemd"
    35  	"github.com/snapcore/snapd/testutil"
    36  )
    37  
    38  func Test(t *testing.T) { TestingT(t) }
    39  
    40  type mockConf struct {
    41  	state   *state.State
    42  	conf    map[string]interface{}
    43  	changes map[string]interface{}
    44  	err     error
    45  }
    46  
    47  func (cfg *mockConf) Get(snapName, key string, result interface{}) error {
    48  	if snapName != "core" {
    49  		return fmt.Errorf("mockConf only knows about core")
    50  	}
    51  
    52  	var value interface{}
    53  	value = cfg.changes[key]
    54  	if value == nil {
    55  		value = cfg.conf[key]
    56  	}
    57  	if value != nil {
    58  		v1 := reflect.ValueOf(result)
    59  		v2 := reflect.Indirect(v1)
    60  		v2.Set(reflect.ValueOf(value))
    61  	}
    62  	return cfg.err
    63  }
    64  
    65  func (cfg *mockConf) GetMaybe(snapName, key string, result interface{}) error {
    66  	err := cfg.Get(snapName, key, result)
    67  	if err != nil && !config.IsNoOption(err) {
    68  		return err
    69  	}
    70  	return nil
    71  }
    72  
    73  func (cfg *mockConf) GetPristine(snapName, key string, result interface{}) error {
    74  	if snapName != "core" {
    75  		return fmt.Errorf("mockConf only knows about core")
    76  	}
    77  
    78  	var value interface{}
    79  	value = cfg.conf[key]
    80  	if value != nil {
    81  		v1 := reflect.ValueOf(result)
    82  		v2 := reflect.Indirect(v1)
    83  		v2.Set(reflect.ValueOf(value))
    84  	}
    85  	return cfg.err
    86  }
    87  
    88  func (cfg *mockConf) GetPristineMaybe(snapName, key string, result interface{}) error {
    89  	err := cfg.GetPristine(snapName, key, result)
    90  	if err != nil && !config.IsNoOption(err) {
    91  		return err
    92  	}
    93  	return nil
    94  }
    95  
    96  func (cfg *mockConf) Set(snapName, key string, v interface{}) error {
    97  	if snapName != "core" {
    98  		return fmt.Errorf("mockConf only knows about core")
    99  	}
   100  	if cfg.conf == nil {
   101  		cfg.conf = make(map[string]interface{})
   102  	}
   103  	cfg.conf[key] = v
   104  	return nil
   105  }
   106  
   107  func (cfg *mockConf) Changes() []string {
   108  	out := make([]string, 0, len(cfg.changes))
   109  	for k := range cfg.changes {
   110  		out = append(out, "core."+k)
   111  	}
   112  	return out
   113  }
   114  
   115  func (cfg *mockConf) State() *state.State {
   116  	return cfg.state
   117  }
   118  
   119  // configcoreSuite is the base for all the configcore tests
   120  type configcoreSuite struct {
   121  	testutil.BaseTest
   122  
   123  	state *state.State
   124  
   125  	systemctlArgs     [][]string
   126  	systemdSysctlArgs [][]string
   127  }
   128  
   129  var _ = Suite(&configcoreSuite{})
   130  
   131  func (s *configcoreSuite) SetUpTest(c *C) {
   132  	s.BaseTest.SetUpTest(c)
   133  
   134  	dirs.SetRootDir(c.MkDir())
   135  	s.AddCleanup(func() { dirs.SetRootDir("") })
   136  
   137  	s.AddCleanup(systemd.MockSystemctl(func(args ...string) ([]byte, error) {
   138  		s.systemctlArgs = append(s.systemctlArgs, args[:])
   139  		output := []byte("ActiveState=inactive")
   140  		return output, nil
   141  	}))
   142  	s.systemctlArgs = nil
   143  	s.AddCleanup(systemd.MockSystemdSysctl(func(args ...string) error {
   144  		s.systemdSysctlArgs = append(s.systemdSysctlArgs, args[:])
   145  		return nil
   146  	}))
   147  	s.systemdSysctlArgs = nil
   148  
   149  	s.state = state.New(nil)
   150  
   151  	restore := snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})
   152  	s.AddCleanup(restore)
   153  }
   154  
   155  // runCfgSuite tests configcore.Run()
   156  type runCfgSuite struct {
   157  	configcoreSuite
   158  }
   159  
   160  var _ = Suite(&runCfgSuite{})
   161  
   162  func (r *runCfgSuite) TestConfigureUnknownOption(c *C) {
   163  	conf := &mockConf{
   164  		state: r.state,
   165  		changes: map[string]interface{}{
   166  			"unknown.option": "1",
   167  		},
   168  	}
   169  
   170  	err := configcore.Run(conf)
   171  	c.Check(err, ErrorMatches, `cannot set "core.unknown.option": unsupported system option`)
   172  }
   173  
   174  // applyCfgSuite tests configcore.Apply()
   175  type applyCfgSuite struct {
   176  	tmpDir string
   177  }
   178  
   179  var _ = Suite(&applyCfgSuite{})
   180  
   181  func (s *applyCfgSuite) SetUpTest(c *C) {
   182  	s.tmpDir = c.MkDir()
   183  	dirs.SetRootDir(s.tmpDir)
   184  }
   185  
   186  func (s *applyCfgSuite) TearDownTest(c *C) {
   187  	dirs.SetRootDir("")
   188  }
   189  
   190  func (s *applyCfgSuite) TestEmptyRootDir(c *C) {
   191  	err := configcore.FilesystemOnlyApply("", nil, nil)
   192  	c.Check(err, ErrorMatches, `internal error: root directory for configcore.FilesystemOnlyApply\(\) not set`)
   193  }
   194  
   195  func (s *applyCfgSuite) TestSmoke(c *C) {
   196  	conf := &mockConf{}
   197  	c.Assert(configcore.FilesystemOnlyApply(s.tmpDir, conf, nil), IsNil)
   198  }
   199  
   200  func (s *applyCfgSuite) TestPlainCoreConfigGetErrorIfNotCore(c *C) {
   201  	conf := configcore.PlainCoreConfig(map[string]interface{}{})
   202  	var val interface{}
   203  	c.Assert(conf.Get("some-snap", "a", &val), ErrorMatches, `internal error: expected core snap in Get\(\), "some-snap" was requested`)
   204  }
   205  
   206  func (s *applyCfgSuite) TestPlainCoreConfigGet(c *C) {
   207  	conf := configcore.PlainCoreConfig(map[string]interface{}{"foo": "bar"})
   208  	var val interface{}
   209  	c.Assert(conf.Get("core", "a", &val), DeepEquals, &config.NoOptionError{SnapName: "core", Key: "a"})
   210  	c.Assert(conf.Get("core", "foo", &val), IsNil)
   211  	c.Check(val, DeepEquals, "bar")
   212  }
   213  
   214  func (s *applyCfgSuite) TestPlainCoreConfigGetMaybe(c *C) {
   215  	conf := configcore.PlainCoreConfig(map[string]interface{}{"foo": "bar"})
   216  	var val interface{}
   217  	c.Assert(conf.GetMaybe("core", "a", &val), IsNil)
   218  	c.Assert(val, IsNil)
   219  	c.Assert(conf.Get("core", "foo", &val), IsNil)
   220  	c.Check(val, DeepEquals, "bar")
   221  }
   222  
   223  func (s *applyCfgSuite) TestNilHandlePanics(c *C) {
   224  	c.Assert(func() { configcore.AddFSOnlyHandler(nil, nil, nil) },
   225  		Panics, "cannot have nil handle with fsOnlyHandler")
   226  
   227  	c.Assert(func() { configcore.AddWithStateHandler(nil, nil, nil) },
   228  		Panics, "cannot have nil handle with addWithStateHandler if validatedOnlyStateConfig flag is not set")
   229  }