github.com/containerd/Containerd@v1.4.13/reference/reference_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 reference 18 19 import ( 20 "testing" 21 22 digest "github.com/opencontainers/go-digest" 23 ) 24 25 func TestReferenceParser(t *testing.T) { 26 for _, testcase := range []struct { 27 Skip bool 28 Name string 29 Input string 30 Normalized string 31 Digest digest.Digest 32 Hostname string 33 Expected Spec 34 Err error 35 }{ 36 { 37 Name: "Basic", 38 Input: "docker.io/library/redis:foo?fooo=asdf", 39 Normalized: "docker.io/library/redis:foo", 40 Hostname: "docker.io", 41 Expected: Spec{ 42 Locator: "docker.io/library/redis", 43 Object: "foo", 44 }, 45 }, 46 { 47 Name: "BasicWithDigest", 48 Input: "docker.io/library/redis:foo@sha256:abcdef?fooo=asdf", 49 Normalized: "docker.io/library/redis:foo@sha256:abcdef", 50 Hostname: "docker.io", 51 Digest: "sha256:abcdef", 52 Expected: Spec{ 53 Locator: "docker.io/library/redis", 54 Object: "foo@sha256:abcdef", 55 }, 56 }, 57 58 { 59 Name: "DigestOnly", 60 Input: "docker.io/library/redis@sha256:abcdef?fooo=asdf", 61 Expected: Spec{ 62 Locator: "docker.io/library/redis", 63 Object: "@sha256:abcdef", 64 }, 65 Hostname: "docker.io", 66 Normalized: "docker.io/library/redis@sha256:abcdef", 67 Digest: "sha256:abcdef", 68 }, 69 { 70 Name: "AtShortDigest", 71 Input: "docker.io/library/redis:obj@abcdef?fooo=asdf", 72 Normalized: "docker.io/library/redis:obj@abcdef", 73 Hostname: "docker.io", 74 Digest: "abcdef", 75 Expected: Spec{ 76 Locator: "docker.io/library/redis", 77 Object: "obj@abcdef", 78 }, 79 }, 80 { 81 Name: "HostWithPort", 82 Input: "localhost:5000/library/redis:obj@abcdef?fooo=asdf", 83 Normalized: "localhost:5000/library/redis:obj@abcdef", 84 Hostname: "localhost:5000", 85 Digest: "abcdef", 86 Expected: Spec{ 87 Locator: "localhost:5000/library/redis", 88 Object: "obj@abcdef", 89 }, 90 }, 91 { 92 Name: "HostnameRequired", 93 Input: "/docker.io/library/redis:obj@abcdef?fooo=asdf", 94 Err: ErrHostnameRequired, 95 }, 96 { 97 Name: "ErrObjectRequired", 98 Input: "docker.io/library/redis?fooo=asdf", 99 Hostname: "docker.io", 100 Normalized: "docker.io/library/redis", 101 Expected: Spec{ 102 Locator: "docker.io/library/redis", 103 Object: "", 104 }, 105 }, 106 { 107 Name: "Subdomain", 108 Input: "sub-dom1.foo.com/bar/baz/quux:latest", 109 Hostname: "sub-dom1.foo.com", 110 Expected: Spec{ 111 Locator: "sub-dom1.foo.com/bar/baz/quux", 112 Object: "latest", 113 }, 114 }, 115 { 116 Name: "SubdomainWithLongTag", 117 Input: "sub-dom1.foo.com/bar/baz/quux:some-long-tag", 118 Hostname: "sub-dom1.foo.com", 119 Expected: Spec{ 120 Locator: "sub-dom1.foo.com/bar/baz/quux", 121 Object: "some-long-tag", 122 }, 123 }, 124 { 125 Name: "AGCRAppears", 126 Input: "b.gcr.io/test.example.com/my-app:test.example.com", 127 Hostname: "b.gcr.io", 128 Expected: Spec{ 129 Locator: "b.gcr.io/test.example.com/my-app", 130 Object: "test.example.com", 131 }, 132 }, 133 { 134 Name: "Punycode", 135 Input: "xn--n3h.com/myimage:xn--n3h.com", // ☃.com in punycode 136 Hostname: "xn--n3h.com", 137 Expected: Spec{ 138 Locator: "xn--n3h.com/myimage", 139 Object: "xn--n3h.com", 140 }, 141 }, 142 { 143 144 Name: "PunycodeWithDigest", 145 Input: "xn--7o8h.com/myimage:xn--7o8h.com@sha512:fffffff", 146 Hostname: "xn--7o8h.com", 147 Digest: "sha512:fffffff", 148 Expected: Spec{ 149 Locator: "xn--7o8h.com/myimage", 150 Object: "xn--7o8h.com@sha512:fffffff", 151 }, 152 }, 153 { 154 Skip: true, // TODO(stevvooe): Implement this case. 155 Name: "SchemeDefined", 156 Input: "http://xn--7o8h.com/myimage:xn--7o8h.com@sha512:fffffff", 157 Hostname: "xn--7o8h.com", 158 Digest: "sha512:fffffff", 159 Err: ErrInvalid, 160 }, 161 } { 162 t.Run(testcase.Name, func(t *testing.T) { 163 if testcase.Skip { 164 t.Skip("testcase disabled") 165 return 166 } 167 168 ref, err := Parse(testcase.Input) 169 if err != testcase.Err { 170 if testcase.Err != nil { 171 t.Fatalf("expected error %v for %q, got %v, %#v", testcase.Err, testcase.Input, err, ref) 172 } else { 173 t.Fatalf("unexpected error %v", err) 174 } 175 } else if testcase.Err != nil { 176 return 177 } 178 179 if ref != testcase.Expected { 180 t.Fatalf("%#v != %#v", ref, testcase.Expected) 181 } 182 183 if testcase.Normalized == "" { 184 testcase.Normalized = testcase.Input 185 } 186 187 if ref.String() != testcase.Normalized { 188 t.Fatalf("normalization failed: %v != %v", ref.String(), testcase.Normalized) 189 } 190 191 if ref.Digest() != testcase.Digest { 192 t.Fatalf("digest extraction failed: %v != %v", ref.Digest(), testcase.Digest) 193 } 194 195 if ref.Hostname() != testcase.Hostname { 196 t.Fatalf("unexpected hostname: %v != %v", ref.Hostname(), testcase.Hostname) 197 } 198 }) 199 } 200 }