Ctrl K
ComunidadGuías…

builder/build/dockerfile_build_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package build

import (
	"reflect"
	"strings"
	"testing"
)

// capability_id: rainbond.dockerfile-build.proxy-env-inheritance
func TestBuildKitProxyEnvVars(t *testing.T) {
	tests := []struct {
		name string
		env  map[string]string
		want map[string]string
	}{
		{
			name: "inherits configured proxy variables only",
			env: map[string]string{
				"HTTP_PROXY":    "http://proxy.example:8080",
				"HTTPS_PROXY":   "http://proxy.example:8443",
				"NO_PROXY":      "localhost,127.0.0.1",
				"UNRELATED_ENV": "must-not-be-propagated",
			},
			want: map[string]string{
				"HTTP_PROXY":  "http://proxy.example:8080",
				"HTTPS_PROXY": "http://proxy.example:8443",
				"NO_PROXY":    "localhost,127.0.0.1",
			},
		},
		{
			name: "leaves buildkit environment unchanged without proxy configuration",
			env: map[string]string{
				"UNRELATED_ENV": "must-not-be-propagated",
			},
			want: map[string]string{},
		},
		{
			name: "skips empty proxy variables",
			env: map[string]string{
				"HTTP_PROXY":  "http://proxy.example:8080",
				"HTTPS_PROXY": "",
				"NO_PROXY":    "",
			},
			want: map[string]string{
				"HTTP_PROXY": "http://proxy.example:8080",
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			for _, name := range []string{"HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY"} {
				t.Setenv(name, "")
			}
			for name, value := range tt.env {
				t.Setenv(name, value)
			}

			got := make(map[string]string)
			for _, env := range buildKitProxyEnvVars() {
				got[env.Name] = env.Value
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("buildKitProxyEnvVars() = %#v, want %#v", got, tt.want)
			}
		})
	}
}

// TestLocalBuildKitCacheArgsContainServiceID 验证生成的本地 layer cache 参数
// 使用 buildctl 的 --import-cache / --export-cache(而非 buildx 的
// --cache-from / --cache-to),且缓存路径包含 serviceID。
func TestLocalBuildKitCacheArgsContainServiceID(t *testing.T) {
	const serviceID = "svc-abc123"

	args := localBuildKitCacheArgs(serviceID)

	for _, invalid := range []string{"--cache-from", "--cache-to"} {
		for _, a := range args {
			if a == invalid {
				t.Errorf("args contain %q, which buildctl does not support", invalid)
			}
		}
	}

	from := flagValue(t, args, "--import-cache")
	to := flagValue(t, args, "--export-cache")

	wantDir := "/cache/buildkit/" + serviceID
	if !strings.Contains(from, wantDir) {
		t.Errorf("--import-cache %q does not contain cache dir %q", from, wantDir)
	}
	if !strings.Contains(to, wantDir) {
		t.Errorf("--export-cache %q does not contain cache dir %q", to, wantDir)
	}
	if !strings.Contains(from, "type=local") || !strings.Contains(from, "src=") {
		t.Errorf("--import-cache %q is not a local source spec", from)
	}
	if !strings.Contains(to, "type=local") || !strings.Contains(to, "dest=") || !strings.Contains(to, "mode=max") {
		t.Errorf("--export-cache %q is not a local mode=max dest spec", to)
	}
}

// flagValue 返回 args 中紧跟在 flag 之后的值,找不到则 fail。
func flagValue(t *testing.T, args []string, flag string) string {
	t.Helper()
	for i, a := range args {
		if a == flag {
			if i+1 >= len(args) {
				t.Fatalf("flag %q has no following value in args %#v", flag, args)
			}
			return args[i+1]
		}
	}
	t.Fatalf("flag %q not found in args %#v", flag, args)
	return ""
}