Files
buildkit/control/control_test.go
Tonis Tiigi 9d6d33dd72 control: handle duplicate inline cache exporter
Inline cache exporter can be set with multiple ways, doesn't
have any attributes and can always only run one time.

Instead of allowing multiple inline exporters where one
gets ignored later when there is an attribute difference, or
erroring when attributes are unset, just ignore the extra ones.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2025-10-06 08:36:32 -07:00

204 lines
3.9 KiB
Go

package control
import (
"testing"
controlapi "github.com/moby/buildkit/api/services/control"
"github.com/stretchr/testify/require"
)
func TestDuplicateCacheOptions(t *testing.T) {
var testCases = []struct {
name string
opts []*controlapi.CacheOptionsEntry
expected []*controlapi.CacheOptionsEntry
rest []*controlapi.CacheOptionsEntry
}{
{
name: "avoids unique opts",
opts: []*controlapi.CacheOptionsEntry{
{
Type: "registry",
Attrs: map[string]string{
"ref": "example.com/ref:v1.0.0",
},
},
{
Type: "local",
Attrs: map[string]string{
"dest": "/path/for/export",
},
},
},
expected: nil,
},
{
name: "finds duplicate opts",
opts: []*controlapi.CacheOptionsEntry{
{
Type: "registry",
Attrs: map[string]string{
"ref": "example.com/ref:v1.0.0",
},
},
{
Type: "registry",
Attrs: map[string]string{
"ref": "example.com/ref:v1.0.0",
},
},
{
Type: "local",
Attrs: map[string]string{
"dest": "/path/for/export",
},
},
{
Type: "local",
Attrs: map[string]string{
"dest": "/path/for/export",
},
},
},
expected: []*controlapi.CacheOptionsEntry{
{
Type: "registry",
Attrs: map[string]string{
"ref": "example.com/ref:v1.0.0",
},
},
{
Type: "local",
Attrs: map[string]string{
"dest": "/path/for/export",
},
},
},
},
{
name: "skip inline with attrs",
opts: []*controlapi.CacheOptionsEntry{
{
Type: "inline",
},
{
Type: "registry",
Attrs: map[string]string{
"ref": "example.com/ref:v1.0.0",
},
},
{
Type: "inline",
Attrs: map[string]string{
"foo": "bar",
},
},
},
rest: []*controlapi.CacheOptionsEntry{
{
Type: "inline",
},
{
Type: "registry",
Attrs: map[string]string{
"ref": "example.com/ref:v1.0.0",
},
},
},
expected: nil,
},
{
name: "skip inline simple",
opts: []*controlapi.CacheOptionsEntry{
{
Type: "inline",
},
{
Type: "inline",
},
},
rest: []*controlapi.CacheOptionsEntry{
{
Type: "inline",
},
},
expected: nil,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
rest, result, err := findDuplicateCacheOptions(tc.opts)
require.NoError(t, err)
require.ElementsMatch(t, tc.expected, result)
if tc.rest != nil {
require.ElementsMatch(t, tc.rest, rest)
} else if len(result) == 0 {
require.ElementsMatch(t, tc.opts, rest)
}
})
}
}
func TestParseCacheExportIgnoreError(t *testing.T) {
tests := map[string]struct {
expectedIgnoreError bool
expectedSupported bool
}{
"": {
expectedIgnoreError: false,
expectedSupported: false,
},
".": {
expectedIgnoreError: false,
expectedSupported: false,
},
"fake": {
expectedIgnoreError: false,
expectedSupported: false,
},
"true": {
expectedIgnoreError: true,
expectedSupported: true,
},
"True": {
expectedIgnoreError: true,
expectedSupported: true,
},
"TRUE": {
expectedIgnoreError: true,
expectedSupported: true,
},
"truee": {
expectedIgnoreError: false,
expectedSupported: false,
},
"false": {
expectedIgnoreError: false,
expectedSupported: true,
},
"False": {
expectedIgnoreError: false,
expectedSupported: true,
},
"FALSE": {
expectedIgnoreError: false,
expectedSupported: true,
},
"ffalse": {
expectedIgnoreError: false,
expectedSupported: false,
},
}
for ignoreErrStr, test := range tests {
t.Run(ignoreErrStr, func(t *testing.T) {
ignoreErr, supported := parseCacheExportIgnoreError(ignoreErrStr)
t.Log("checking expectedIgnoreError")
require.Equal(t, test.expectedIgnoreError, ignoreErr)
t.Log("checking expectedSupported")
require.Equal(t, test.expectedSupported, supported)
})
}
}