github.com/rigado/snapd@v2.42.5-go-mod+incompatible/snap/snapenv/snapenv_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2014-2015 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 snapenv
    21  
    22  import (
    23  	"fmt"
    24  	"os"
    25  	"os/user"
    26  	"strings"
    27  	"testing"
    28  
    29  	. "gopkg.in/check.v1"
    30  
    31  	"github.com/snapcore/snapd/arch"
    32  	"github.com/snapcore/snapd/dirs"
    33  	"github.com/snapcore/snapd/osutil/sys"
    34  	"github.com/snapcore/snapd/snap"
    35  	"github.com/snapcore/snapd/testutil"
    36  )
    37  
    38  func Test(t *testing.T) { TestingT(t) }
    39  
    40  type HTestSuite struct {
    41  	testutil.BaseTest
    42  }
    43  
    44  var _ = Suite(&HTestSuite{})
    45  
    46  var mockYaml = []byte(`name: snapname
    47  version: 1.0
    48  apps:
    49   app:
    50    command: run-app
    51  hooks:
    52   configure:
    53  `)
    54  
    55  var mockSnapInfo = &snap.Info{
    56  	SuggestedName: "foo",
    57  	Version:       "1.0",
    58  	SideInfo: snap.SideInfo{
    59  		Revision: snap.R(17),
    60  	},
    61  }
    62  var mockClassicSnapInfo = &snap.Info{
    63  	SuggestedName: "foo",
    64  	Version:       "1.0",
    65  	SideInfo: snap.SideInfo{
    66  		Revision: snap.R(17),
    67  	},
    68  	Confinement: snap.ClassicConfinement,
    69  }
    70  
    71  func (s *HTestSuite) SetUpTest(c *C) {
    72  	s.BaseTest.SetUpTest(c)
    73  	s.BaseTest.AddCleanup(snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {}))
    74  }
    75  
    76  func (s *HTestSuite) TearDownTest(c *C) {
    77  	s.BaseTest.TearDownTest(c)
    78  }
    79  
    80  func (ts *HTestSuite) TestBasic(c *C) {
    81  	env := basicEnv(mockSnapInfo)
    82  
    83  	c.Assert(env, DeepEquals, map[string]string{
    84  		"SNAP":               fmt.Sprintf("%s/foo/17", dirs.CoreSnapMountDir),
    85  		"SNAP_ARCH":          arch.DpkgArchitecture(),
    86  		"SNAP_COMMON":        "/var/snap/foo/common",
    87  		"SNAP_DATA":          "/var/snap/foo/17",
    88  		"SNAP_LIBRARY_PATH":  "/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void",
    89  		"SNAP_NAME":          "foo",
    90  		"SNAP_INSTANCE_NAME": "foo",
    91  		"SNAP_INSTANCE_KEY":  "",
    92  		"SNAP_REEXEC":        "",
    93  		"SNAP_REVISION":      "17",
    94  		"SNAP_VERSION":       "1.0",
    95  	})
    96  
    97  }
    98  
    99  func (ts *HTestSuite) TestUser(c *C) {
   100  	env := userEnv(mockSnapInfo, "/root")
   101  
   102  	c.Assert(env, DeepEquals, map[string]string{
   103  		"HOME":             "/root/snap/foo/17",
   104  		"SNAP_USER_COMMON": "/root/snap/foo/common",
   105  		"SNAP_USER_DATA":   "/root/snap/foo/17",
   106  		"XDG_RUNTIME_DIR":  fmt.Sprintf("/run/user/%d/snap.foo", sys.Geteuid()),
   107  	})
   108  }
   109  
   110  func (ts *HTestSuite) TestUserForClassicConfinement(c *C) {
   111  	env := userEnv(mockClassicSnapInfo, "/root")
   112  
   113  	c.Assert(env, DeepEquals, map[string]string{
   114  		// NOTE HOME Is absent! we no longer override it
   115  		"SNAP_USER_COMMON": "/root/snap/foo/common",
   116  		"SNAP_USER_DATA":   "/root/snap/foo/17",
   117  		"XDG_RUNTIME_DIR":  fmt.Sprintf("/run/user/%d/snap.foo", sys.Geteuid()),
   118  	})
   119  }
   120  
   121  func (s *HTestSuite) TestSnapRunSnapExecEnv(c *C) {
   122  	info, err := snap.InfoFromSnapYaml(mockYaml)
   123  	c.Assert(err, IsNil)
   124  	info.SideInfo.Revision = snap.R(42)
   125  
   126  	usr, err := user.Current()
   127  	c.Assert(err, IsNil)
   128  
   129  	homeEnv := os.Getenv("HOME")
   130  	defer os.Setenv("HOME", homeEnv)
   131  
   132  	for _, withHomeEnv := range []bool{true, false} {
   133  		if !withHomeEnv {
   134  			os.Setenv("HOME", "")
   135  		}
   136  
   137  		env := snapEnv(info)
   138  		c.Check(env, DeepEquals, map[string]string{
   139  			"SNAP_ARCH":          arch.DpkgArchitecture(),
   140  			"SNAP_LIBRARY_PATH":  "/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void",
   141  			"SNAP_NAME":          "snapname",
   142  			"SNAP_INSTANCE_NAME": "snapname",
   143  			"SNAP_INSTANCE_KEY":  "",
   144  			"SNAP_REEXEC":        "",
   145  			"SNAP_REVISION":      "42",
   146  			"SNAP_VERSION":       "1.0",
   147  
   148  			"SNAP":        fmt.Sprintf("%s/snapname/42", dirs.CoreSnapMountDir),
   149  			"SNAP_COMMON": "/var/snap/snapname/common",
   150  			"SNAP_DATA":   "/var/snap/snapname/42",
   151  
   152  			"SNAP_USER_COMMON": fmt.Sprintf("%s/snap/snapname/common", usr.HomeDir),
   153  			"SNAP_USER_DATA":   fmt.Sprintf("%s/snap/snapname/42", usr.HomeDir),
   154  			"XDG_RUNTIME_DIR":  fmt.Sprintf("/run/user/%d/snap.snapname", sys.Geteuid()),
   155  			"HOME":             fmt.Sprintf("%s/snap/snapname/42", usr.HomeDir),
   156  		})
   157  	}
   158  }
   159  
   160  func (s *HTestSuite) TestParallelInstallSnapRunSnapExecEnv(c *C) {
   161  	info, err := snap.InfoFromSnapYaml(mockYaml)
   162  	c.Assert(err, IsNil)
   163  	info.SideInfo.Revision = snap.R(42)
   164  
   165  	usr, err := user.Current()
   166  	c.Assert(err, IsNil)
   167  
   168  	homeEnv := os.Getenv("HOME")
   169  	defer os.Setenv("HOME", homeEnv)
   170  
   171  	// pretend it's snapname_foo
   172  	info.InstanceKey = "foo"
   173  
   174  	for _, withHomeEnv := range []bool{true, false} {
   175  		if !withHomeEnv {
   176  			os.Setenv("HOME", "")
   177  		}
   178  
   179  		env := snapEnv(info)
   180  		c.Check(env, DeepEquals, map[string]string{
   181  			"SNAP_ARCH":          arch.DpkgArchitecture(),
   182  			"SNAP_LIBRARY_PATH":  "/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void",
   183  			"SNAP_NAME":          "snapname",
   184  			"SNAP_INSTANCE_NAME": "snapname_foo",
   185  			"SNAP_INSTANCE_KEY":  "foo",
   186  			"SNAP_REEXEC":        "",
   187  			"SNAP_REVISION":      "42",
   188  			"SNAP_VERSION":       "1.0",
   189  
   190  			// Those are mapped to snap-specific directories by
   191  			// mount namespace setup
   192  			"SNAP":        fmt.Sprintf("%s/snapname/42", dirs.CoreSnapMountDir),
   193  			"SNAP_COMMON": "/var/snap/snapname/common",
   194  			"SNAP_DATA":   "/var/snap/snapname/42",
   195  
   196  			// User's data directories are not mapped to
   197  			// snap-specific ones
   198  			"SNAP_USER_COMMON": fmt.Sprintf("%s/snap/snapname_foo/common", usr.HomeDir),
   199  			"SNAP_USER_DATA":   fmt.Sprintf("%s/snap/snapname_foo/42", usr.HomeDir),
   200  			"XDG_RUNTIME_DIR":  fmt.Sprintf("/run/user/%d/snap.snapname_foo", sys.Geteuid()),
   201  			"HOME":             fmt.Sprintf("%s/snap/snapname_foo/42", usr.HomeDir),
   202  		})
   203  	}
   204  }
   205  
   206  func (ts *HTestSuite) TestParallelInstallUser(c *C) {
   207  	info := *mockSnapInfo
   208  	info.InstanceKey = "bar"
   209  	env := userEnv(&info, "/root")
   210  
   211  	c.Assert(env, DeepEquals, map[string]string{
   212  		"HOME":             "/root/snap/foo_bar/17",
   213  		"SNAP_USER_COMMON": "/root/snap/foo_bar/common",
   214  		"SNAP_USER_DATA":   "/root/snap/foo_bar/17",
   215  		"XDG_RUNTIME_DIR":  fmt.Sprintf("/run/user/%d/snap.foo_bar", sys.Geteuid()),
   216  	})
   217  }
   218  
   219  func (ts *HTestSuite) TestParallelInstallUserForClassicConfinement(c *C) {
   220  	info := *mockClassicSnapInfo
   221  	info.InstanceKey = "bar"
   222  	env := userEnv(&info, "/root")
   223  
   224  	c.Assert(env, DeepEquals, map[string]string{
   225  		// NOTE HOME Is absent! we no longer override it
   226  		"SNAP_USER_COMMON": "/root/snap/foo_bar/common",
   227  		"SNAP_USER_DATA":   "/root/snap/foo_bar/17",
   228  		"XDG_RUNTIME_DIR":  fmt.Sprintf("/run/user/%d/snap.foo_bar", sys.Geteuid()),
   229  	})
   230  }
   231  
   232  func envValue(env []string, key string) (bool, string) {
   233  	for _, item := range env {
   234  		if strings.HasPrefix(item, key+"=") {
   235  			return true, strings.SplitN(item, "=", 2)[1]
   236  		}
   237  	}
   238  	return false, ""
   239  }
   240  
   241  func (s *HTestSuite) TestExtraEnvForExecEnv(c *C) {
   242  	info, err := snap.InfoFromSnapYaml(mockYaml)
   243  	c.Assert(err, IsNil)
   244  	info.SideInfo.Revision = snap.R(42)
   245  
   246  	env := ExecEnv(info, map[string]string{"FOO": "BAR"})
   247  	found, val := envValue(env, "FOO")
   248  	c.Assert(found, Equals, true)
   249  	c.Assert(val, Equals, "BAR")
   250  }
   251  
   252  func setenvWithReset(s *HTestSuite, key string, val string) {
   253  	tmpdirEnv, tmpdirFound := os.LookupEnv("TMPDIR")
   254  	os.Setenv("TMPDIR", "/var/tmp")
   255  	if tmpdirFound {
   256  		s.AddCleanup(func() { os.Setenv("TMPDIR", tmpdirEnv) })
   257  	} else {
   258  		s.AddCleanup(func() { os.Unsetenv("TMPDIR") })
   259  	}
   260  }
   261  
   262  func (s *HTestSuite) TestExecEnvNoRenameTMPDIRForNonClassic(c *C) {
   263  	setenvWithReset(s, "TMPDIR", "/var/tmp")
   264  
   265  	env := ExecEnv(mockSnapInfo, map[string]string{})
   266  
   267  	found, val := envValue(env, "TMPDIR")
   268  	c.Assert(found, Equals, true)
   269  	c.Assert(val, Equals, "/var/tmp")
   270  
   271  	found, _ = envValue(env, PreservedUnsafePrefix+"TMPDIR")
   272  	c.Assert(found, Equals, false)
   273  }
   274  
   275  func (s *HTestSuite) TestExecEnvRenameTMPDIRForClassic(c *C) {
   276  	setenvWithReset(s, "TMPDIR", "/var/tmp")
   277  
   278  	env := ExecEnv(mockClassicSnapInfo, map[string]string{})
   279  
   280  	found, _ := envValue(env, "TMPDIR")
   281  	c.Assert(found, Equals, false)
   282  
   283  	found, val := envValue(env, PreservedUnsafePrefix+"TMPDIR")
   284  	c.Assert(found, Equals, true)
   285  	c.Assert(val, Equals, "/var/tmp")
   286  }