github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/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  }