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  }