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 }