kunchenguid--no-mistakes
26f897c1ec
release / release-please (push) Failing after 1m49s
docs / build (push) Failing after 6m34s
release / build-and-upload (arm64, linux) (push) Has been cancelled
release / build-and-upload (arm64, windows) (push) Has been cancelled
release / build-darwin (amd64, darwin) (push) Has been cancelled
release / checksums (push) Has been cancelled
release / finalize (push) Has been cancelled
release / build-darwin (arm64, darwin) (push) Has been cancelled
release / build-and-upload (amd64, linux) (push) Has been cancelled
release / build-and-upload (amd64, windows) (push) Has been cancelled
docs / deploy (push) Has been cancelled
170 行
5.0 KiB
Go
170 行
5.0 KiB
Go
//go:build e2e
|
|
|
|
package e2e
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/kunchenguid/no-mistakes/internal/ipc"
|
|
"github.com/kunchenguid/no-mistakes/internal/paths"
|
|
"github.com/kunchenguid/no-mistakes/internal/types"
|
|
)
|
|
|
|
func TestFixtureRootFromRepoRoot(t *testing.T) {
|
|
root, err := fixtureRootFromRepoRoot(t.TempDir())
|
|
if err == nil {
|
|
t.Fatalf("fixtureRootFromRepoRoot succeeded with %q, want error", root)
|
|
}
|
|
|
|
repoRoot, err := findRepoRoot()
|
|
if err != nil {
|
|
t.Fatalf("findRepoRoot: %v", err)
|
|
}
|
|
|
|
root, err = fixtureRootFromRepoRoot(repoRoot)
|
|
if err != nil {
|
|
t.Fatalf("fixtureRootFromRepoRoot: %v", err)
|
|
}
|
|
want := filepath.Join(repoRoot, "internal", "e2e", "fixtures")
|
|
if root != want {
|
|
t.Fatalf("fixture root = %q, want %q", root, want)
|
|
}
|
|
}
|
|
|
|
func TestDaemonStartTimeoutLeavesRoomForLoginShellProbe(t *testing.T) {
|
|
timeout, err := time.ParseDuration(e2eDaemonStartTimeout)
|
|
if err != nil {
|
|
t.Fatalf("parse e2eDaemonStartTimeout: %v", err)
|
|
}
|
|
if timeout <= 30*time.Second {
|
|
t.Fatalf("e2eDaemonStartTimeout = %v, want more than the 30s login-shell probe budget", timeout)
|
|
}
|
|
}
|
|
|
|
func TestCommitChangeCreatesMissingBranchFromMain(t *testing.T) {
|
|
workDir := t.TempDir()
|
|
h := &Harness{t: t, WorkDir: workDir}
|
|
ctx := context.Background()
|
|
mustGit := func(args ...string) string {
|
|
t.Helper()
|
|
out, err := h.runGit(ctx, workDir, args...)
|
|
if err != nil {
|
|
t.Fatalf("git %v: %v\n%s", args, err, out)
|
|
}
|
|
return strings.TrimSpace(string(out))
|
|
}
|
|
|
|
mustGit("init", "--initial-branch=main")
|
|
mustGit("config", "user.email", "e2e@example.com")
|
|
mustGit("config", "user.name", "E2E Test")
|
|
mustGit("config", "commit.gpgsign", "false")
|
|
|
|
readme := filepath.Join(workDir, "README.md")
|
|
if err := os.WriteFile(readme, []byte("base\n"), 0o644); err != nil {
|
|
t.Fatalf("write README.md: %v", err)
|
|
}
|
|
mustGit("add", "README.md")
|
|
mustGit("commit", "-m", "initial commit")
|
|
mainSHA := mustGit("rev-parse", "HEAD")
|
|
|
|
mustGit("checkout", "-b", "feature/existing")
|
|
featureOnly := filepath.Join(workDir, "feature-only.txt")
|
|
if err := os.WriteFile(featureOnly, []byte("feature\n"), 0o644); err != nil {
|
|
t.Fatalf("write feature-only.txt: %v", err)
|
|
}
|
|
mustGit("add", "feature-only.txt")
|
|
mustGit("commit", "-m", "feature commit")
|
|
|
|
h.CommitChange("feature/new", "hello.txt", "hello\n", "new branch commit")
|
|
|
|
mergeBase := mustGit("merge-base", "feature/new", "main")
|
|
if mergeBase != mainSHA {
|
|
t.Fatalf("merge-base(feature/new, main) = %s, want %s", mergeBase, mainSHA)
|
|
}
|
|
if _, err := os.Stat(filepath.Join(workDir, "feature-only.txt")); !os.IsNotExist(err) {
|
|
t.Fatalf("feature-only.txt present on new branch, want branch rooted at main")
|
|
}
|
|
show := mustGit("show", "feature/new:hello.txt")
|
|
if show != "hello" {
|
|
t.Fatalf("hello.txt contents = %q, want %q", show, "hello")
|
|
}
|
|
}
|
|
|
|
func TestDaemonStopDirFallsBackWhenWorkDirMoved(t *testing.T) {
|
|
workDir := filepath.Join(t.TempDir(), "missing-work")
|
|
homeDir := t.TempDir()
|
|
h := &Harness{WorkDir: workDir, HomeDir: homeDir}
|
|
|
|
if got := h.daemonStopDir(); got != homeDir {
|
|
t.Fatalf("daemonStopDir() = %q, want home dir %q", got, homeDir)
|
|
}
|
|
}
|
|
|
|
func TestWaitForRunPrefersNewestRunOnBranch(t *testing.T) {
|
|
nmHome, err := os.MkdirTemp("/tmp", "nm-e2e-")
|
|
if err != nil {
|
|
t.Fatalf("MkdirTemp: %v", err)
|
|
}
|
|
t.Cleanup(func() { _ = os.RemoveAll(nmHome) })
|
|
workDir := t.TempDir()
|
|
p := paths.WithRoot(nmHome)
|
|
if err := os.MkdirAll(nmHome, 0o755); err != nil {
|
|
t.Fatalf("mkdir nm home: %v", err)
|
|
}
|
|
|
|
server := ipc.NewServer()
|
|
var calls atomic.Int32
|
|
server.Handle(ipc.MethodGetRuns, func(_ context.Context, _ json.RawMessage) (interface{}, error) {
|
|
if calls.Add(1) == 1 {
|
|
return ipc.GetRunsResult{Runs: []ipc.RunInfo{
|
|
{ID: "run-new", RepoID: "ignored", Branch: "feature/e2e", Status: types.RunRunning, CreatedAt: 20, UpdatedAt: 20},
|
|
{ID: "run-old", RepoID: "ignored", Branch: "feature/e2e", Status: types.RunCompleted, CreatedAt: 10, UpdatedAt: 10},
|
|
}}, nil
|
|
}
|
|
return ipc.GetRunsResult{Runs: []ipc.RunInfo{
|
|
{ID: "run-new", RepoID: "ignored", Branch: "feature/e2e", Status: types.RunCompleted, CreatedAt: 20, UpdatedAt: 30},
|
|
{ID: "run-old", RepoID: "ignored", Branch: "feature/e2e", Status: types.RunCompleted, CreatedAt: 10, UpdatedAt: 10},
|
|
}}, nil
|
|
})
|
|
|
|
errCh := make(chan error, 1)
|
|
go func() {
|
|
errCh <- server.Serve(p.Socket())
|
|
}()
|
|
t.Cleanup(func() {
|
|
server.Close()
|
|
if err := <-errCh; err != nil {
|
|
t.Errorf("ipc server: %v", err)
|
|
}
|
|
})
|
|
|
|
deadline := time.Now().Add(2 * time.Second)
|
|
for time.Now().Before(deadline) {
|
|
client, err := ipc.Dial(p.Socket())
|
|
if err == nil {
|
|
client.Close()
|
|
break
|
|
}
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
|
|
h := &Harness{t: t, NMHome: nmHome, WorkDir: workDir}
|
|
run := h.WaitForRun("feature/e2e", 2*time.Second)
|
|
if run.ID != "run-new" {
|
|
t.Fatalf("WaitForRun returned %q, want newest run", run.ID)
|
|
}
|
|
if run.Status != types.RunCompleted {
|
|
t.Fatalf("WaitForRun status = %s, want %s", run.Status, types.RunCompleted)
|
|
}
|
|
if calls.Load() < 2 {
|
|
t.Fatalf("GetRuns calls = %d, want at least 2 polls", calls.Load())
|
|
}
|
|
}
|