github.com/lalkh/containerd@v1.4.3/platforms/platforms_test.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package platforms
    18  
    19  import (
    20  	"reflect"
    21  	"runtime"
    22  	"testing"
    23  
    24  	specs "github.com/opencontainers/image-spec/specs-go/v1"
    25  )
    26  
    27  func TestParseSelector(t *testing.T) {
    28  	var (
    29  		defaultOS      = runtime.GOOS
    30  		defaultArch    = runtime.GOARCH
    31  		defaultVariant = ""
    32  	)
    33  
    34  	if defaultArch == "arm" && cpuVariant != "v7" {
    35  		defaultVariant = cpuVariant
    36  	}
    37  
    38  	for _, testcase := range []struct {
    39  		skip      bool
    40  		input     string
    41  		expected  specs.Platform
    42  		matches   []specs.Platform
    43  		formatted string
    44  	}{
    45  		// While wildcards are a valid use case for platform selection,
    46  		// addressing these cases is outside the initial scope for this
    47  		// package. When we do add platform wildcards, we should add in these
    48  		// testcases to ensure that they are correctly represented.
    49  		{
    50  			skip:  true,
    51  			input: "*",
    52  			expected: specs.Platform{
    53  				OS:           "*",
    54  				Architecture: "*",
    55  			},
    56  			formatted: "*/*",
    57  		},
    58  		{
    59  			skip:  true,
    60  			input: "linux/*",
    61  			expected: specs.Platform{
    62  				OS:           "linux",
    63  				Architecture: "*",
    64  			},
    65  			formatted: "linux/*",
    66  		},
    67  		{
    68  			skip:  true,
    69  			input: "*/arm64",
    70  			expected: specs.Platform{
    71  				OS:           "*",
    72  				Architecture: "arm64",
    73  			},
    74  			matches: []specs.Platform{
    75  				{
    76  					OS:           "*",
    77  					Architecture: "aarch64",
    78  				},
    79  				{
    80  					OS:           "*",
    81  					Architecture: "aarch64",
    82  					Variant:      "v8",
    83  				},
    84  				{
    85  					OS:           "*",
    86  					Architecture: "arm64",
    87  					Variant:      "v8",
    88  				},
    89  			},
    90  			formatted: "*/arm64",
    91  		},
    92  		{
    93  			input: "linux/arm64",
    94  			expected: specs.Platform{
    95  				OS:           "linux",
    96  				Architecture: "arm64",
    97  			},
    98  			matches: []specs.Platform{
    99  				{
   100  					OS:           "linux",
   101  					Architecture: "aarch64",
   102  				},
   103  				{
   104  					OS:           "linux",
   105  					Architecture: "aarch64",
   106  					Variant:      "v8",
   107  				},
   108  				{
   109  					OS:           "linux",
   110  					Architecture: "arm64",
   111  					Variant:      "v8",
   112  				},
   113  			},
   114  			formatted: "linux/arm64",
   115  		},
   116  		{
   117  			input: "linux/arm64/v8",
   118  			expected: specs.Platform{
   119  				OS:           "linux",
   120  				Architecture: "arm64",
   121  				Variant:      "v8",
   122  			},
   123  			matches: []specs.Platform{
   124  				{
   125  					OS:           "linux",
   126  					Architecture: "aarch64",
   127  				},
   128  				{
   129  					OS:           "linux",
   130  					Architecture: "aarch64",
   131  					Variant:      "v8",
   132  				},
   133  				{
   134  					OS:           "linux",
   135  					Architecture: "arm64",
   136  				},
   137  			},
   138  			formatted: "linux/arm64/v8",
   139  		},
   140  		{
   141  			// NOTE(stevvooe): In this case, the consumer can assume this is v7
   142  			// but we leave the variant blank. This will represent the vast
   143  			// majority of arm images.
   144  			input: "linux/arm",
   145  			expected: specs.Platform{
   146  				OS:           "linux",
   147  				Architecture: "arm",
   148  			},
   149  			matches: []specs.Platform{
   150  				{
   151  					OS:           "linux",
   152  					Architecture: "arm",
   153  					Variant:      "v7",
   154  				},
   155  				{
   156  					OS:           "linux",
   157  					Architecture: "armhf",
   158  				},
   159  				{
   160  					OS:           "linux",
   161  					Architecture: "arm",
   162  					Variant:      "7",
   163  				},
   164  			},
   165  			formatted: "linux/arm",
   166  		},
   167  		{
   168  			input: "linux/arm/v6",
   169  			expected: specs.Platform{
   170  				OS:           "linux",
   171  				Architecture: "arm",
   172  				Variant:      "v6",
   173  			},
   174  			matches: []specs.Platform{
   175  				{
   176  					OS:           "linux",
   177  					Architecture: "armel",
   178  				},
   179  			},
   180  			formatted: "linux/arm/v6",
   181  		},
   182  		{
   183  			input: "linux/arm/v7",
   184  			expected: specs.Platform{
   185  				OS:           "linux",
   186  				Architecture: "arm",
   187  				Variant:      "v7",
   188  			},
   189  			matches: []specs.Platform{
   190  				{
   191  					OS:           "linux",
   192  					Architecture: "arm",
   193  				},
   194  				{
   195  					OS:           "linux",
   196  					Architecture: "armhf",
   197  				},
   198  			},
   199  			formatted: "linux/arm/v7",
   200  		},
   201  		{
   202  			input: "arm",
   203  			expected: specs.Platform{
   204  				OS:           defaultOS,
   205  				Architecture: "arm",
   206  			},
   207  			formatted: joinNotEmpty(defaultOS, "arm"),
   208  		},
   209  		{
   210  			input: "armel",
   211  			expected: specs.Platform{
   212  				OS:           defaultOS,
   213  				Architecture: "arm",
   214  				Variant:      "v6",
   215  			},
   216  			formatted: joinNotEmpty(defaultOS, "arm/v6"),
   217  		},
   218  		{
   219  			input: "armhf",
   220  			expected: specs.Platform{
   221  				OS:           defaultOS,
   222  				Architecture: "arm",
   223  			},
   224  			formatted: joinNotEmpty(defaultOS, "arm"),
   225  		},
   226  		{
   227  			input: "Aarch64",
   228  			expected: specs.Platform{
   229  				OS:           defaultOS,
   230  				Architecture: "arm64",
   231  			},
   232  			formatted: joinNotEmpty(defaultOS, "arm64"),
   233  		},
   234  		{
   235  			input: "x86_64",
   236  			expected: specs.Platform{
   237  				OS:           defaultOS,
   238  				Architecture: "amd64",
   239  			},
   240  			formatted: joinNotEmpty(defaultOS, "amd64"),
   241  		},
   242  		{
   243  			input: "Linux/x86_64",
   244  			expected: specs.Platform{
   245  				OS:           "linux",
   246  				Architecture: "amd64",
   247  			},
   248  			formatted: "linux/amd64",
   249  		},
   250  		{
   251  			input: "i386",
   252  			expected: specs.Platform{
   253  				OS:           defaultOS,
   254  				Architecture: "386",
   255  			},
   256  			formatted: joinNotEmpty(defaultOS, "386"),
   257  		},
   258  		{
   259  			input: "linux",
   260  			expected: specs.Platform{
   261  				OS:           "linux",
   262  				Architecture: defaultArch,
   263  				Variant:      defaultVariant,
   264  			},
   265  			formatted: joinNotEmpty("linux", defaultArch, defaultVariant),
   266  		},
   267  		{
   268  			input: "s390x",
   269  			expected: specs.Platform{
   270  				OS:           defaultOS,
   271  				Architecture: "s390x",
   272  			},
   273  			formatted: joinNotEmpty(defaultOS, "s390x"),
   274  		},
   275  		{
   276  			input: "linux/s390x",
   277  			expected: specs.Platform{
   278  				OS:           "linux",
   279  				Architecture: "s390x",
   280  			},
   281  			formatted: "linux/s390x",
   282  		},
   283  		{
   284  			input: "macOS",
   285  			expected: specs.Platform{
   286  				OS:           "darwin",
   287  				Architecture: defaultArch,
   288  				Variant:      defaultVariant,
   289  			},
   290  			formatted: joinNotEmpty("darwin", defaultArch, defaultVariant),
   291  		},
   292  	} {
   293  		t.Run(testcase.input, func(t *testing.T) {
   294  			if testcase.skip {
   295  				t.Skip("this case is not yet supported")
   296  			}
   297  			p, err := Parse(testcase.input)
   298  			if err != nil {
   299  				t.Fatal(err)
   300  			}
   301  
   302  			if !reflect.DeepEqual(p, testcase.expected) {
   303  				t.Fatalf("platform did not match expected: %#v != %#v", p, testcase.expected)
   304  			}
   305  
   306  			m := NewMatcher(p)
   307  
   308  			// ensure that match works on the input to the output.
   309  			if ok := m.Match(testcase.expected); !ok {
   310  				t.Fatalf("expected specifier %q matches %#v", testcase.input, testcase.expected)
   311  			}
   312  			for _, mc := range testcase.matches {
   313  				if ok := m.Match(mc); !ok {
   314  					t.Fatalf("expected specifier %q matches %#v", testcase.input, mc)
   315  				}
   316  			}
   317  
   318  			formatted := Format(p)
   319  			if formatted != testcase.formatted {
   320  				t.Fatalf("unexpected format: %q != %q", formatted, testcase.formatted)
   321  			}
   322  
   323  			// re-parse the formatted output and ensure we are stable
   324  			reparsed, err := Parse(formatted)
   325  			if err != nil {
   326  				t.Fatalf("error parsing formatted output: %v", err)
   327  			}
   328  
   329  			if Format(reparsed) != formatted {
   330  				t.Fatalf("normalized output did not survive the round trip: %v != %v", Format(reparsed), formatted)
   331  			}
   332  		})
   333  	}
   334  }
   335  
   336  func TestParseSelectorInvalid(t *testing.T) {
   337  	for _, testcase := range []struct {
   338  		input string
   339  	}{
   340  		{
   341  			input: "", // empty
   342  		},
   343  		{
   344  			input: "/linux/arm", // leading slash
   345  		},
   346  		{
   347  			input: "linux/arm/", // trailing slash
   348  		},
   349  		{
   350  			input: "linux /arm", // spaces
   351  		},
   352  		{
   353  			input: "linux/&arm", // invalid character
   354  		},
   355  		{
   356  			input: "linux/arm/foo/bar", // too many components
   357  		},
   358  	} {
   359  		t.Run(testcase.input, func(t *testing.T) {
   360  			if _, err := Parse(testcase.input); err == nil {
   361  				t.Fatalf("should have received an error")
   362  			}
   363  		})
   364  	}
   365  }