github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/pkg/cache/cache_opts_test.go (about) 1 package cache 2 3 import ( 4 "fmt" 5 "os" 6 "runtime" 7 "strings" 8 "testing" 9 10 "github.com/heroku/color" 11 "github.com/sclevine/spec" 12 "github.com/sclevine/spec/report" 13 14 h "github.com/buildpacks/pack/testhelpers" 15 ) 16 17 type CacheOptTestCase struct { 18 name string 19 input string 20 output string 21 shouldFail bool 22 } 23 24 func TestMetadata(t *testing.T) { 25 color.Disable(true) 26 defer color.Disable(false) 27 spec.Run(t, "Metadata", testCacheOpts, spec.Sequential(), spec.Report(report.Terminal{})) 28 } 29 30 func testCacheOpts(t *testing.T, when spec.G, it spec.S) { 31 when("image cache format options are passed", func() { 32 it("with complete options", func() { 33 testcases := []CacheOptTestCase{ 34 { 35 name: "Build cache as Image", 36 input: "type=build;format=image;name=io.test.io/myorg/my-cache:build", 37 output: "type=build;format=image;name=io.test.io/myorg/my-cache:build;type=launch;format=volume;", 38 }, 39 { 40 name: "Launch cache as Image", 41 input: "type=launch;format=image;name=io.test.io/myorg/my-cache:build", 42 output: "type=build;format=volume;type=launch;format=image;name=io.test.io/myorg/my-cache:build;", 43 }, 44 } 45 46 for _, testcase := range testcases { 47 var cacheFlags CacheOpts 48 t.Logf("Testing cache type: %s", testcase.name) 49 err := cacheFlags.Set(testcase.input) 50 h.AssertNil(t, err) 51 h.AssertEq(t, testcase.output, cacheFlags.String()) 52 } 53 }) 54 55 it("with missing options", func() { 56 successTestCases := []CacheOptTestCase{ 57 { 58 name: "Build cache as Image missing: type", 59 input: "format=image;name=io.test.io/myorg/my-cache:build", 60 output: "type=build;format=image;name=io.test.io/myorg/my-cache:build;type=launch;format=volume;", 61 }, 62 { 63 name: "Build cache as Image missing: format", 64 input: "type=build;name=io.test.io/myorg/my-cache:build", 65 output: "type=build;format=volume;name=io.test.io/myorg/my-cache:build;type=launch;format=volume;", 66 }, 67 { 68 name: "Build cache as Image missing: name", 69 input: "type=build;format=image", 70 output: "cache 'name' is required", 71 shouldFail: true, 72 }, 73 { 74 name: "Build cache as Image missing: type, format", 75 input: "name=io.test.io/myorg/my-cache:build", 76 output: "type=build;format=volume;name=io.test.io/myorg/my-cache:build;type=launch;format=volume;", 77 }, 78 { 79 name: "Build cache as Image missing: format, name", 80 input: "type=build", 81 output: "type=build;format=volume;type=launch;format=volume;", 82 }, 83 { 84 name: "Build cache as Image missing: type, name", 85 input: "format=image", 86 output: "cache 'name' is required", 87 shouldFail: true, 88 }, 89 { 90 name: "Launch cache as Image missing: name", 91 input: "type=launch;format=image", 92 output: "cache 'name' is required", 93 shouldFail: true, 94 }, 95 } 96 97 for _, testcase := range successTestCases { 98 var cacheFlags CacheOpts 99 t.Logf("Testing cache type: %s", testcase.name) 100 err := cacheFlags.Set(testcase.input) 101 102 if testcase.shouldFail { 103 h.AssertError(t, err, testcase.output) 104 } else { 105 h.AssertNil(t, err) 106 output := cacheFlags.String() 107 h.AssertEq(t, testcase.output, output) 108 } 109 } 110 }) 111 112 it("with invalid options", func() { 113 testcases := []CacheOptTestCase{ 114 { 115 name: "Invalid cache type", 116 input: "type=invalid_cache;format=image;name=io.test.io/myorg/my-cache:build", 117 output: "invalid cache type 'invalid_cache'", 118 shouldFail: true, 119 }, 120 { 121 name: "Invalid cache format", 122 input: "type=launch;format=invalid_format;name=io.test.io/myorg/my-cache:build", 123 output: "invalid cache format 'invalid_format'", 124 shouldFail: true, 125 }, 126 { 127 name: "Not a key=value pair", 128 input: "launch;format=image;name=io.test.io/myorg/my-cache:build", 129 output: "invalid field 'launch' must be a key=value pair", 130 shouldFail: true, 131 }, 132 { 133 name: "Extra semicolon", 134 input: "type=launch;format=image;name=io.test.io/myorg/my-cache:build;", 135 output: "invalid field '' must be a key=value pair", 136 shouldFail: true, 137 }, 138 } 139 140 for _, testcase := range testcases { 141 var cacheFlags CacheOpts 142 t.Logf("Testing cache type: %s", testcase.name) 143 err := cacheFlags.Set(testcase.input) 144 h.AssertError(t, err, testcase.output) 145 } 146 }) 147 }) 148 149 when("volume cache format options are passed", func() { 150 it("with complete options", func() { 151 testcases := []CacheOptTestCase{ 152 { 153 name: "Build cache as Volume", 154 input: "type=build;format=volume;name=test-build-volume-cache", 155 output: "type=build;format=volume;name=test-build-volume-cache;type=launch;format=volume;", 156 }, 157 { 158 name: "Launch cache as Volume", 159 input: "type=launch;format=volume;name=test-launch-volume-cache", 160 output: "type=build;format=volume;type=launch;format=volume;name=test-launch-volume-cache;", 161 }, 162 } 163 164 for _, testcase := range testcases { 165 var cacheFlags CacheOpts 166 t.Logf("Testing cache type: %s", testcase.name) 167 err := cacheFlags.Set(testcase.input) 168 h.AssertNil(t, err) 169 h.AssertEq(t, testcase.output, cacheFlags.String()) 170 } 171 }) 172 173 it("with missing options", func() { 174 successTestCases := []CacheOptTestCase{ 175 { 176 name: "Launch cache as Volume missing: format", 177 input: "type=launch;name=test-launch-volume", 178 output: "type=build;format=volume;type=launch;format=volume;name=test-launch-volume;", 179 }, 180 { 181 name: "Launch cache as Volume missing: name", 182 input: "type=launch;format=volume", 183 output: "type=build;format=volume;type=launch;format=volume;", 184 }, 185 { 186 name: "Launch cache as Volume missing: format, name", 187 input: "type=launch", 188 output: "type=build;format=volume;type=launch;format=volume;", 189 }, 190 { 191 name: "Launch cache as Volume missing: type, name", 192 input: "format=volume", 193 output: "type=build;format=volume;type=launch;format=volume;", 194 }, 195 } 196 197 for _, testcase := range successTestCases { 198 var cacheFlags CacheOpts 199 t.Logf("Testing cache type: %s", testcase.name) 200 err := cacheFlags.Set(testcase.input) 201 202 if testcase.shouldFail { 203 h.AssertError(t, err, testcase.output) 204 } else { 205 h.AssertNil(t, err) 206 output := cacheFlags.String() 207 h.AssertEq(t, testcase.output, output) 208 } 209 } 210 }) 211 }) 212 213 when("bind cache format options are passed", func() { 214 it("with complete options", func() { 215 var testcases []CacheOptTestCase 216 homeDir, err := os.UserHomeDir() 217 h.AssertNil(t, err) 218 cwd, err := os.Getwd() 219 h.AssertNil(t, err) 220 221 if runtime.GOOS != "windows" { 222 testcases = []CacheOptTestCase{ 223 { 224 name: "Build cache as bind", 225 input: fmt.Sprintf("type=build;format=bind;source=%s/test-bind-build-cache", homeDir), 226 output: fmt.Sprintf("type=build;format=bind;source=%s/test-bind-build-cache/build-cache;type=launch;format=volume;", homeDir), 227 }, 228 { 229 name: "Build cache as bind with relative path", 230 input: "type=build;format=bind;source=./test-bind-build-cache-relative", 231 output: fmt.Sprintf("type=build;format=bind;source=%s/test-bind-build-cache-relative/build-cache;type=launch;format=volume;", cwd), 232 }, 233 { 234 name: "Launch cache as bind", 235 input: fmt.Sprintf("type=launch;format=bind;source=%s/test-bind-volume-cache", homeDir), 236 output: fmt.Sprintf("type=build;format=volume;type=launch;format=bind;source=%s/test-bind-volume-cache/launch-cache;", homeDir), 237 }, 238 } 239 } else { 240 testcases = []CacheOptTestCase{ 241 { 242 name: "Build cache as bind", 243 input: fmt.Sprintf("type=build;format=bind;source=%s\\test-bind-build-cache", homeDir), 244 output: fmt.Sprintf("type=build;format=bind;source=%s\\test-bind-build-cache\\build-cache;type=launch;format=volume;", homeDir), 245 }, 246 { 247 name: "Build cache as bind with relative path", 248 input: "type=build;format=bind;source=.\\test-bind-build-cache-relative", 249 output: fmt.Sprintf("type=build;format=bind;source=%s\\test-bind-build-cache-relative\\build-cache;type=launch;format=volume;", cwd), 250 }, 251 { 252 name: "Launch cache as bind", 253 input: fmt.Sprintf("type=launch;format=bind;source=%s\\test-bind-volume-cache", homeDir), 254 output: fmt.Sprintf("type=build;format=volume;type=launch;format=bind;source=%s\\test-bind-volume-cache\\launch-cache;", homeDir), 255 }, 256 } 257 } 258 259 for _, testcase := range testcases { 260 var cacheFlags CacheOpts 261 t.Logf("Testing cache type: %s", testcase.name) 262 err := cacheFlags.Set(testcase.input) 263 h.AssertNil(t, err) 264 h.AssertEq(t, strings.ToLower(testcase.output), strings.ToLower(cacheFlags.String())) 265 } 266 }) 267 268 it("with missing options", func() { 269 successTestCases := []CacheOptTestCase{ 270 { 271 name: "Launch cache as bind missing: source", 272 input: "type=launch;format=bind", 273 output: "cache 'source' is required", 274 shouldFail: true, 275 }, 276 { 277 name: "Launch cache as Volume missing: type, source", 278 input: "format=bind", 279 output: "cache 'source' is required", 280 shouldFail: true, 281 }, 282 } 283 284 for _, testcase := range successTestCases { 285 var cacheFlags CacheOpts 286 t.Logf("Testing cache type: %s", testcase.name) 287 err := cacheFlags.Set(testcase.input) 288 289 if testcase.shouldFail { 290 h.AssertError(t, err, testcase.output) 291 } else { 292 h.AssertNil(t, err) 293 output := cacheFlags.String() 294 h.AssertEq(t, testcase.output, output) 295 } 296 } 297 }) 298 }) 299 }