| // Copyright 2026 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package cli |
| |
| import ( |
| "context" |
| "flag" |
| "testing" |
| |
| "go.fuchsia.dev/fuchsia/src/testing/host-target-testing/artifacts" |
| ) |
| |
| func TestRepeatableBuildVarParsing(t *testing.T) { |
| for _, tc := range []struct { |
| name string |
| kind repeatableBuildKind |
| input string |
| expectedValue string |
| expectedVersion string |
| expectError bool |
| }{ |
| { |
| name: "build id plain", |
| kind: buildIdKind, |
| input: "12345", |
| expectedValue: "12345", |
| expectedVersion: "latest", |
| }, |
| { |
| name: "build id with latest", |
| kind: buildIdKind, |
| input: "12345:latest", |
| expectedValue: "12345", |
| expectedVersion: "latest", |
| }, |
| { |
| name: "build id with fromApiLevel", |
| kind: buildIdKind, |
| input: "12345:fromApiLevel", |
| expectedValue: "12345", |
| expectedVersion: "fromApiLevel", |
| }, |
| { |
| name: "builder name", |
| kind: builderNameKind, |
| input: "core.x64-release", |
| expectedValue: "core.x64-release", |
| }, |
| { |
| name: "fuchsia build dir", |
| kind: fuchsiaBuildDirKind, |
| input: "/path/to/out/default", |
| expectedValue: "/path/to/out/default", |
| }, |
| { |
| name: "product bundle dir", |
| kind: productBundleDirKind, |
| input: "/path/to/pb", |
| expectedValue: "/path/to/pb", |
| }, |
| { |
| name: "empty string error", |
| kind: buildIdKind, |
| input: "", |
| expectError: true, |
| }, |
| { |
| name: "invalid version policy error", |
| kind: buildIdKind, |
| input: "12345:invalid_policy", |
| expectError: true, |
| }, |
| { |
| name: "blob fetch mode not allowed in version specifier", |
| kind: buildIdKind, |
| input: "12345:lazy", |
| expectError: true, |
| }, |
| { |
| name: "blob fetch mode prefetch not allowed in version specifier", |
| kind: buildIdKind, |
| input: "12345:prefetch", |
| expectError: true, |
| }, |
| { |
| name: "too many parts in specifier error", |
| kind: buildIdKind, |
| input: "12345:latest:lazy", |
| expectError: true, |
| }, |
| } { |
| t.Run(tc.name, func(t *testing.T) { |
| c := &RepeatableBuildConfig{} |
| rbVar := repeatableBuildVar{c: c, kind: tc.kind} |
| err := rbVar.Set(tc.input) |
| if tc.expectError { |
| if err == nil { |
| t.Fatalf("expected error for input %q, got nil", tc.input) |
| } |
| return |
| } |
| if err != nil { |
| t.Fatalf("unexpected error for input %q: %v", tc.input, err) |
| } |
| if len(c.builds) != 1 { |
| t.Fatalf("expected 1 build, got %d", len(c.builds)) |
| } |
| b := c.builds[0] |
| if b.kind != tc.kind { |
| t.Fatalf("expected kind %v, got %v", tc.kind, b.kind) |
| } |
| if b.value != tc.expectedValue { |
| t.Fatalf("expected value %q, got %q", tc.expectedValue, b.value) |
| } |
| if tc.expectedVersion != "" && b.versionPolicy != tc.expectedVersion { |
| t.Fatalf("expected versionPolicy %q, got %q", tc.expectedVersion, b.versionPolicy) |
| } |
| }) |
| } |
| } |
| |
| func TestRepeatableBuildConfigBlobFetchModeDefault(t *testing.T) { |
| fs := flag.NewFlagSet("test", flag.ContinueOnError) |
| c := NewRepeatableBuildConfig(fs, nil, nil, "", "") |
| |
| args := []string{ |
| "-fuchsia-build-dir", "/tmp/dir1", |
| "-product-bundle-dir", "/tmp/dir2", |
| } |
| if err := fs.Parse(args); err != nil { |
| t.Fatalf("failed to parse flags: %v", err) |
| } |
| |
| if c.blobFetchMode != artifacts.Unspecified { |
| t.Fatalf("expected default blobFetchMode Unspecified, got %v", c.blobFetchMode) |
| } |
| |
| builds, err := c.GetBuilds(context.Background(), nil, "") |
| if err != nil { |
| t.Fatalf("GetBuilds failed: %v", err) |
| } |
| |
| if len(builds) != 2 { |
| t.Fatalf("expected 2 builds, got %d", len(builds)) |
| } |
| |
| for i, b := range builds { |
| if b.BlobFetchMode != artifacts.Unspecified { |
| t.Fatalf("build %d: expected Unspecified, got %v", i, b.BlobFetchMode) |
| } |
| } |
| } |
| |
| func TestRepeatableBuildConfigBlobFetchModeConfigured(t *testing.T) { |
| for _, modeStr := range []string{"lazy", "prefetch"} { |
| t.Run(modeStr, func(t *testing.T) { |
| fs := flag.NewFlagSet("test", flag.ContinueOnError) |
| c := NewRepeatableBuildConfig(fs, nil, nil, "", "") |
| |
| args := []string{ |
| "-blob-fetch-mode", modeStr, |
| "-fuchsia-build-dir", "/tmp/dir1", |
| } |
| if err := fs.Parse(args); err != nil { |
| t.Fatalf("failed to parse flags: %v", err) |
| } |
| |
| expectedMode, err := artifacts.ParseBlobFetchMode(modeStr) |
| if err != nil { |
| t.Fatalf("failed to parse mode: %v", err) |
| } |
| |
| if c.blobFetchMode != expectedMode { |
| t.Fatalf("expected blobFetchMode %v, got %v", expectedMode, c.blobFetchMode) |
| } |
| |
| builds, err := c.GetBuilds(context.Background(), nil, "") |
| if err != nil { |
| t.Fatalf("GetBuilds failed: %v", err) |
| } |
| |
| if len(builds) != 1 { |
| t.Fatalf("expected 1 build, got %d", len(builds)) |
| } |
| |
| if builds[0].BlobFetchMode != expectedMode { |
| t.Fatalf("expected %v, got %v", expectedMode, builds[0].BlobFetchMode) |
| } |
| }) |
| } |
| } |