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  }