244 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package platforms
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"reflect"
 | |
| 	"runtime"
 | |
| 	"testing"
 | |
| 
 | |
| 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 | |
| )
 | |
| 
 | |
| func TestParseSelector(t *testing.T) {
 | |
| 	var (
 | |
| 		defaultOS   = runtime.GOOS
 | |
| 		defaultArch = runtime.GOARCH
 | |
| 	)
 | |
| 
 | |
| 	for _, testcase := range []struct {
 | |
| 		skip      bool
 | |
| 		input     string
 | |
| 		expected  specs.Platform
 | |
| 		formatted string
 | |
| 	}{
 | |
| 		// While wildcards are a valid use case for platform selection,
 | |
| 		// addressing these cases is outside the initial scope for this
 | |
| 		// package. When we do add platform wildcards, we should add in these
 | |
| 		// testcases to ensure that they are correctly represented.
 | |
| 		{
 | |
| 			skip:  true,
 | |
| 			input: "*",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           "*",
 | |
| 				Architecture: "*",
 | |
| 			},
 | |
| 			formatted: "*/*",
 | |
| 		},
 | |
| 		{
 | |
| 			skip:  true,
 | |
| 			input: "linux/*",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           "linux",
 | |
| 				Architecture: "*",
 | |
| 			},
 | |
| 			formatted: "linux/*",
 | |
| 		},
 | |
| 		{
 | |
| 			skip:  true,
 | |
| 			input: "*/arm64",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           "*",
 | |
| 				Architecture: "arm64",
 | |
| 			},
 | |
| 			formatted: "*/arm64",
 | |
| 		},
 | |
| 		{
 | |
| 			// NOTE(stevvooe): In this case, the consumer can assume this is v7
 | |
| 			// but we leave the variant blank. This will represent the vast
 | |
| 			// majority of arm images.
 | |
| 			input: "linux/arm",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           "linux",
 | |
| 				Architecture: "arm",
 | |
| 			},
 | |
| 			formatted: "linux/arm",
 | |
| 		},
 | |
| 		{
 | |
| 			input: "linux/arm/v6",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           "linux",
 | |
| 				Architecture: "arm",
 | |
| 				Variant:      "v6",
 | |
| 			},
 | |
| 			formatted: "linux/arm/v6",
 | |
| 		},
 | |
| 		{
 | |
| 			input: "linux/arm/v7",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           "linux",
 | |
| 				Architecture: "arm",
 | |
| 				Variant:      "v7",
 | |
| 			},
 | |
| 			formatted: "linux/arm/v7",
 | |
| 		},
 | |
| 		{
 | |
| 			input: "arm",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           defaultOS,
 | |
| 				Architecture: "arm",
 | |
| 			},
 | |
| 			formatted: joinNotEmpty(defaultOS, "arm"),
 | |
| 		},
 | |
| 		{
 | |
| 			input: "armel",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           defaultOS,
 | |
| 				Architecture: "arm",
 | |
| 				Variant:      "v6",
 | |
| 			},
 | |
| 			formatted: joinNotEmpty(defaultOS, "arm/v6"),
 | |
| 		},
 | |
| 		{
 | |
| 			input: "armhf",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           defaultOS,
 | |
| 				Architecture: "arm",
 | |
| 			},
 | |
| 			formatted: joinNotEmpty(defaultOS, "arm"),
 | |
| 		},
 | |
| 		{
 | |
| 			input: "Aarch64",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           defaultOS,
 | |
| 				Architecture: "arm64",
 | |
| 			},
 | |
| 			formatted: joinNotEmpty(defaultOS, "arm64"),
 | |
| 		},
 | |
| 		{
 | |
| 			input: "x86_64",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           defaultOS,
 | |
| 				Architecture: "amd64",
 | |
| 			},
 | |
| 			formatted: joinNotEmpty(defaultOS, "amd64"),
 | |
| 		},
 | |
| 		{
 | |
| 			input: "Linux/x86_64",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           "linux",
 | |
| 				Architecture: "amd64",
 | |
| 			},
 | |
| 			formatted: "linux/amd64",
 | |
| 		},
 | |
| 		{
 | |
| 			input: "i386",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           defaultOS,
 | |
| 				Architecture: "386",
 | |
| 			},
 | |
| 			formatted: joinNotEmpty(defaultOS, "386"),
 | |
| 		},
 | |
| 		{
 | |
| 			input: "linux",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           "linux",
 | |
| 				Architecture: defaultArch,
 | |
| 			},
 | |
| 			formatted: joinNotEmpty("linux", defaultArch),
 | |
| 		},
 | |
| 		{
 | |
| 			input: "s390x",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           defaultOS,
 | |
| 				Architecture: "s390x",
 | |
| 			},
 | |
| 			formatted: joinNotEmpty(defaultOS, "s390x"),
 | |
| 		},
 | |
| 		{
 | |
| 			input: "linux/s390x",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           "linux",
 | |
| 				Architecture: "s390x",
 | |
| 			},
 | |
| 			formatted: "linux/s390x",
 | |
| 		},
 | |
| 		{
 | |
| 			input: "macOS",
 | |
| 			expected: specs.Platform{
 | |
| 				OS:           "darwin",
 | |
| 				Architecture: defaultArch,
 | |
| 			},
 | |
| 			formatted: joinNotEmpty("darwin", defaultArch),
 | |
| 		},
 | |
| 	} {
 | |
| 		t.Run(testcase.input, func(t *testing.T) {
 | |
| 			if testcase.skip {
 | |
| 				t.Skip("this case is not yet supported")
 | |
| 			}
 | |
| 			m, err := Parse(testcase.input)
 | |
| 			if err != nil {
 | |
| 				t.Fatal(err)
 | |
| 			}
 | |
| 
 | |
| 			if !reflect.DeepEqual(m.Spec(), testcase.expected) {
 | |
| 				t.Fatalf("platform did not match expected: %#v != %#v", m.Spec(), testcase.expected)
 | |
| 			}
 | |
| 
 | |
| 			// ensure that match works on the input to the output.
 | |
| 			if ok := m.Match(testcase.expected); !ok {
 | |
| 				t.Fatalf("expected specifier %q matches %v", testcase.input, testcase.expected)
 | |
| 			}
 | |
| 
 | |
| 			if fmt.Sprint(m) != testcase.formatted {
 | |
| 				t.Fatalf("unexpected matcher string:  %q != %q", fmt.Sprint(m), testcase.formatted)
 | |
| 			}
 | |
| 
 | |
| 			formatted := Format(m.Spec())
 | |
| 			if formatted != testcase.formatted {
 | |
| 				t.Fatalf("unexpected format: %q != %q", formatted, testcase.formatted)
 | |
| 			}
 | |
| 
 | |
| 			// re-parse the formatted output and ensure we are stable
 | |
| 			reparsed, err := Parse(formatted)
 | |
| 			if err != nil {
 | |
| 				t.Fatalf("error parsing formatted output: %v", err)
 | |
| 			}
 | |
| 
 | |
| 			if Format(reparsed.Spec()) != formatted {
 | |
| 				t.Fatalf("normalized output did not survive the round trip: %v != %v", Format(reparsed.Spec()), formatted)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestParseSelectorInvalid(t *testing.T) {
 | |
| 	for _, testcase := range []struct {
 | |
| 		input string
 | |
| 	}{
 | |
| 		{
 | |
| 			input: "", // empty
 | |
| 		},
 | |
| 		{
 | |
| 			input: "/linux/arm", // leading slash
 | |
| 		},
 | |
| 		{
 | |
| 			input: "linux/arm/", // trailing slash
 | |
| 		},
 | |
| 		{
 | |
| 			input: "linux /arm", // spaces
 | |
| 		},
 | |
| 		{
 | |
| 			input: "linux/&arm", // invalid character
 | |
| 		},
 | |
| 		{
 | |
| 			input: "linux/arm/foo/bar", // too many components
 | |
| 		},
 | |
| 	} {
 | |
| 		t.Run(testcase.input, func(t *testing.T) {
 | |
| 			if _, err := Parse(testcase.input); err == nil {
 | |
| 				t.Fatalf("should have received an error")
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | 
