github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/opts/opts_test.go (about)

     1  package opts // import "github.com/docker/docker/opts"
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  
     8  	"gotest.tools/v3/assert"
     9  	is "gotest.tools/v3/assert/cmp"
    10  )
    11  
    12  func TestValidateIPAddress(t *testing.T) {
    13  	if ret, err := ValidateIPAddress(`1.2.3.4`); err != nil || ret == "" {
    14  		t.Fatalf("ValidateIPAddress(`1.2.3.4`) got %s %s", ret, err)
    15  	}
    16  
    17  	if ret, err := ValidateIPAddress(`127.0.0.1`); err != nil || ret == "" {
    18  		t.Fatalf("ValidateIPAddress(`127.0.0.1`) got %s %s", ret, err)
    19  	}
    20  
    21  	if ret, err := ValidateIPAddress(`::1`); err != nil || ret == "" {
    22  		t.Fatalf("ValidateIPAddress(`::1`) got %s %s", ret, err)
    23  	}
    24  
    25  	if ret, err := ValidateIPAddress(`127`); err == nil || ret != "" {
    26  		t.Fatalf("ValidateIPAddress(`127`) got %s %s", ret, err)
    27  	}
    28  
    29  	if ret, err := ValidateIPAddress(`random invalid string`); err == nil || ret != "" {
    30  		t.Fatalf("ValidateIPAddress(`random invalid string`) got %s %s", ret, err)
    31  	}
    32  }
    33  
    34  func TestMapOpts(t *testing.T) {
    35  	tmpMap := make(map[string]string)
    36  	o := NewMapOpts(tmpMap, logOptsValidator)
    37  	o.Set("max-size=1")
    38  	if o.String() != "map[max-size:1]" {
    39  		t.Errorf("%s != [map[max-size:1]", o.String())
    40  	}
    41  
    42  	o.Set("max-file=2")
    43  	if len(tmpMap) != 2 {
    44  		t.Errorf("map length %d != 2", len(tmpMap))
    45  	}
    46  
    47  	if tmpMap["max-file"] != "2" {
    48  		t.Errorf("max-file = %s != 2", tmpMap["max-file"])
    49  	}
    50  
    51  	if tmpMap["max-size"] != "1" {
    52  		t.Errorf("max-size = %s != 1", tmpMap["max-size"])
    53  	}
    54  	if o.Set("dummy-val=3") == nil {
    55  		t.Error("validator is not being called")
    56  	}
    57  }
    58  
    59  func TestListOptsWithoutValidator(t *testing.T) {
    60  	o := NewListOpts(nil)
    61  	o.Set("foo")
    62  	if o.String() != "[foo]" {
    63  		t.Errorf("%s != [foo]", o.String())
    64  	}
    65  	o.Set("bar")
    66  	if o.Len() != 2 {
    67  		t.Errorf("%d != 2", o.Len())
    68  	}
    69  	o.Set("bar")
    70  	if o.Len() != 3 {
    71  		t.Errorf("%d != 3", o.Len())
    72  	}
    73  	if !o.Get("bar") {
    74  		t.Error("o.Get(\"bar\") == false")
    75  	}
    76  	if o.Get("baz") {
    77  		t.Error("o.Get(\"baz\") == true")
    78  	}
    79  	o.Delete("foo")
    80  	if o.String() != "[bar bar]" {
    81  		t.Errorf("%s != [bar bar]", o.String())
    82  	}
    83  	listOpts := o.GetAll()
    84  	if len(listOpts) != 2 || listOpts[0] != "bar" || listOpts[1] != "bar" {
    85  		t.Errorf("Expected [[bar bar]], got [%v]", listOpts)
    86  	}
    87  	mapListOpts := o.GetMap()
    88  	if len(mapListOpts) != 1 {
    89  		t.Errorf("Expected [map[bar:{}]], got [%v]", mapListOpts)
    90  	}
    91  }
    92  
    93  func TestListOptsWithValidator(t *testing.T) {
    94  	// Re-using logOptsvalidator (used by MapOpts)
    95  	o := NewListOpts(logOptsValidator)
    96  	o.Set("foo")
    97  	if o.String() != "" {
    98  		t.Errorf(`%s != ""`, o.String())
    99  	}
   100  	o.Set("foo=bar")
   101  	if o.String() != "" {
   102  		t.Errorf(`%s != ""`, o.String())
   103  	}
   104  	o.Set("max-file=2")
   105  	if o.Len() != 1 {
   106  		t.Errorf("%d != 1", o.Len())
   107  	}
   108  	if !o.Get("max-file=2") {
   109  		t.Error("o.Get(\"max-file=2\") == false")
   110  	}
   111  	if o.Get("baz") {
   112  		t.Error("o.Get(\"baz\") == true")
   113  	}
   114  	o.Delete("max-file=2")
   115  	if o.String() != "" {
   116  		t.Errorf(`%s != ""`, o.String())
   117  	}
   118  }
   119  
   120  func TestValidateDNSSearch(t *testing.T) {
   121  	valid := []string{
   122  		`.`,
   123  		`a`,
   124  		`a.`,
   125  		`1.foo`,
   126  		`17.foo`,
   127  		`foo.bar`,
   128  		`foo.bar.baz`,
   129  		`foo.bar.`,
   130  		`foo.bar.baz`,
   131  		`foo1.bar2`,
   132  		`foo1.bar2.baz`,
   133  		`1foo.2bar.`,
   134  		`1foo.2bar.baz`,
   135  		`foo-1.bar-2`,
   136  		`foo-1.bar-2.baz`,
   137  		`foo-1.bar-2.`,
   138  		`foo-1.bar-2.baz`,
   139  		`1-foo.2-bar`,
   140  		`1-foo.2-bar.baz`,
   141  		`1-foo.2-bar.`,
   142  		`1-foo.2-bar.baz`,
   143  	}
   144  
   145  	invalid := []string{
   146  		``,
   147  		` `,
   148  		`  `,
   149  		`17`,
   150  		`17.`,
   151  		`.17`,
   152  		`17-.`,
   153  		`17-.foo`,
   154  		`.foo`,
   155  		`foo-.bar`,
   156  		`-foo.bar`,
   157  		`foo.bar-`,
   158  		`foo.bar-.baz`,
   159  		`foo.-bar`,
   160  		`foo.-bar.baz`,
   161  		`foo.bar.baz.this.should.fail.on.long.name.because.it.is.longer.thanitshouldbethis.should.fail.on.long.name.because.it.is.longer.thanitshouldbethis.should.fail.on.long.name.because.it.is.longer.thanitshouldbethis.should.fail.on.long.name.because.it.is.longer.thanitshouldbe`,
   162  	}
   163  
   164  	for _, domain := range valid {
   165  		if ret, err := ValidateDNSSearch(domain); err != nil || ret == "" {
   166  			t.Fatalf("ValidateDNSSearch(`"+domain+"`) got %s %s", ret, err)
   167  		}
   168  	}
   169  
   170  	for _, domain := range invalid {
   171  		if ret, err := ValidateDNSSearch(domain); err == nil || ret != "" {
   172  			t.Fatalf("ValidateDNSSearch(`"+domain+"`) got %s %s", ret, err)
   173  		}
   174  	}
   175  }
   176  
   177  func TestValidateLabel(t *testing.T) {
   178  	testCases := []struct {
   179  		name           string
   180  		label          string
   181  		expectedResult string
   182  		expectedErr    string
   183  	}{
   184  		{
   185  			name:        "lable with bad attribute format",
   186  			label:       "label",
   187  			expectedErr: "bad attribute format: label",
   188  		},
   189  		{
   190  			name:           "label with general format",
   191  			label:          "key1=value1",
   192  			expectedResult: "key1=value1",
   193  		},
   194  		{
   195  			name:           "label with more than one =",
   196  			label:          "key1=value1=value2",
   197  			expectedResult: "key1=value1=value2",
   198  		},
   199  		{
   200  			name:           "label with one more",
   201  			label:          "key1=value1=value2=value3",
   202  			expectedResult: "key1=value1=value2=value3",
   203  		},
   204  		{
   205  			name:           "label with no reserved com.docker.*",
   206  			label:          "com.dockerpsychnotreserved.label=value",
   207  			expectedResult: "com.dockerpsychnotreserved.label=value",
   208  		},
   209  		{
   210  			name:           "label with no reserved io.docker.*",
   211  			label:          "io.dockerproject.not=reserved",
   212  			expectedResult: "io.dockerproject.not=reserved",
   213  		},
   214  		{
   215  			name:           "label with no reserved org.dockerproject.*",
   216  			label:          "org.docker.not=reserved",
   217  			expectedResult: "org.docker.not=reserved",
   218  		},
   219  		{
   220  			name:        "label with reserved com.docker.*",
   221  			label:       "com.docker.feature=enabled",
   222  			expectedErr: "label com.docker.feature=enabled is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
   223  		},
   224  		{
   225  			name:        "label with reserved upcase com.docker.* ",
   226  			label:       "COM.docker.feature=enabled",
   227  			expectedErr: "label COM.docker.feature=enabled is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
   228  		},
   229  		{
   230  			name:        "label with reserved io.docker.*",
   231  			label:       "io.docker.configuration=0",
   232  			expectedErr: "label io.docker.configuration=0 is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
   233  		},
   234  		{
   235  			name:        "label with reserved upcase io.docker.*",
   236  			label:       "io.DOCKER.CONFIGURATion=0",
   237  			expectedErr: "label io.DOCKER.CONFIGURATion=0 is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
   238  		},
   239  		{
   240  			name:        "label with reserved org.dockerproject.*",
   241  			label:       "org.dockerproject.setting=on",
   242  			expectedErr: "label org.dockerproject.setting=on is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
   243  		},
   244  		{
   245  			name:        "label with reserved upcase org.dockerproject.*",
   246  			label:       "Org.Dockerproject.Setting=on",
   247  			expectedErr: "label Org.Dockerproject.Setting=on is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
   248  		},
   249  	}
   250  
   251  	for _, testCase := range testCases {
   252  		testCase := testCase
   253  		t.Run(testCase.name, func(t *testing.T) {
   254  			result, err := ValidateLabel(testCase.label)
   255  
   256  			if testCase.expectedErr != "" {
   257  				assert.Error(t, err, testCase.expectedErr)
   258  			} else {
   259  				assert.NilError(t, err)
   260  			}
   261  			if testCase.expectedResult != "" {
   262  				assert.Check(t, is.Equal(result, testCase.expectedResult))
   263  			}
   264  		})
   265  	}
   266  }
   267  
   268  func logOptsValidator(val string) (string, error) {
   269  	allowedKeys := map[string]string{"max-size": "1", "max-file": "2"}
   270  	vals := strings.Split(val, "=")
   271  	if allowedKeys[vals[0]] != "" {
   272  		return val, nil
   273  	}
   274  	return "", fmt.Errorf("invalid key %s", vals[0])
   275  }
   276  
   277  func TestNamedListOpts(t *testing.T) {
   278  	var v []string
   279  	o := NewNamedListOptsRef("foo-name", &v, nil)
   280  
   281  	o.Set("foo")
   282  	if o.String() != "[foo]" {
   283  		t.Errorf("%s != [foo]", o.String())
   284  	}
   285  	if o.Name() != "foo-name" {
   286  		t.Errorf("%s != foo-name", o.Name())
   287  	}
   288  	if len(v) != 1 {
   289  		t.Errorf("expected foo to be in the values, got %v", v)
   290  	}
   291  }
   292  
   293  func TestNamedMapOpts(t *testing.T) {
   294  	tmpMap := make(map[string]string)
   295  	o := NewNamedMapOpts("max-name", tmpMap, nil)
   296  
   297  	o.Set("max-size=1")
   298  	if o.String() != "map[max-size:1]" {
   299  		t.Errorf("%s != [map[max-size:1]", o.String())
   300  	}
   301  	if o.Name() != "max-name" {
   302  		t.Errorf("%s != max-name", o.Name())
   303  	}
   304  	if _, exist := tmpMap["max-size"]; !exist {
   305  		t.Errorf("expected map-size to be in the values, got %v", tmpMap)
   306  	}
   307  }
   308  
   309  func TestParseLink(t *testing.T) {
   310  	name, alias, err := ParseLink("name:alias")
   311  	if err != nil {
   312  		t.Fatalf("Expected not to error out on a valid name:alias format but got: %v", err)
   313  	}
   314  	if name != "name" {
   315  		t.Fatalf("Link name should have been name, got %s instead", name)
   316  	}
   317  	if alias != "alias" {
   318  		t.Fatalf("Link alias should have been alias, got %s instead", alias)
   319  	}
   320  	// short format definition
   321  	name, alias, err = ParseLink("name")
   322  	if err != nil {
   323  		t.Fatalf("Expected not to error out on a valid name only format but got: %v", err)
   324  	}
   325  	if name != "name" {
   326  		t.Fatalf("Link name should have been name, got %s instead", name)
   327  	}
   328  	if alias != "name" {
   329  		t.Fatalf("Link alias should have been name, got %s instead", alias)
   330  	}
   331  	// empty string link definition is not allowed
   332  	if _, _, err := ParseLink(""); err == nil || !strings.Contains(err.Error(), "empty string specified for links") {
   333  		t.Fatalf("Expected error 'empty string specified for links' but got: %v", err)
   334  	}
   335  	// more than two colons are not allowed
   336  	if _, _, err := ParseLink("link:alias:wrong"); err == nil || !strings.Contains(err.Error(), "bad format for links: link:alias:wrong") {
   337  		t.Fatalf("Expected error 'bad format for links: link:alias:wrong' but got: %v", err)
   338  	}
   339  }