github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/overlord/snapstate/backend/aliases_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 backend_test 21 22 import ( 23 "io/ioutil" 24 "os" 25 "path/filepath" 26 27 . "gopkg.in/check.v1" 28 29 "github.com/snapcore/snapd/dirs" 30 31 "github.com/snapcore/snapd/overlord/snapstate/backend" 32 ) 33 34 type aliasesSuite struct { 35 be backend.Backend 36 base string 37 } 38 39 // silly wrappers to get better failure messages 40 type noBaseAliasesSuite struct{ aliasesSuite } 41 type withBaseAliasesSuite struct{ aliasesSuite } 42 type withSnapdAliasesSuite struct{ aliasesSuite } 43 44 var _ = Suite(&noBaseAliasesSuite{}) 45 var _ = Suite(&withBaseAliasesSuite{aliasesSuite{base: "core99"}}) 46 var _ = Suite(&withSnapdAliasesSuite{aliasesSuite{base: "core-with-snapd"}}) 47 48 func (s *aliasesSuite) SetUpTest(c *C) { 49 dirs.SetRootDir(c.MkDir()) 50 if s.base == "core-with-snapd" { 51 c.Check(os.MkdirAll(filepath.Join(dirs.SnapMountDir, "snapd/current/usr/lib/snapd"), 0755), IsNil) 52 } 53 err := os.MkdirAll(dirs.SnapBinariesDir, 0755) 54 c.Assert(err, IsNil) 55 c.Assert(os.MkdirAll(dirs.CompletersDir, 0755), IsNil) 56 c.Assert(os.MkdirAll(filepath.Dir(dirs.CompleteShPath(s.base)), 0755), IsNil) 57 c.Assert(ioutil.WriteFile(dirs.CompleteShPath(s.base), nil, 0644), IsNil) 58 } 59 60 func (s *aliasesSuite) TearDownTest(c *C) { 61 dirs.SetRootDir("") 62 } 63 64 func missingAliases(aliases []*backend.Alias) (missingAs, missingCs []*backend.Alias, err error) { 65 for _, cand := range aliases { 66 _, err = os.Lstat(filepath.Join(dirs.SnapBinariesDir, cand.Name)) 67 if err != nil { 68 if !os.IsNotExist(err) { 69 return nil, nil, err 70 } 71 missingAs = append(missingAs, cand) 72 } 73 74 _, err = os.Lstat(filepath.Join(dirs.CompletersDir, cand.Name)) 75 if err != nil { 76 if !os.IsNotExist(err) { 77 return nil, nil, err 78 } 79 missingCs = append(missingCs, cand) 80 } 81 } 82 return missingAs, missingCs, nil 83 } 84 85 func (s *aliasesSuite) TestMissingAliases(c *C) { 86 err := os.Symlink("x.foo", filepath.Join(dirs.SnapBinariesDir, "foo")) 87 c.Assert(err, IsNil) 88 c.Assert(os.Symlink("x.a", filepath.Join(dirs.CompletersDir, "a")), IsNil) 89 90 missingAs, missingCs, err := missingAliases([]*backend.Alias{{Name: "a", Target: "x.a"}, {Name: "foo", Target: "x.foo"}}) 91 c.Assert(err, IsNil) 92 c.Check(missingAs, DeepEquals, []*backend.Alias{{Name: "a", Target: "x.a"}}) 93 c.Check(missingCs, DeepEquals, []*backend.Alias{{Name: "foo", Target: "x.foo"}}) 94 } 95 96 func matchingAliases(aliases []*backend.Alias) (matchingAs, matchingCs []*backend.Alias, err error) { 97 for _, cand := range aliases { 98 target, err := os.Readlink(filepath.Join(dirs.SnapBinariesDir, cand.Name)) 99 if err == nil { 100 if target == cand.Target { 101 matchingAs = append(matchingAs, cand) 102 } 103 } else if !os.IsNotExist(err) { 104 return nil, nil, err 105 } 106 107 target, err = os.Readlink(filepath.Join(dirs.CompletersDir, cand.Name)) 108 if err == nil { 109 if target == cand.Target { 110 matchingCs = append(matchingCs, cand) 111 } 112 } else if !os.IsNotExist(err) { 113 return nil, nil, err 114 } 115 } 116 return matchingAs, matchingCs, nil 117 } 118 119 func (s *aliasesSuite) TestMatchingAliases(c *C) { 120 err := os.Symlink("x.foo", filepath.Join(dirs.SnapBinariesDir, "foo")) 121 c.Assert(err, IsNil) 122 err = os.Symlink("y.bar", filepath.Join(dirs.SnapBinariesDir, "bar")) 123 c.Assert(err, IsNil) 124 c.Assert(os.Symlink("y.foo", filepath.Join(dirs.CompletersDir, "foo")), IsNil) 125 c.Assert(os.Symlink("x.bar", filepath.Join(dirs.CompletersDir, "bar")), IsNil) 126 127 matchingAs, matchingCs, err := matchingAliases([]*backend.Alias{{Name: "a", Target: "x.a"}, {Name: "foo", Target: "x.foo"}, {Name: "bar", Target: "x.bar"}}) 128 c.Assert(err, IsNil) 129 c.Check(matchingAs, DeepEquals, []*backend.Alias{{Name: "foo", Target: "x.foo"}}) 130 c.Check(matchingCs, DeepEquals, []*backend.Alias{{Name: "bar", Target: "x.bar"}}) 131 } 132 133 func (s *aliasesSuite) TestUpdateAliasesAdd(c *C) { 134 aliases := []*backend.Alias{{Name: "foo", Target: "x.foo"}, {Name: "bar", Target: "x.bar"}} 135 136 err := s.be.UpdateAliases(aliases, nil) 137 c.Assert(err, IsNil) 138 139 matchingAs, matchingCs, err := matchingAliases(aliases) 140 c.Assert(err, IsNil) 141 c.Check(matchingAs, DeepEquals, aliases) 142 c.Check(matchingCs, HasLen, 0) 143 } 144 145 func mkCompleters(c *C, base string, apps ...string) { 146 for _, app := range apps { 147 c.Assert(os.Symlink(dirs.CompleteShPath(base), filepath.Join(dirs.CompletersDir, app)), IsNil) 148 } 149 } 150 151 func (s *aliasesSuite) TestUpdateAliasesAddWithCompleter(c *C) { 152 mkCompleters(c, s.base, "x.bar", "x.foo") 153 aliases := []*backend.Alias{{Name: "foo", Target: "x.foo"}, {Name: "bar", Target: "x.bar"}} 154 155 err := s.be.UpdateAliases(aliases, nil) 156 c.Assert(err, IsNil) 157 158 matchingAs, matchingCs, err := matchingAliases(aliases) 159 c.Assert(err, IsNil) 160 c.Check(matchingAs, DeepEquals, aliases) 161 c.Check(matchingCs, DeepEquals, aliases) 162 } 163 164 func (s *aliasesSuite) TestUpdateAliasesAddIdempot(c *C) { 165 aliases := []*backend.Alias{{Name: "foo", Target: "x.foo"}, {Name: "bar", Target: "x.bar"}} 166 167 err := s.be.UpdateAliases(aliases, nil) 168 c.Assert(err, IsNil) 169 170 err = s.be.UpdateAliases(aliases, nil) 171 c.Assert(err, IsNil) 172 173 matchingAs, matchingCs, err := matchingAliases(aliases) 174 c.Assert(err, IsNil) 175 c.Check(matchingAs, DeepEquals, aliases) 176 c.Check(matchingCs, HasLen, 0) 177 } 178 179 func (s *aliasesSuite) TestUpdateAliasesAddWithCompleterIdempot(c *C) { 180 mkCompleters(c, s.base, "x.foo", "x.bar") 181 aliases := []*backend.Alias{{Name: "foo", Target: "x.foo"}, {Name: "bar", Target: "x.bar"}} 182 183 err := s.be.UpdateAliases(aliases, nil) 184 c.Assert(err, IsNil) 185 186 err = s.be.UpdateAliases(aliases, nil) 187 c.Assert(err, IsNil) 188 189 matchingAs, matchingCs, err := matchingAliases(aliases) 190 c.Assert(err, IsNil) 191 c.Check(matchingAs, DeepEquals, aliases) 192 c.Check(matchingCs, DeepEquals, aliases) 193 } 194 195 func (s *aliasesSuite) TestUpdateAliasesRemove(c *C) { 196 aliases := []*backend.Alias{{Name: "foo", Target: "x.foo"}, {Name: "bar", Target: "x.bar"}} 197 198 err := s.be.UpdateAliases(aliases, nil) 199 c.Assert(err, IsNil) 200 201 matchingAs, matchingCs, err := matchingAliases(aliases) 202 c.Assert(err, IsNil) 203 c.Check(matchingAs, DeepEquals, aliases) 204 c.Check(matchingCs, HasLen, 0) 205 206 err = s.be.UpdateAliases(nil, aliases) 207 c.Assert(err, IsNil) 208 209 missingAs, missingCs, err := missingAliases(aliases) 210 c.Assert(err, IsNil) 211 c.Check(missingAs, DeepEquals, aliases) 212 c.Check(missingCs, DeepEquals, aliases) 213 214 matchingAs, matchingCs, err = matchingAliases(aliases) 215 c.Assert(err, IsNil) 216 c.Check(matchingAs, HasLen, 0) 217 c.Check(matchingCs, HasLen, 0) 218 } 219 220 func (s *aliasesSuite) TestUpdateAliasesWithCompleterRemove(c *C) { 221 mkCompleters(c, s.base, "x.foo", "x.bar") 222 aliases := []*backend.Alias{{Name: "foo", Target: "x.foo"}, {Name: "bar", Target: "x.bar"}} 223 224 err := s.be.UpdateAliases(aliases, nil) 225 c.Assert(err, IsNil) 226 227 matchingAs, matchingCs, err := matchingAliases(aliases) 228 c.Assert(err, IsNil) 229 c.Check(matchingAs, HasLen, len(aliases)) 230 c.Check(matchingCs, HasLen, len(aliases)) 231 232 err = s.be.UpdateAliases(nil, aliases) 233 c.Assert(err, IsNil) 234 235 missingAs, missingCs, err := missingAliases(aliases) 236 c.Assert(err, IsNil) 237 c.Check(missingAs, DeepEquals, aliases) 238 c.Check(missingCs, DeepEquals, aliases) 239 240 matchingAs, matchingCs, err = matchingAliases(aliases) 241 c.Assert(err, IsNil) 242 c.Check(matchingAs, HasLen, 0) 243 c.Check(matchingCs, HasLen, 0) 244 } 245 246 func (s *aliasesSuite) TestUpdateAliasesRemoveIdempot(c *C) { 247 aliases := []*backend.Alias{{Name: "foo", Target: "x.foo"}, {Name: "bar", Target: "x.bar"}} 248 249 err := s.be.UpdateAliases(aliases, nil) 250 c.Assert(err, IsNil) 251 252 err = s.be.UpdateAliases(nil, aliases) 253 c.Assert(err, IsNil) 254 255 err = s.be.UpdateAliases(nil, aliases) 256 c.Assert(err, IsNil) 257 258 missingAs, missingCs, err := missingAliases(aliases) 259 c.Assert(err, IsNil) 260 c.Check(missingAs, DeepEquals, aliases) 261 c.Check(missingCs, DeepEquals, aliases) 262 263 matchingAs, matchingCs, err := matchingAliases(aliases) 264 c.Assert(err, IsNil) 265 c.Check(matchingAs, HasLen, 0) 266 c.Check(matchingCs, HasLen, 0) 267 } 268 269 func (s *aliasesSuite) TestUpdateAliasesWithCompleterRemoveIdempot(c *C) { 270 mkCompleters(c, s.base, "x.foo", "x.bar") 271 aliases := []*backend.Alias{{Name: "foo", Target: "x.foo"}, {Name: "bar", Target: "x.bar"}} 272 273 err := s.be.UpdateAliases(aliases, nil) 274 c.Assert(err, IsNil) 275 276 err = s.be.UpdateAliases(nil, aliases) 277 c.Assert(err, IsNil) 278 279 err = s.be.UpdateAliases(nil, aliases) 280 c.Assert(err, IsNil) 281 282 missingAs, missingCs, err := missingAliases(aliases) 283 c.Assert(err, IsNil) 284 c.Check(missingAs, DeepEquals, aliases) 285 c.Check(missingCs, DeepEquals, aliases) 286 287 matchingAs, matchingCs, err := matchingAliases(aliases) 288 c.Assert(err, IsNil) 289 c.Check(matchingAs, HasLen, 0) 290 c.Check(matchingCs, HasLen, 0) 291 } 292 293 func (s *aliasesSuite) TestUpdateAliasesAddRemoveOverlap(c *C) { 294 before := []*backend.Alias{{Name: "bar", Target: "x.bar"}} 295 after := []*backend.Alias{{Name: "bar", Target: "x.baz"}} 296 297 err := s.be.UpdateAliases(before, nil) 298 c.Assert(err, IsNil) 299 300 err = s.be.UpdateAliases(after, before) 301 c.Assert(err, IsNil) 302 303 matchingAs, matchingCs, err := matchingAliases(before) 304 c.Assert(err, IsNil) 305 c.Check(matchingAs, HasLen, 0) 306 c.Check(matchingCs, HasLen, 0) 307 matchingAs, matchingCs, err = matchingAliases(after) 308 c.Assert(err, IsNil) 309 c.Check(matchingAs, DeepEquals, after) 310 c.Check(matchingCs, HasLen, 0) 311 } 312 313 func (s *aliasesSuite) TestUpdateAliasesWithCompleterAddRemoveOverlap(c *C) { 314 mkCompleters(c, s.base, "x.baz", "x.bar") 315 before := []*backend.Alias{{Name: "bar", Target: "x.bar"}} 316 after := []*backend.Alias{{Name: "bar", Target: "x.baz"}} 317 318 err := s.be.UpdateAliases(before, nil) 319 c.Assert(err, IsNil) 320 321 err = s.be.UpdateAliases(after, before) 322 c.Assert(err, IsNil) 323 324 matchingAs, matchingCs, err := matchingAliases(before) 325 c.Assert(err, IsNil) 326 c.Check(matchingAs, HasLen, 0) 327 c.Check(matchingCs, HasLen, 0) 328 matchingAs, matchingCs, err = matchingAliases(after) 329 c.Assert(err, IsNil) 330 c.Check(matchingAs, DeepEquals, after) 331 c.Check(matchingCs, DeepEquals, after) 332 } 333 334 func (s *aliasesSuite) TestRemoveSnapAliases(c *C) { 335 aliases := []*backend.Alias{{Name: "bar", Target: "x.bar"}, {Name: "baz", Target: "y.baz"}} 336 337 err := s.be.UpdateAliases(aliases, nil) 338 c.Assert(err, IsNil) 339 340 err = s.be.RemoveSnapAliases("x") 341 c.Assert(err, IsNil) 342 343 matchingAs, matchingCs, err := matchingAliases(aliases) 344 c.Assert(err, IsNil) 345 c.Check(matchingAs, DeepEquals, []*backend.Alias{{Name: "baz", Target: "y.baz"}}) 346 // no completion for the commands -> no completion for the aliases 347 c.Check(matchingCs, HasLen, 0) 348 } 349 350 func (s *aliasesSuite) TestRemoveSnapAliasesWithCompleter(c *C) { 351 mkCompleters(c, s.base, "x", "x.bar", "y", "y.baz") 352 aliases := []*backend.Alias{ 353 {Name: "xx", Target: "x"}, 354 {Name: "bar", Target: "x.bar"}, 355 {Name: "baz", Target: "y.baz"}, 356 {Name: "yy", Target: "y"}} 357 358 err := s.be.UpdateAliases(aliases, nil) 359 c.Assert(err, IsNil) 360 361 err = s.be.RemoveSnapAliases("x") 362 c.Assert(err, IsNil) 363 364 matchingAs, matchingCs, err := matchingAliases(aliases) 365 c.Assert(err, IsNil) 366 c.Check(matchingAs, DeepEquals, []*backend.Alias{{Name: "baz", Target: "y.baz"}, {Name: "yy", Target: "y"}}) 367 c.Check(matchingCs, DeepEquals, []*backend.Alias{{Name: "baz", Target: "y.baz"}, {Name: "yy", Target: "y"}}) 368 }