github.com/anonymouse64/snapd@v0.0.0-20210824153203-04c4c42d842d/cmd/snap-update-ns/bootstrap_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  	. "gopkg.in/check.v1"
    24  
    25  	update "github.com/snapcore/snapd/cmd/snap-update-ns"
    26  )
    27  
    28  type bootstrapSuite struct{}
    29  
    30  var _ = Suite(&bootstrapSuite{})
    31  
    32  // Check that ValidateSnapName rejects "/" and "..".
    33  func (s *bootstrapSuite) TestValidateInstanceName(c *C) {
    34  	validNames := []string{
    35  		"aa",
    36  		"aa_a",
    37  		"hello-world",
    38  		"a123456789012345678901234567890123456789",
    39  		"a123456789012345678901234567890123456789_0123456789",
    40  		"hello-world_foo",
    41  		"foo_0123456789",
    42  		"foo_1234abcd",
    43  		"a123456789012345678901234567890123456789",
    44  		"a123456789012345678901234567890123456789_0123456789",
    45  	}
    46  	for _, name := range validNames {
    47  		c.Check(update.ValidateInstanceName(name), Equals, 0, Commentf("name %q should be valid but is not", name))
    48  	}
    49  
    50  	invalidNames := []string{
    51  		"",
    52  		"a",
    53  		"a_a",
    54  		"a123456789012345678901234567890123456789_01234567890",
    55  		"hello/world",
    56  		"hello..world",
    57  		"INVALID",
    58  		"-invalid",
    59  		"hello-world_",
    60  		"_foo",
    61  		"foo_01234567890",
    62  		"foo_123_456",
    63  		"foo__456",
    64  		"foo_",
    65  		"hello-world_foo_foo",
    66  		"foo01234567890012345678900123456789001234567890",
    67  		"foo01234567890012345678900123456789001234567890_foo",
    68  		"a123456789012345678901234567890123456789_0123456789_",
    69  	}
    70  	for _, name := range invalidNames {
    71  		c.Check(update.ValidateInstanceName(name), Equals, -1, Commentf("name %q should be invalid but is valid", name))
    72  	}
    73  
    74  }
    75  
    76  // Test various cases of command line handling.
    77  func (s *bootstrapSuite) TestProcessArguments(c *C) {
    78  	cases := []struct {
    79  		cmdline     []string
    80  		snapName    string
    81  		shouldSetNs bool
    82  		userFstab   bool
    83  		uid         uint
    84  		errPattern  string
    85  	}{
    86  		// Corrupted buffer is dealt with.
    87  		{[]string{}, "", false, false, 0, "argv0 is corrupted"},
    88  		// When testing real bootstrap is identified and disabled.
    89  		{[]string{"argv0.test"}, "", false, false, 0, "bootstrap is not enabled while testing"},
    90  		// Snap name is mandatory.
    91  		{[]string{"argv0"}, "", false, false, 0, "snap name not provided"},
    92  		// Snap name is parsed correctly.
    93  		{[]string{"argv0", "snapname"}, "snapname", true, false, 0, ""},
    94  		{[]string{"argv0", "snapname_instance"}, "snapname_instance", true, false, 0, ""},
    95  		// Onlye one snap name is allowed.
    96  		{[]string{"argv0", "snapone", "snaptwo"}, "", false, false, 0, "too many positional arguments"},
    97  		// Snap name is validated correctly.
    98  		{[]string{"argv0", ""}, "", false, false, 0, "snap name must contain at least one letter"},
    99  		{[]string{"argv0", "in--valid"}, "", false, false, 0, "snap name cannot contain two consecutive dashes"},
   100  		{[]string{"argv0", "invalid-"}, "", false, false, 0, "snap name cannot end with a dash"},
   101  		{[]string{"argv0", "@invalid"}, "", false, false, 0, "snap name must use lower case letters, digits or dashes"},
   102  		{[]string{"argv0", "INVALID"}, "", false, false, 0, "snap name must use lower case letters, digits or dashes"},
   103  		{[]string{"argv0", "foo_01234567890"}, "", false, false, 0, "instance key must be shorter than 10 characters"},
   104  		{[]string{"argv0", "foo_0123456_2"}, "", false, false, 0, "snap instance name can contain only one underscore"},
   105  		// The option --from-snap-confine disables setns.
   106  		{[]string{"argv0", "--from-snap-confine", "snapname"}, "snapname", false, false, 0, ""},
   107  		{[]string{"argv0", "snapname", "--from-snap-confine"}, "snapname", false, false, 0, ""},
   108  		// The option --user-mounts switches to the real uid
   109  		{[]string{"argv0", "--user-mounts", "snapname"}, "snapname", false, true, 0, ""},
   110  		// Unknown options are reported.
   111  		{[]string{"argv0", "-invalid"}, "", false, false, 0, "unsupported option"},
   112  		{[]string{"argv0", "--option"}, "", false, false, 0, "unsupported option"},
   113  		{[]string{"argv0", "--from-snap-confine", "-invalid", "snapname"}, "", false, false, 0, "unsupported option"},
   114  		// The -u option can be used to specify the user id.
   115  		{[]string{"argv0", "snapname", "-u", "1234"}, "snapname", true, true, 1234, ""},
   116  		{[]string{"argv0", "-u", "1234", "snapname"}, "snapname", true, true, 1234, ""},
   117  		/* Empty user id is rejected. */
   118  		{[]string{"argv0", "-u", "", "snapname"}, "", false, false, 0, "cannot parse user id"},
   119  		/* Partially parsed values are rejected. */
   120  		{[]string{"argv0", "-u", "1foo", "snapname"}, "", false, false, 0, "cannot parse user id"},
   121  		/* Hexadecimal values are rejected. */
   122  		{[]string{"argv0", "-u", "0x16", "snapname"}, "", false, false, 0, "cannot parse user id"},
   123  		{[]string{"argv0", "-u", " 0x16", "snapname"}, "", false, false, 0, "cannot parse user id"},
   124  		{[]string{"argv0", "-u", "0x16 ", "snapname"}, "", false, false, 0, "cannot parse user id"},
   125  		{[]string{"argv0", "-u", " 0x16 ", "snapname"}, "", false, false, 0, "cannot parse user id"},
   126  		/* Octal-looking values are parsed as decimal. */
   127  		{[]string{"argv0", "-u", "042", "snapname"}, "snapname", true, true, 42, ""},
   128  		/* Spaces around octal values is rejected. */
   129  		{[]string{"argv0", "-u", " 042", "snapname"}, "", false, false, 0, "cannot parse user id"},
   130  		{[]string{"argv0", "-u", "042 ", "snapname"}, "", false, false, 0, "cannot parse user id"},
   131  		{[]string{"argv0", "-u", " 042 ", "snapname"}, "", false, false, 0, "cannot parse user id"},
   132  		/* Space around the value is rejected. */
   133  		{[]string{"argv0", "-u", "42 ", "snapname"}, "", false, false, 0, "cannot parse user id"},
   134  		{[]string{"argv0", "-u", " 42", "snapname"}, "", false, false, 0, "cannot parse user id"},
   135  		{[]string{"argv0", "-u", " 42 ", "snapname"}, "", false, false, 0, "cannot parse user id"},
   136  		{[]string{"argv0", "-u", "\n42 ", "snapname"}, "", false, false, 0, "cannot parse user id"},
   137  		{[]string{"argv0", "-u", "42\t", "snapname"}, "", false, false, 0, "cannot parse user id"},
   138  		/* Negative values are rejected. */
   139  		{[]string{"argv0", "-u", "-1", "snapname"}, "", false, false, 0, "user id cannot be negative"},
   140  		/* The option -u requires an argument. */
   141  		{[]string{"argv0", "snapname", "-u"}, "", false, false, 0, "-u requires an argument"},
   142  	}
   143  	for _, tc := range cases {
   144  		update.ClearBootstrapError()
   145  		snapName, shouldSetNs, userFstab, uid := update.ProcessArguments(tc.cmdline)
   146  		err := update.BootstrapError()
   147  		comment := Commentf("failed with cmdline %q, expected error pattern %q, actual error %q",
   148  			tc.cmdline, tc.errPattern, err)
   149  		if tc.errPattern != "" {
   150  			c.Assert(err, ErrorMatches, tc.errPattern, comment)
   151  		} else {
   152  			c.Assert(err, IsNil, comment)
   153  		}
   154  		c.Check(snapName, Equals, tc.snapName, comment)
   155  		c.Check(shouldSetNs, Equals, tc.shouldSetNs, comment)
   156  		c.Check(userFstab, Equals, tc.userFstab, comment)
   157  		c.Check(uid, Equals, tc.uid, comment)
   158  	}
   159  }