github.com/rigado/snapd@v2.42.5-go-mod+incompatible/cmd/snap-update-ns/common_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 main_test 21 22 import ( 23 "bytes" 24 "io/ioutil" 25 "os" 26 "path/filepath" 27 28 . "gopkg.in/check.v1" 29 30 update "github.com/snapcore/snapd/cmd/snap-update-ns" 31 "github.com/snapcore/snapd/cmd/snaplock" 32 "github.com/snapcore/snapd/dirs" 33 "github.com/snapcore/snapd/osutil" 34 "github.com/snapcore/snapd/testutil" 35 ) 36 37 type commonSuite struct { 38 dir string 39 upCtx *update.CommonProfileUpdateContext 40 } 41 42 var _ = Suite(&commonSuite{}) 43 44 func (s *commonSuite) SetUpTest(c *C) { 45 s.dir = c.MkDir() 46 s.upCtx = update.NewCommonProfileUpdateContext("foo", false, 47 filepath.Join(s.dir, "current.fstab"), 48 filepath.Join(s.dir, "desired.fstab")) 49 } 50 51 func (s *commonSuite) TestInstanceName(c *C) { 52 c.Check(s.upCtx.InstanceName(), Equals, "foo") 53 } 54 55 func (s *commonSuite) TestLock(c *C) { 56 // Mock away real freezer code, allowing test code to return an error when freezing. 57 var freezingError error 58 restore := update.MockFreezing(func(string) error { return freezingError }, func(string) error { return nil }) 59 defer restore() 60 // Mock system directories, we use the lock directory. 61 dirs.SetRootDir(s.dir) 62 defer dirs.SetRootDir("") 63 64 // We will use 2nd lock for our testing. 65 testLock, err := snaplock.OpenLock(s.upCtx.InstanceName()) 66 c.Assert(err, IsNil) 67 defer testLock.Close() 68 69 // When fromSnapConfine is false we acquire our own lock. 70 s.upCtx.SetFromSnapConfine(false) 71 c.Check(s.upCtx.FromSnapConfine(), Equals, false) 72 unlock, err := s.upCtx.Lock() 73 c.Assert(err, IsNil) 74 // The lock is acquired now. We should not be able to get another lock. 75 c.Check(testLock.TryLock(), Equals, osutil.ErrAlreadyLocked) 76 // We can release the original lock now and see our test lock working. 77 unlock() 78 c.Assert(testLock.TryLock(), IsNil) 79 80 // When fromSnapConfine is true we test existing lock but don't grab one. 81 s.upCtx.SetFromSnapConfine(true) 82 c.Check(s.upCtx.FromSnapConfine(), Equals, true) 83 err = testLock.Lock() 84 c.Assert(err, IsNil) 85 unlock, err = s.upCtx.Lock() 86 c.Assert(err, IsNil) 87 unlock() 88 89 // When the test lock is unlocked the common update helper reports an error 90 // since it was expecting the lock to be held. Oh, and the lock is not leaked. 91 testLock.Unlock() 92 unlock, err = s.upCtx.Lock() 93 c.Check(err, ErrorMatches, `mount namespace of snap "foo" is not locked but --from-snap-confine was used`) 94 c.Check(unlock, IsNil) 95 c.Assert(testLock.TryLock(), IsNil) 96 97 // When freezing fails the lock acquired internally is not leaked. 98 freezingError = errTesting 99 s.upCtx.SetFromSnapConfine(false) 100 c.Check(s.upCtx.FromSnapConfine(), Equals, false) 101 testLock.Unlock() 102 unlock, err = s.upCtx.Lock() 103 c.Check(err, Equals, errTesting) 104 c.Check(unlock, IsNil) 105 c.Check(testLock.TryLock(), IsNil) 106 } 107 108 func (s *commonSuite) TestLoadDesiredProfile(c *C) { 109 upCtx := s.upCtx 110 text := "tmpfs /tmp tmpfs defaults 0 0\n" 111 112 // Ask the common profile update helper to read the desired profile. 113 profile, err := upCtx.LoadCurrentProfile() 114 c.Assert(err, IsNil) 115 116 // A profile that is not present on disk just reads as a valid empty profile. 117 c.Check(profile.Entries, HasLen, 0) 118 119 // Write a desired user mount profile for snap "foo". 120 path := upCtx.DesiredProfilePath() 121 c.Assert(os.MkdirAll(filepath.Dir(path), 0755), IsNil) 122 c.Assert(ioutil.WriteFile(path, []byte(text), 0644), IsNil) 123 124 // Ask the common profile update helper to read the desired profile. 125 profile, err = upCtx.LoadDesiredProfile() 126 c.Assert(err, IsNil) 127 builder := &bytes.Buffer{} 128 profile.WriteTo(builder) 129 130 // The profile is returned unchanged. 131 c.Check(builder.String(), Equals, text) 132 } 133 134 func (s *commonSuite) TestLoadCurrentProfile(c *C) { 135 upCtx := s.upCtx 136 text := "tmpfs /tmp tmpfs defaults 0 0\n" 137 138 // Ask the common profile update helper to read the current profile. 139 profile, err := upCtx.LoadCurrentProfile() 140 c.Assert(err, IsNil) 141 142 // A profile that is not present on disk just reads as a valid empty profile. 143 c.Check(profile.Entries, HasLen, 0) 144 145 // Write a current user mount profile for snap "foo". 146 path := upCtx.CurrentProfilePath() 147 c.Assert(os.MkdirAll(filepath.Dir(path), 0755), IsNil) 148 c.Assert(ioutil.WriteFile(path, []byte(text), 0644), IsNil) 149 150 // Ask the common profile update helper to read the current profile. 151 profile, err = upCtx.LoadCurrentProfile() 152 c.Assert(err, IsNil) 153 builder := &bytes.Buffer{} 154 profile.WriteTo(builder) 155 156 // The profile is returned unchanged. 157 c.Check(builder.String(), Equals, text) 158 } 159 160 func (s *commonSuite) TestSaveCurrentProfile(c *C) { 161 upCtx := s.upCtx 162 text := "tmpfs /tmp tmpfs defaults 0 0\n" 163 164 // Prepare a mount profile to be saved. 165 profile, err := osutil.LoadMountProfileText(text) 166 c.Assert(err, IsNil) 167 168 // Prepare the directory for saving the profile. 169 path := upCtx.CurrentProfilePath() 170 c.Assert(os.MkdirAll(filepath.Dir(path), 0755), IsNil) 171 172 // Ask the common profile update to write the current profile. 173 c.Assert(upCtx.SaveCurrentProfile(profile), IsNil) 174 c.Check(path, testutil.FileEquals, text) 175 }