252 lines
7.7 KiB
Go
252 lines
7.7 KiB
Go
package cli
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.maximumdirect.net/eric/distributor/internal/storage"
|
|
"gitea.maximumdirect.net/eric/distributor/internal/testutil"
|
|
)
|
|
|
|
func TestExecuteRootHelp(t *testing.T) {
|
|
var stdout, stderr bytes.Buffer
|
|
|
|
code := Execute(context.Background(), []string{"--help"}, &stdout, &stderr)
|
|
|
|
if code != exitOK {
|
|
t.Fatalf("exit code = %d, want %d", code, exitOK)
|
|
}
|
|
if !strings.Contains(stdout.String(), "Usage:") {
|
|
t.Fatalf("stdout = %q, want help text", stdout.String())
|
|
}
|
|
if stderr.Len() != 0 {
|
|
t.Fatalf("stderr = %q, want empty", stderr.String())
|
|
}
|
|
}
|
|
|
|
func TestExecuteVersion(t *testing.T) {
|
|
var stdout, stderr bytes.Buffer
|
|
|
|
code := Execute(context.Background(), []string{"version"}, &stdout, &stderr)
|
|
|
|
if code != exitOK {
|
|
t.Fatalf("exit code = %d, want %d", code, exitOK)
|
|
}
|
|
if got, want := stdout.String(), "distributor dev\n"; got != want {
|
|
t.Fatalf("stdout = %q, want %q", got, want)
|
|
}
|
|
if stderr.Len() != 0 {
|
|
t.Fatalf("stderr = %q, want empty", stderr.String())
|
|
}
|
|
}
|
|
|
|
func TestExecuteValidate(t *testing.T) {
|
|
var stdout, stderr bytes.Buffer
|
|
|
|
code := Execute(context.Background(), []string{"validate", filepath.Join("..", "bundle", "testdata", "valid_bundle")}, &stdout, &stderr)
|
|
|
|
if code != exitOK {
|
|
t.Fatalf("exit code = %d, want %d; stderr = %q", code, exitOK, stderr.String())
|
|
}
|
|
if got, want := stdout.String(), "Validated 1 bundle(s)\n"; got != want {
|
|
t.Fatalf("stdout = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestExecuteValidateArgs(t *testing.T) {
|
|
validPath := filepath.Join("..", "bundle", "testdata", "valid_bundle")
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
wantCode int
|
|
wantStdout string
|
|
wantStderr string
|
|
}{
|
|
{
|
|
name: "zero args",
|
|
args: []string{"validate"},
|
|
wantCode: exitError,
|
|
wantStderr: "requires a path",
|
|
},
|
|
{
|
|
name: "one arg",
|
|
args: []string{"validate", validPath},
|
|
wantCode: exitOK,
|
|
wantStdout: "Validated 1 bundle(s)",
|
|
},
|
|
{
|
|
name: "two args",
|
|
args: []string{"validate", validPath, validPath},
|
|
wantCode: exitUsage,
|
|
wantStderr: "accepts at most one path",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
var stdout, stderr bytes.Buffer
|
|
code := Execute(context.Background(), tt.args, &stdout, &stderr)
|
|
if code != tt.wantCode {
|
|
t.Fatalf("exit code = %d, want %d; stderr = %q", code, tt.wantCode, stderr.String())
|
|
}
|
|
if tt.wantStdout != "" && !strings.Contains(stdout.String(), tt.wantStdout) {
|
|
t.Fatalf("stdout = %q, want substring %q", stdout.String(), tt.wantStdout)
|
|
}
|
|
if tt.wantStderr != "" && !strings.Contains(stderr.String(), tt.wantStderr) {
|
|
t.Fatalf("stderr = %q, want substring %q", stderr.String(), tt.wantStderr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExecuteInspect(t *testing.T) {
|
|
var stdout, stderr bytes.Buffer
|
|
|
|
code := Execute(context.Background(), []string{"inspect", filepath.Join("..", "bundle", "testdata", "valid_bundle")}, &stdout, &stderr)
|
|
|
|
if code != exitOK {
|
|
t.Fatalf("exit code = %d, want %d; stderr = %q", code, exitOK, stderr.String())
|
|
}
|
|
if !strings.Contains(stdout.String(), "id=weather.daily.brentwood.2026-05-30") {
|
|
t.Fatalf("stdout = %q, want bundle summary", stdout.String())
|
|
}
|
|
}
|
|
|
|
func TestExecuteInspectArgs(t *testing.T) {
|
|
validPath := filepath.Join("..", "bundle", "testdata", "valid_bundle")
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
wantCode int
|
|
wantStdout string
|
|
wantStderr string
|
|
}{
|
|
{
|
|
name: "zero args",
|
|
args: []string{"inspect"},
|
|
wantCode: exitError,
|
|
wantStderr: "requires a path",
|
|
},
|
|
{
|
|
name: "one arg",
|
|
args: []string{"inspect", validPath},
|
|
wantCode: exitOK,
|
|
wantStdout: "id=weather.daily.brentwood.2026-05-30",
|
|
},
|
|
{
|
|
name: "two args",
|
|
args: []string{"inspect", validPath, validPath},
|
|
wantCode: exitUsage,
|
|
wantStderr: "accepts at most one path",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
var stdout, stderr bytes.Buffer
|
|
code := Execute(context.Background(), tt.args, &stdout, &stderr)
|
|
if code != tt.wantCode {
|
|
t.Fatalf("exit code = %d, want %d; stderr = %q", code, tt.wantCode, stderr.String())
|
|
}
|
|
if tt.wantStdout != "" && !strings.Contains(stdout.String(), tt.wantStdout) {
|
|
t.Fatalf("stdout = %q, want substring %q", stdout.String(), tt.wantStdout)
|
|
}
|
|
if tt.wantStderr != "" && !strings.Contains(stderr.String(), tt.wantStderr) {
|
|
t.Fatalf("stderr = %q, want substring %q", stderr.String(), tt.wantStderr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExecuteRunDryRun(t *testing.T) {
|
|
sourceRoot := t.TempDir()
|
|
testutil.WriteSourceBundle(t, sourceRoot, "", testutil.BundleOptions{})
|
|
configPath := testutil.WriteMinimalLocalConfig(t, sourceRoot, t.TempDir())
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
|
|
code := Execute(context.Background(), []string{"run", "--config", configPath, "--dry-run"}, &stdout, &stderr)
|
|
|
|
if code != exitOK {
|
|
t.Fatalf("exit code = %d, want %d; stderr = %q", code, exitOK, stderr.String())
|
|
}
|
|
if !strings.Contains(stdout.String(), "action=publish_new") {
|
|
t.Fatalf("stdout = %q, want config summary", stdout.String())
|
|
}
|
|
if stderr.Len() != 0 {
|
|
t.Fatalf("stderr = %q, want empty", stderr.String())
|
|
}
|
|
}
|
|
|
|
func TestExecuteRunForceDryRunReportsWithoutWriting(t *testing.T) {
|
|
sourceRoot := t.TempDir()
|
|
destinationRoot := t.TempDir()
|
|
testutil.WriteSourceBundle(t, sourceRoot, "", testutil.BundleOptions{})
|
|
if err := os.WriteFile(filepath.Join(destinationRoot, "unmanaged.txt"), []byte("old"), 0o600); err != nil {
|
|
t.Fatalf("write unmanaged file: %v", err)
|
|
}
|
|
configPath := testutil.WriteMinimalLocalConfig(t, sourceRoot, destinationRoot)
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
code := Execute(context.Background(), []string{"run", "--config", configPath, "--force", "--dry-run"}, &stdout, &stderr)
|
|
|
|
if code != exitOK {
|
|
t.Fatalf("exit code = %d, want %d; stderr = %q", code, exitOK, stderr.String())
|
|
}
|
|
if !strings.Contains(stdout.String(), "action=force_replace") {
|
|
t.Fatalf("stdout = %q, want force_replace", stdout.String())
|
|
}
|
|
if _, err := os.Stat(filepath.Join(destinationRoot, "unmanaged.txt")); err != nil {
|
|
t.Fatalf("unmanaged file stat error = %v", err)
|
|
}
|
|
if _, err := os.Stat(filepath.Join(destinationRoot, storage.StateFileName)); !os.IsNotExist(err) {
|
|
t.Fatalf("state stat error = %v, want not exist", err)
|
|
}
|
|
}
|
|
|
|
func TestExecuteRunRejectsExtraPositionalArgs(t *testing.T) {
|
|
var stdout, stderr bytes.Buffer
|
|
|
|
code := Execute(context.Background(), []string{"run", "--config", "config.yml", "extra"}, &stdout, &stderr)
|
|
|
|
if code != exitUsage {
|
|
t.Fatalf("exit code = %d, want %d", code, exitUsage)
|
|
}
|
|
if !strings.Contains(stderr.String(), "does not accept positional arguments") {
|
|
t.Fatalf("stderr = %q, want positional argument error", stderr.String())
|
|
}
|
|
}
|
|
|
|
func TestExecuteRunPublishes(t *testing.T) {
|
|
sourceRoot := t.TempDir()
|
|
destinationRoot := t.TempDir()
|
|
testutil.WriteSourceBundle(t, sourceRoot, "", testutil.BundleOptions{})
|
|
configPath := testutil.WriteMinimalLocalConfig(t, sourceRoot, destinationRoot)
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
|
|
code := Execute(context.Background(), []string{"run", "--config", configPath}, &stdout, &stderr)
|
|
|
|
if code != exitOK {
|
|
t.Fatalf("exit code = %d, want %d; stderr = %q", code, exitOK, stderr.String())
|
|
}
|
|
if _, err := os.Stat(filepath.Join(destinationRoot, storage.StateFileName)); err != nil {
|
|
t.Fatalf("state stat error = %v", err)
|
|
}
|
|
}
|
|
|
|
func TestUnknownCommandIsUsageError(t *testing.T) {
|
|
var stdout, stderr bytes.Buffer
|
|
|
|
code := Execute(context.Background(), []string{"nope"}, &stdout, &stderr)
|
|
|
|
if code != exitUsage {
|
|
t.Fatalf("exit code = %d, want %d", code, exitUsage)
|
|
}
|
|
if !strings.Contains(stderr.String(), "unknown command") {
|
|
t.Fatalf("stderr = %q, want unknown command error", stderr.String())
|
|
}
|
|
}
|