github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/snap/naming/validate_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 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 naming_test
    21  
    22  import (
    23  	"fmt"
    24  	. "gopkg.in/check.v1"
    25  
    26  	"github.com/snapcore/snapd/snap/naming"
    27  
    28  	"github.com/snapcore/snapd/testutil"
    29  )
    30  
    31  type ValidateSuite struct {
    32  	testutil.BaseTest
    33  }
    34  
    35  var _ = Suite(&ValidateSuite{})
    36  
    37  func (s *ValidateSuite) SetUpTest(c *C) {
    38  	s.BaseTest.SetUpTest(c)
    39  }
    40  
    41  func (s *ValidateSuite) TearDownTest(c *C) {
    42  	s.BaseTest.TearDownTest(c)
    43  }
    44  
    45  func (s *ValidateSuite) TestValidateName(c *C) {
    46  	validNames := []string{
    47  		"aa", "aaa", "aaaa",
    48  		"a-a", "aa-a", "a-aa", "a-b-c",
    49  		"a0", "a-0", "a-0a",
    50  		"01game", "1-or-2",
    51  		// a regexp stresser
    52  		"u-94903713687486543234157734673284536758",
    53  	}
    54  	for _, name := range validNames {
    55  		err := naming.ValidateSnap(name)
    56  		c.Assert(err, IsNil)
    57  	}
    58  	invalidNames := []string{
    59  		// name cannot be empty
    60  		"",
    61  		// too short (min 2 chars)
    62  		"a",
    63  		// names cannot be too long
    64  		"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    65  		"xxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxx",
    66  		"1111111111111111111111111111111111111111x",
    67  		"x1111111111111111111111111111111111111111",
    68  		"x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x",
    69  		// a regexp stresser
    70  		"u-9490371368748654323415773467328453675-",
    71  		// dashes alone are not a name
    72  		"-", "--",
    73  		// double dashes in a name are not allowed
    74  		"a--a",
    75  		// name should not end with a dash
    76  		"a-",
    77  		// name cannot have any spaces in it
    78  		"a ", " a", "a a",
    79  		// a number alone is not a name
    80  		"0", "123",
    81  		// identifier must be plain ASCII
    82  		"日本語", "한글", "ру́сский язы́к",
    83  	}
    84  	for _, name := range invalidNames {
    85  		err := naming.ValidateSnap(name)
    86  		c.Assert(err, ErrorMatches, `invalid snap name: ".*"`)
    87  	}
    88  }
    89  
    90  func (s *ValidateSuite) TestValidateInstanceName(c *C) {
    91  	validNames := []string{
    92  		// plain names are also valid instance names
    93  		"aa", "aaa", "aaaa",
    94  		"a-a", "aa-a", "a-aa", "a-b-c",
    95  		// snap instance
    96  		"foo_bar",
    97  		"foo_0123456789",
    98  		"01game_0123456789",
    99  		"foo_1", "foo_1234abcd",
   100  	}
   101  	for _, name := range validNames {
   102  		err := naming.ValidateInstance(name)
   103  		c.Assert(err, IsNil)
   104  	}
   105  	invalidNames := []string{
   106  		// invalid names are also invalid instance names, just a few
   107  		// samples
   108  		"",
   109  		"a",
   110  		"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
   111  		"xxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxx",
   112  		"a--a",
   113  		"a-",
   114  		"a ", " a", "a a",
   115  		"_",
   116  		"ру́сский_язы́к",
   117  	}
   118  	for _, name := range invalidNames {
   119  		err := naming.ValidateInstance(name)
   120  		c.Assert(err, ErrorMatches, `invalid snap name: ".*"`)
   121  	}
   122  	invalidInstanceKeys := []string{
   123  		// the snap names are valid, but instance keys are not
   124  		"foo_", "foo_1-23", "foo_01234567890", "foo_123_456",
   125  		"foo__bar",
   126  	}
   127  	for _, name := range invalidInstanceKeys {
   128  		err := naming.ValidateInstance(name)
   129  		c.Assert(err, ErrorMatches, `invalid instance key: ".*"`)
   130  	}
   131  
   132  }
   133  
   134  func (s *ValidateSuite) TestValidateHookName(c *C) {
   135  	validHooks := []string{
   136  		"a",
   137  		"aaa",
   138  		"a-a",
   139  		"aa-a",
   140  		"a-aa",
   141  		"a-b-c",
   142  		"valid",
   143  	}
   144  	for _, hook := range validHooks {
   145  		err := naming.ValidateHook(hook)
   146  		c.Assert(err, IsNil)
   147  	}
   148  	invalidHooks := []string{
   149  		"",
   150  		"a a",
   151  		"a--a",
   152  		"-a",
   153  		"a-",
   154  		"0",
   155  		"123",
   156  		"123abc",
   157  		"日本語",
   158  	}
   159  	for _, hook := range invalidHooks {
   160  		err := naming.ValidateHook(hook)
   161  		c.Assert(err, ErrorMatches, `invalid hook name: ".*"`)
   162  	}
   163  	// Regression test for https://bugs.launchpad.net/snapd/+bug/1638988
   164  	c.Assert(naming.ValidateHook("connect-plug-i2c"), IsNil)
   165  }
   166  
   167  func (s *ValidateSuite) TestValidateAppName(c *C) {
   168  	validAppNames := []string{
   169  		"1", "a", "aa", "aaa", "aaaa", "Aa", "aA", "1a", "a1", "1-a", "a-1",
   170  		"a-a", "aa-a", "a-aa", "a-b-c", "0a-a", "a-0a",
   171  	}
   172  	for _, name := range validAppNames {
   173  		c.Check(naming.ValidateApp(name), IsNil)
   174  	}
   175  	invalidAppNames := []string{
   176  		"", "-", "--", "a--a", "a-", "a ", " a", "a a", "日本語", "한글",
   177  		"ру́сский язы́к", "ໄຂ່​ອີ​ສ​ເຕີ້", ":a", "a:", "a:a", "_a", "a_", "a_a",
   178  	}
   179  	for _, name := range invalidAppNames {
   180  		err := naming.ValidateApp(name)
   181  		c.Assert(err, ErrorMatches, `invalid app name: ".*"`)
   182  	}
   183  }
   184  
   185  func (s *ValidateSuite) TestValidateAlias(c *C) {
   186  	validAliases := []string{
   187  		"a", "aa", "aaa", "aaaa",
   188  		"a-a", "aa-a", "a-aa", "a-b-c",
   189  		"a0", "a-0", "a-0a",
   190  		"a_a", "aa_a", "a_aa", "a_b_c",
   191  		"a0", "a_0", "a_0a",
   192  		"01game", "1-or-2",
   193  		"0.1game", "1_or_2",
   194  	}
   195  	for _, alias := range validAliases {
   196  		err := naming.ValidateAlias(alias)
   197  		c.Assert(err, IsNil)
   198  	}
   199  	invalidAliases := []string{
   200  		"",
   201  		"_foo",
   202  		"-foo",
   203  		".foo",
   204  		"foo$",
   205  	}
   206  	for _, alias := range invalidAliases {
   207  		err := naming.ValidateAlias(alias)
   208  		c.Assert(err, ErrorMatches, `invalid alias name: ".*"`)
   209  	}
   210  }
   211  
   212  func (s *ValidateSuite) TestValidateSocketName(c *C) {
   213  	validNames := []string{
   214  		"a", "aa", "aaa", "aaaa",
   215  		"a-a", "aa-a", "a-aa", "a-b-c",
   216  		"a0", "a-0", "a-0a",
   217  		"01game", "1-or-2",
   218  	}
   219  	for _, name := range validNames {
   220  		err := naming.ValidateSocket(name)
   221  		c.Assert(err, IsNil)
   222  	}
   223  	invalidNames := []string{
   224  		// name cannot be empty
   225  		"",
   226  		// dashes alone are not a name
   227  		"-", "--",
   228  		// double dashes in a name are not allowed
   229  		"a--a",
   230  		// name should not end with a dash
   231  		"a-",
   232  		// name cannot have any spaces in it
   233  		"a ", " a", "a a",
   234  		// a number alone is not a name
   235  		"0", "123",
   236  		// identifier must be plain ASCII
   237  		"日本語", "한글", "ру́сский язы́к",
   238  		// no null chars in the string are allowed
   239  		"aa-a\000-b",
   240  	}
   241  	for _, name := range invalidNames {
   242  		err := naming.ValidateSocket(name)
   243  		c.Assert(err, ErrorMatches, `invalid socket name: ".*"`)
   244  	}
   245  }
   246  
   247  func (s *ValidateSuite) TestValidateSlotPlugInterfaceName(c *C) {
   248  	valid := []string{
   249  		"a",
   250  		"aaa",
   251  		"a-a",
   252  		"aa-a",
   253  		"a-aa",
   254  		"a-b-c",
   255  		"valid",
   256  		"valid-123",
   257  	}
   258  	for _, name := range valid {
   259  		err := naming.ValidateSlot(name)
   260  		c.Assert(err, IsNil)
   261  		err = naming.ValidatePlug(name)
   262  		c.Assert(err, IsNil)
   263  		err = naming.ValidateInterface(name)
   264  		c.Assert(err, IsNil)
   265  	}
   266  	invalid := []string{
   267  		"",
   268  		"a a",
   269  		"a--a",
   270  		"-a",
   271  		"a-",
   272  		"0",
   273  		"123",
   274  		"123abc",
   275  		"日本語",
   276  	}
   277  	for _, name := range invalid {
   278  		err := naming.ValidateSlot(name)
   279  		c.Assert(err, ErrorMatches, `invalid slot name: ".*"`)
   280  		err = naming.ValidatePlug(name)
   281  		c.Assert(err, ErrorMatches, `invalid plug name: ".*"`)
   282  		err = naming.ValidateInterface(name)
   283  		c.Assert(err, ErrorMatches, `invalid interface name: ".*"`)
   284  	}
   285  }
   286  
   287  func (s *ValidateSuite) TestValidateSnapID(c *C) {
   288  	c.Check(naming.ValidateSnapID("buPKUD3TKqCOgLEjjHx5kSiCpIs5cMuQ"), IsNil)
   289  
   290  	invalid := []string{
   291  		"",
   292  		"buPKUD3TKqC",
   293  		"buPKUD3TKqCOgLE-jHx5kSiCpIs5cMuQ",
   294  		"buPKUD3TKqCOgLEjjHx5kSiCpIs5cMuQxxx",
   295  	}
   296  	for _, id := range invalid {
   297  		err := naming.ValidateSnapID(id)
   298  		c.Check(err, ErrorMatches, fmt.Sprintf("invalid snap-id: %q", id))
   299  	}
   300  }
   301  
   302  func (s *ValidateSuite) TestValidateSecurityTag(c *C) {
   303  	// valid snap names, snap instances, app names and hook names are accepted.
   304  	c.Check(naming.ValidateSecurityTag("snap.pkg.app"), IsNil)
   305  	c.Check(naming.ValidateSecurityTag("snap.pkg.hook.configure"), IsNil)
   306  	c.Check(naming.ValidateSecurityTag("snap.pkg_key.app"), IsNil)
   307  	c.Check(naming.ValidateSecurityTag("snap.pkg_key.hook.configure"), IsNil)
   308  
   309  	// invalid format is rejected
   310  	c.Check(naming.ValidateSecurityTag("snap.pkg_key.app.surprise"), ErrorMatches, "invalid security tag")
   311  	c.Check(naming.ValidateSecurityTag("snap.pkg_key.hook.configure.surprise"), ErrorMatches, "invalid security tag")
   312  
   313  	// invalid snap and app names are rejected.
   314  	c.Check(naming.ValidateSecurityTag("snap._.app"), ErrorMatches, "invalid security tag")
   315  	c.Check(naming.ValidateSecurityTag("snap.pkg._"), ErrorMatches, "invalid security tag")
   316  
   317  	// invalid number of components are rejected.
   318  	c.Check(naming.ValidateSecurityTag("snap.pkg.hook.surprise."), ErrorMatches, "invalid security tag")
   319  	c.Check(naming.ValidateSecurityTag("snap.pkg.hook."), ErrorMatches, "invalid security tag")
   320  	c.Check(naming.ValidateSecurityTag("snap.pkg.hook"), IsNil) // Perhaps somewhat unexpectedly, this tag is valid.
   321  	c.Check(naming.ValidateSecurityTag("snap.pkg.app.surprise"), ErrorMatches, "invalid security tag")
   322  	c.Check(naming.ValidateSecurityTag("snap.pkg."), ErrorMatches, "invalid security tag")
   323  	c.Check(naming.ValidateSecurityTag("snap.pkg"), ErrorMatches, "invalid security tag")
   324  	c.Check(naming.ValidateSecurityTag("snap."), ErrorMatches, "invalid security tag")
   325  	c.Check(naming.ValidateSecurityTag("snap"), ErrorMatches, "invalid security tag")
   326  }