github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/cli/opts/port_test.go (about)

     1  package opts
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/docker/docker/api/types/swarm"
     7  	"gotest.tools/v3/assert"
     8  	is "gotest.tools/v3/assert/cmp"
     9  )
    10  
    11  func TestPortOptValidSimpleSyntax(t *testing.T) {
    12  	testCases := []struct {
    13  		value    string
    14  		expected []swarm.PortConfig
    15  	}{
    16  		{
    17  			value: "80",
    18  			expected: []swarm.PortConfig{
    19  				{
    20  					Protocol:    "tcp",
    21  					TargetPort:  80,
    22  					PublishMode: swarm.PortConfigPublishModeIngress,
    23  				},
    24  			},
    25  		},
    26  		{
    27  			value: "80:8080",
    28  			expected: []swarm.PortConfig{
    29  				{
    30  					Protocol:      "tcp",
    31  					TargetPort:    8080,
    32  					PublishedPort: 80,
    33  					PublishMode:   swarm.PortConfigPublishModeIngress,
    34  				},
    35  			},
    36  		},
    37  		{
    38  			value: "8080:80/tcp",
    39  			expected: []swarm.PortConfig{
    40  				{
    41  					Protocol:      "tcp",
    42  					TargetPort:    80,
    43  					PublishedPort: 8080,
    44  					PublishMode:   swarm.PortConfigPublishModeIngress,
    45  				},
    46  			},
    47  		},
    48  		{
    49  			value: "80:8080/udp",
    50  			expected: []swarm.PortConfig{
    51  				{
    52  					Protocol:      "udp",
    53  					TargetPort:    8080,
    54  					PublishedPort: 80,
    55  					PublishMode:   swarm.PortConfigPublishModeIngress,
    56  				},
    57  			},
    58  		},
    59  		{
    60  			value: "80-81:8080-8081/tcp",
    61  			expected: []swarm.PortConfig{
    62  				{
    63  					Protocol:      "tcp",
    64  					TargetPort:    8080,
    65  					PublishedPort: 80,
    66  					PublishMode:   swarm.PortConfigPublishModeIngress,
    67  				},
    68  				{
    69  					Protocol:      "tcp",
    70  					TargetPort:    8081,
    71  					PublishedPort: 81,
    72  					PublishMode:   swarm.PortConfigPublishModeIngress,
    73  				},
    74  			},
    75  		},
    76  		{
    77  			value: "80-82:8080-8082/udp",
    78  			expected: []swarm.PortConfig{
    79  				{
    80  					Protocol:      "udp",
    81  					TargetPort:    8080,
    82  					PublishedPort: 80,
    83  					PublishMode:   swarm.PortConfigPublishModeIngress,
    84  				},
    85  				{
    86  					Protocol:      "udp",
    87  					TargetPort:    8081,
    88  					PublishedPort: 81,
    89  					PublishMode:   swarm.PortConfigPublishModeIngress,
    90  				},
    91  				{
    92  					Protocol:      "udp",
    93  					TargetPort:    8082,
    94  					PublishedPort: 82,
    95  					PublishMode:   swarm.PortConfigPublishModeIngress,
    96  				},
    97  			},
    98  		},
    99  		{
   100  			value: "80-82:8080/udp",
   101  			expected: []swarm.PortConfig{
   102  				{
   103  					Protocol:      "udp",
   104  					TargetPort:    8080,
   105  					PublishedPort: 80,
   106  					PublishMode:   swarm.PortConfigPublishModeIngress,
   107  				},
   108  				{
   109  					Protocol:      "udp",
   110  					TargetPort:    8080,
   111  					PublishedPort: 81,
   112  					PublishMode:   swarm.PortConfigPublishModeIngress,
   113  				},
   114  				{
   115  					Protocol:      "udp",
   116  					TargetPort:    8080,
   117  					PublishedPort: 82,
   118  					PublishMode:   swarm.PortConfigPublishModeIngress,
   119  				},
   120  			},
   121  		},
   122  		{
   123  			value: "80-80:8080/tcp",
   124  			expected: []swarm.PortConfig{
   125  				{
   126  					Protocol:      "tcp",
   127  					TargetPort:    8080,
   128  					PublishedPort: 80,
   129  					PublishMode:   swarm.PortConfigPublishModeIngress,
   130  				},
   131  			},
   132  		},
   133  	}
   134  	for _, tc := range testCases {
   135  		var port PortOpt
   136  		assert.NilError(t, port.Set(tc.value))
   137  		assert.Check(t, is.Len(port.Value(), len(tc.expected)))
   138  		for _, expectedPortConfig := range tc.expected {
   139  			assertContains(t, port.Value(), expectedPortConfig)
   140  		}
   141  	}
   142  }
   143  
   144  func TestPortOptValidComplexSyntax(t *testing.T) {
   145  	testCases := []struct {
   146  		value    string
   147  		expected []swarm.PortConfig
   148  	}{
   149  		{
   150  			value: "target=80",
   151  			expected: []swarm.PortConfig{
   152  				{
   153  					TargetPort:  80,
   154  					Protocol:    "tcp",
   155  					PublishMode: swarm.PortConfigPublishModeIngress,
   156  				},
   157  			},
   158  		},
   159  		{
   160  			value: "target=80,protocol=tcp",
   161  			expected: []swarm.PortConfig{
   162  				{
   163  					Protocol:    "tcp",
   164  					TargetPort:  80,
   165  					PublishMode: swarm.PortConfigPublishModeIngress,
   166  				},
   167  			},
   168  		},
   169  		{
   170  			value: "target=80,published=8080,protocol=tcp",
   171  			expected: []swarm.PortConfig{
   172  				{
   173  					Protocol:      "tcp",
   174  					TargetPort:    80,
   175  					PublishedPort: 8080,
   176  					PublishMode:   swarm.PortConfigPublishModeIngress,
   177  				},
   178  			},
   179  		},
   180  		{
   181  			value: "published=80,target=8080,protocol=tcp",
   182  			expected: []swarm.PortConfig{
   183  				{
   184  					Protocol:      "tcp",
   185  					TargetPort:    8080,
   186  					PublishedPort: 80,
   187  					PublishMode:   swarm.PortConfigPublishModeIngress,
   188  				},
   189  			},
   190  		},
   191  		{
   192  			value: "target=80,published=8080,protocol=tcp,mode=host",
   193  			expected: []swarm.PortConfig{
   194  				{
   195  					Protocol:      "tcp",
   196  					TargetPort:    80,
   197  					PublishedPort: 8080,
   198  					PublishMode:   "host",
   199  				},
   200  			},
   201  		},
   202  		{
   203  			value: "target=80,published=8080,mode=host",
   204  			expected: []swarm.PortConfig{
   205  				{
   206  					TargetPort:    80,
   207  					PublishedPort: 8080,
   208  					PublishMode:   "host",
   209  					Protocol:      "tcp",
   210  				},
   211  			},
   212  		},
   213  		{
   214  			value: "target=80,published=8080,mode=ingress",
   215  			expected: []swarm.PortConfig{
   216  				{
   217  					TargetPort:    80,
   218  					PublishedPort: 8080,
   219  					PublishMode:   "ingress",
   220  					Protocol:      "tcp",
   221  				},
   222  			},
   223  		},
   224  	}
   225  	for _, tc := range testCases {
   226  		var port PortOpt
   227  		assert.NilError(t, port.Set(tc.value))
   228  		assert.Check(t, is.Len(port.Value(), len(tc.expected)))
   229  		for _, expectedPortConfig := range tc.expected {
   230  			assertContains(t, port.Value(), expectedPortConfig)
   231  		}
   232  	}
   233  }
   234  
   235  func TestPortOptInvalidComplexSyntax(t *testing.T) {
   236  	testCases := []struct {
   237  		value         string
   238  		expectedError string
   239  	}{
   240  		{
   241  			value:         "invalid,target=80",
   242  			expectedError: "invalid field",
   243  		},
   244  		{
   245  			value:         "invalid=field",
   246  			expectedError: "invalid field",
   247  		},
   248  		{
   249  			value:         "protocol=invalid",
   250  			expectedError: "invalid protocol value",
   251  		},
   252  		{
   253  			value:         "target=invalid",
   254  			expectedError: "invalid syntax",
   255  		},
   256  		{
   257  			value:         "published=invalid",
   258  			expectedError: "invalid syntax",
   259  		},
   260  		{
   261  			value:         "mode=invalid",
   262  			expectedError: "invalid publish mode value",
   263  		},
   264  		{
   265  			value:         "published=8080,protocol=tcp,mode=ingress",
   266  			expectedError: "missing mandatory field",
   267  		},
   268  		{
   269  			value:         `target=80,protocol="tcp,mode=ingress"`,
   270  			expectedError: "non-quoted-field",
   271  		},
   272  		{
   273  			value:         `target=80,"protocol=tcp,mode=ingress"`,
   274  			expectedError: "invalid protocol value",
   275  		},
   276  	}
   277  	for _, tc := range testCases {
   278  		var port PortOpt
   279  		assert.ErrorContains(t, port.Set(tc.value), tc.expectedError)
   280  	}
   281  }
   282  
   283  func TestPortOptInvalidSimpleSyntax(t *testing.T) {
   284  	testCases := []struct {
   285  		value         string
   286  		expectedError string
   287  	}{
   288  		{
   289  			value:         "9999999",
   290  			expectedError: "Invalid containerPort: 9999999",
   291  		},
   292  		{
   293  			value:         "80/xyz",
   294  			expectedError: "Invalid proto: xyz",
   295  		},
   296  		{
   297  			value:         "tcp",
   298  			expectedError: "Invalid containerPort: tcp",
   299  		},
   300  		{
   301  			value:         "udp",
   302  			expectedError: "Invalid containerPort: udp",
   303  		},
   304  		{
   305  			value:         "",
   306  			expectedError: "No port specified: <empty>",
   307  		},
   308  		{
   309  			value:         "1.1.1.1:80:80",
   310  			expectedError: "hostip is not supported",
   311  		},
   312  	}
   313  	for _, tc := range testCases {
   314  		var port PortOpt
   315  		assert.Error(t, port.Set(tc.value), tc.expectedError)
   316  	}
   317  }
   318  
   319  func assertContains(t *testing.T, portConfigs []swarm.PortConfig, expected swarm.PortConfig) {
   320  	var contains = false
   321  	for _, portConfig := range portConfigs {
   322  		if portConfig == expected {
   323  			contains = true
   324  			break
   325  		}
   326  	}
   327  	if !contains {
   328  		t.Errorf("expected %v to contain %v, did not", portConfigs, expected)
   329  	}
   330  }