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