Skip to content

Commit 5df7fe1

Browse files
feat(tests): refactor test helpers and update Makefile for improved test execution
1 parent 7e37842 commit 5df7fe1

10 files changed

Lines changed: 84 additions & 92 deletions

File tree

.envrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export TEST_HELPERS=$(realpath build)/

Makefile

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,16 @@ prepare_test: verify download $(GOBIN)/mockery ## Generate mocks
125125
@find . -path "*/mocks/*" -exec rm {} \;
126126
@"$(GOBIN)/mockery" --config .mockery.yml
127127

128-
$(BUILD)test-helper: $(BUILD) ## Build the test helper binary
128+
$(BUILD)test-args: ./testhelpers/args/*.go ## Build the test-args binary
129129
@echo "[*] $@"
130-
@$(GOBUILD) -v -o $(BUILD)test-helper ./testhelper
130+
@$(GOBUILD) -v -o $(BUILD)test-args ./testhelpers/args
131+
132+
$(BUILD)test-echo: ./testhelpers/echo/*.go ## Build the test-echo binary
133+
@echo "[*] $@"
134+
@$(GOBUILD) -v -o $(BUILD)test-echo ./testhelpers/echo
135+
136+
.PHONY: test-helpers
137+
test-helpers: $(BUILD)test-args $(BUILD)test-echo ## Build all test helper binaries
131138

132139
download: verify ## Download dependencies
133140
@echo "[*] $@"
@@ -182,20 +189,23 @@ build-windows: prepare_build ## Build the binary for Windows
182189

183190
build-all: build-mac build-linux build-pi build-windows ## Build the binary for all platforms
184191

185-
test: $(GOBIN)/gotestsum prepare_test $(BUILD)test-helper ## Run unit tests
192+
test: export TEST_HELPERS=$(BUILD)
193+
test: $(GOBIN)/gotestsum prepare_test test-helpers ## Run unit tests
186194
@echo "[*] $@"
187-
@TEST_HELPER=$(BUILD)test-helper $(GOBIN)/gotestsum -- -count=1 $(TESTS)
195+
@$(GOBIN)/gotestsum -- -count=1 $(TESTS)
188196

189-
test-short: $(GOBIN)/gotestsum prepare_test $(BUILD)test-helper ## Run unit tests in short mode
197+
test-short: export TEST_HELPERS=$(BUILD)
198+
test-short: $(GOBIN)/gotestsum prepare_test test-helpers ## Run unit tests in short mode
190199
@echo "[*] $@"
191-
@TEST_HELPER=$(BUILD)test-helper $(GOBIN)/gotestsum -- -short -count=1 $(TESTS)
200+
@$(GOBIN)/gotestsum -- -short -count=1 $(TESTS)
192201

193-
test-race: $(GOBIN)/gotestsum prepare_test $(BUILD)test-helper ## Run unit tests with race detector
202+
test-race: export TEST_HELPERS=$(BUILD)
203+
test-race: $(GOBIN)/gotestsum prepare_test test-helpers ## Run unit tests with race detector
194204
@echo "[*] $@"
195-
@TEST_HELPER=$(BUILD)test-helper $(GOBIN)/gotestsum -- -short -race -count=1 $(TESTS)
205+
@$(GOBIN)/gotestsum -- -short -race -count=1 $(TESTS)
196206

197-
test-ci: export TEST_HELPER=$(BUILD)test-helper
198-
test-ci: $(GOBIN)/gotestsum prepare_test $(BUILD)test-helper ## Run unit tests with coverage (for CI)
207+
test-ci: export TEST_HELPERS=$(BUILD)
208+
test-ci: $(GOBIN)/gotestsum prepare_test test-helpers ## Run unit tests with coverage (for CI)
199209
@echo "[*] $@"
200210
@$(GOBIN)/gotestsum --junitfile $(JUNIT_FILE) -- -race -short -count=1 -tags=fuse -coverprofile='$(COVERAGE_FILE)' ./...
201211

@@ -405,7 +415,8 @@ ssh-test: ## Run SSH client tests
405415
@go test -run TestSSHClient -v -race -tags ssh -coverprofile='$(COVERAGE_SSH_FILE)' ./ssh
406416

407417
.PHONY: write-run-tests
408-
write-run-tests: $(BUILD)test-helper ## Generate the run-tests.sh script for BSD tests
418+
write-run-tests: export TEST_HELPERS=$(BUILD)
419+
write-run-tests: test-helpers ## Generate the run-tests.sh script for BSD tests
409420
@echo "[*] $@"
410-
@$(GOTEST) -c ./batt ./calendar ./util/...
411-
@TEST_HELPER=$(BUILD)test-helper ./scripts/write-run-tests.sh
421+
@$(GOTEST) -c . ./batt ./calendar ./util/...
422+
@./scripts/write-run-tests.sh

lock/lock_signal_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func TestLockIsRemovedAfterInterruptSignal(t *testing.T) {
2626
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
2727
defer cancel()
2828

29-
cmd := exec.CommandContext(ctx, helperBinary, "-wait", "2000", "-lock", lockfile)
29+
cmd := exec.CommandContext(ctx, lockBinary, "lock", "-wait", "2000", "-lock", lockfile)
3030
cmd.Stdout = buffer
3131
cmd.Stderr = buffer
3232

@@ -55,7 +55,7 @@ func TestLockIsRemovedAfterInterruptSignalInsideShell(t *testing.T) {
5555
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
5656
defer cancel()
5757

58-
cmd := exec.CommandContext(ctx, "sh", "-c", "exec \""+helperBinary+"\" -wait 2000 -lock \""+lockfile+"\"")
58+
cmd := exec.CommandContext(ctx, "sh", "-c", "exec \""+lockBinary+"\" lock -wait 2000 -lock \""+lockfile+"\"")
5959
cmd.Stdout = buffer
6060
cmd.Stderr = buffer
6161

lock/lock_test.go

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,28 @@ import (
1212
"testing"
1313
"time"
1414

15-
"github.com/creativeprojects/resticprofile/constants"
16-
"github.com/creativeprojects/resticprofile/platform"
1715
"github.com/creativeprojects/resticprofile/shell"
1816
"github.com/shirou/gopsutil/v3/process"
1917
"github.com/stretchr/testify/assert"
2018
"github.com/stretchr/testify/require"
2119
)
2220

2321
var (
24-
helperBinary string
22+
lockBinary string
2523
)
2624

2725
func TestMain(m *testing.M) {
2826
// using an anonymous function to handle defer statements before os.Exit()
2927
exitCode := func() int {
30-
ctx, cancel := context.WithTimeout(context.Background(), constants.DefaultTestTimeout)
31-
defer cancel()
32-
33-
tempDir, err := os.MkdirTemp("", "resticprofile-lock")
28+
var err error
29+
lockBinary = filepath.Join(os.Getenv("TEST_HELPERS"), "test-args")
30+
lockBinary, err = filepath.Abs(lockBinary)
3431
if err != nil {
35-
fmt.Fprintf(os.Stderr, "cannot create temp dir: %v\n", err)
32+
fmt.Fprintf(os.Stderr, "Failed to get absolute path of test-args binary: %v\n", err)
3633
return 1
3734
}
38-
defer os.RemoveAll(tempDir)
39-
40-
helperBinary = filepath.Join(tempDir, platform.Executable("locktest"))
41-
42-
cmd := exec.CommandContext(ctx, "go", "build", "-buildvcs=false", "-v", "-o", helperBinary, "./test")
43-
if output, err := cmd.CombinedOutput(); err != nil {
44-
fmt.Fprintf(os.Stderr, "Error building lock binary: %s\nCommand output: %s\n", err, string(output))
35+
if _, err := os.Stat(lockBinary); err != nil {
36+
fmt.Fprintf(os.Stderr, "test-args binary is not available at expected path: %s\n", lockBinary)
4537
return 1
4638
}
4739

@@ -147,7 +139,7 @@ func TestProcessPID(t *testing.T) {
147139
buffer := &bytes.Buffer{}
148140

149141
// use the lock helper binary (we only need to wait for some time, we don't need the locking part)
150-
cmd := shell.NewCommand(helperBinary, []string{"-wait", "200", "-lock", filepath.Join(t.TempDir(), t.Name())})
142+
cmd := shell.NewCommand(lockBinary, []string{"lock", "-wait", "200", "-lock", filepath.Join(t.TempDir(), t.Name())})
151143
cmd.Stdout = buffer
152144
// SetPID method is called right after we forked and have a PID available
153145
cmd.SetPID = func(pid int32) {
@@ -232,7 +224,7 @@ func TestForceLockWithRunningPID(t *testing.T) {
232224
assert.True(t, lock.HasLocked())
233225

234226
// user the lock helper binary (we only need to wait for some time, we don't need the locking part)
235-
cmd := shell.NewCommand(helperBinary, []string{"-wait", "100", "-lock", filepath.Join(t.TempDir(), t.Name())})
227+
cmd := shell.NewCommand(lockBinary, []string{"lock", "-wait", "100", "-lock", filepath.Join(t.TempDir(), t.Name())})
236228
cmd.SetPID = func(pid int32) {
237229
lock.SetPID(pid)
238230
// make sure we cannot break the lock right now
@@ -255,7 +247,7 @@ func TestLockWithNoInterruption(t *testing.T) {
255247
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
256248
defer cancel()
257249

258-
cmd := exec.CommandContext(ctx, helperBinary, "-wait", "10", "-lock", lockfile)
250+
cmd := exec.CommandContext(ctx, lockBinary, "lock", "-wait", "10", "-lock", lockfile)
259251
cmd.Stdout = buffer
260252
cmd.Stderr = buffer
261253

main_test.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,14 @@ func TestMain(m *testing.M) {
4343
return 1
4444
}
4545

46-
echoBinary = filepath.Join(tempDir, platform.Executable("shellecho"))
47-
48-
cmdEcho := exec.CommandContext(ctx, "go", "build", "-buildvcs=false", "-o", echoBinary, "./shell/echo")
49-
if output, err := cmdEcho.CombinedOutput(); err != nil {
50-
fmt.Fprintf(os.Stderr, "Error building shell/echo binary: %s\nCommand output: %s\n", err, string(output))
46+
echoBinary = filepath.Join(os.Getenv("TEST_HELPERS"), "test-echo")
47+
echoBinary, err = filepath.Abs(echoBinary)
48+
if err != nil {
49+
fmt.Fprintf(os.Stderr, "Failed to get absolute path of test-echo binary: %v\n", err)
50+
return 1
51+
}
52+
if _, err := os.Stat(echoBinary); err != nil {
53+
fmt.Fprintf(os.Stderr, "test-echo binary is not available at expected path: %s\n", echoBinary)
5154
return 1
5255
}
5356

scripts/write-run-tests.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ OUTPUT=./scripts/run-tests.sh
33

44
echo "#!/bin/sh" >$OUTPUT
55
chmod +x $OUTPUT
6-
echo "export TEST_HELPER=$TEST_HELPER" >>$OUTPUT
7-
find . -type f -name "*.test" | xargs -I % echo "echo \"=== % ===\" && % -test.short -test.v || command_failed=1" >>$OUTPUT
6+
echo "export TEST_HELPERS=\"$TEST_HELPERS\"" >>$OUTPUT
7+
find . -type f -name "*.test" -print0 | xargs -0 -I % echo "echo \"=== % ===\" && % -test.short -test.v || command_failed=1" >>$OUTPUT
88
echo "if [ \${command_failed:-0} -eq 1 ]" >>$OUTPUT
99
echo "then" >>$OUTPUT
1010
echo " echo \"-> FAIL\"" >>$OUTPUT
Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package main
22

33
import (
4-
"flag"
54
"fmt"
65
"os"
76
"os/signal"
@@ -11,22 +10,7 @@ import (
1110
"github.com/creativeprojects/resticprofile/lock"
1211
)
1312

14-
// quick command to put a lock, wait for some time, then release the lock
15-
16-
func main() {
17-
wait := 0
18-
lockfile := ""
19-
flag.IntVar(&wait, "wait", 1000, "Wait n milliseconds before unlocking")
20-
flag.StringVar(&lockfile, "lock", "test.lock", "Name of the lock file")
21-
flag.Parse()
22-
23-
code := run(wait, lockfile)
24-
if code > 0 {
25-
os.Exit(code)
26-
}
27-
}
28-
29-
func run(wait int, lockfile string) int {
13+
func runLock(wait int, lockfile string) int {
3014
sigChan := make(chan os.Signal, 2)
3115
signal.Ignore()
3216
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"flag"
45
"fmt"
56
"os"
67

@@ -21,6 +22,7 @@ func run() int {
2122
}
2223

2324
switch os.Args[1] {
25+
2426
case "executable":
2527
executable, err := util.Executable()
2628
if err != nil {
@@ -30,6 +32,19 @@ func run() int {
3032
fmt.Printf("%q\n", executable)
3133
return 0
3234

35+
case "lock":
36+
wait := 0
37+
lockfile := ""
38+
flags := flag.NewFlagSet("lock", flag.ContinueOnError)
39+
flags.IntVar(&wait, "wait", 1000, "Wait n milliseconds before unlocking")
40+
flags.StringVar(&lockfile, "lock", "test.lock", "Name of the lock file")
41+
if err := flags.Parse(os.Args[2:]); err != nil {
42+
fmt.Fprintf(os.Stderr, "parsing flags: %s", err)
43+
return 1
44+
}
45+
46+
return runLock(wait, lockfile)
47+
3348
default:
3449
fmt.Printf("command argument %q not supported\n", os.Args[1])
3550
return 1

util/executable_unix_test.go

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ package util
44

55
import (
66
"context"
7-
"errors"
8-
"io/fs"
97
"os"
108
"os/exec"
119
"path/filepath"
@@ -22,16 +20,10 @@ const (
2220
)
2321

2422
func TestExecutable(t *testing.T) {
25-
helperBinary := os.Getenv("TEST_HELPER")
26-
if helperBinary == "" {
27-
helperBinary = "./test-helper"
28-
}
23+
helperBinary := filepath.Join(os.Getenv("TEST_HELPERS"), "test-args")
2924
helperBinary, err := filepath.Abs(helperBinary)
30-
require.NoError(t, err, "Failed to get absolute path of helper binary")
31-
32-
if _, err := os.Stat(helperBinary); errors.Is(err, fs.ErrNotExist) {
33-
t.Fatalf("Helper binary does not exist at expected path: %q\n", helperBinary)
34-
}
25+
require.NoError(t, err, "Failed to get absolute path of helper binary", helperBinary)
26+
require.FileExists(t, helperBinary, "Helper binary is not available at expected path")
3527

3628
tempDir := t.TempDir()
3729
symlinkBinary := filepath.Join(tempDir, "executable_test_symlink")
@@ -44,11 +36,10 @@ func TestExecutable(t *testing.T) {
4436

4537
cmd := exec.CommandContext(ctx, helperBinary, helperExecutableCommand)
4638
output, err := cmd.Output()
47-
if err != nil {
48-
t.Fatalf("Error executing helper binary: %s\n", err)
49-
}
39+
require.NoError(t, err)
40+
5041
t.Log(string(output))
51-
assert.Equal(t, string(output), "\""+helperBinary+"\"\n", "Output should match the helper binary path")
42+
assert.Equal(t, "\""+helperBinary+"\"\n", string(output), "Output should match the helper binary path")
5243
})
5344

5445
t.Run("absolute symlink", func(t *testing.T) {
@@ -57,11 +48,10 @@ func TestExecutable(t *testing.T) {
5748

5849
cmd := exec.CommandContext(ctx, symlinkBinary, helperExecutableCommand)
5950
output, err := cmd.Output()
60-
if err != nil {
61-
t.Fatalf("Error executing helper binary: %s\n", err)
62-
}
51+
require.NoError(t, err)
52+
6353
t.Log(string(output))
64-
assert.Equal(t, string(output), "\""+symlinkBinary+"\"\n", "Output should match the helper binary path")
54+
assert.Equal(t, "\""+symlinkBinary+"\"\n", string(output), "Output should match the helper binary path")
6555
})
6656

6757
t.Run("relative", func(t *testing.T) {
@@ -71,11 +61,10 @@ func TestExecutable(t *testing.T) {
7161
cmd := exec.CommandContext(ctx, "./"+filepath.Base(helperBinary), helperExecutableCommand)
7262
cmd.Dir = filepath.Dir(helperBinary) // Set the working directory to the helper binary's directory
7363
output, err := cmd.Output()
74-
if err != nil {
75-
t.Fatalf("Error executing helper binary: %s\n", err)
76-
}
64+
require.NoError(t, err)
65+
7766
t.Log(string(output))
78-
assert.Equal(t, string(output), "\""+helperBinary+"\"\n", "Output should match the helper binary path")
67+
assert.Equal(t, "\""+helperBinary+"\"\n", string(output), "Output should match the helper binary path")
7968
})
8069

8170
t.Run("relative symlink", func(t *testing.T) {
@@ -85,11 +74,10 @@ func TestExecutable(t *testing.T) {
8574
cmd := exec.CommandContext(ctx, "./"+filepath.Base(symlinkBinary), helperExecutableCommand)
8675
cmd.Dir = tempDir // Set the working directory to the temp directory
8776
output, err := cmd.Output()
88-
if err != nil {
89-
t.Fatalf("Error executing helper binary: %s\n", err)
90-
}
77+
require.NoError(t, err)
78+
9179
t.Log(string(output))
92-
assert.Equal(t, string(output), "\""+symlinkBinary+"\"\n", "Output should match the helper binary path")
80+
assert.Equal(t, "\""+symlinkBinary+"\"\n", string(output), "Output should match the helper binary path")
9381
})
9482

9583
t.Run("from PATH", func(t *testing.T) {
@@ -102,11 +90,10 @@ func TestExecutable(t *testing.T) {
10290

10391
cmd := exec.CommandContext(ctx, filepath.Base(helperBinary), helperExecutableCommand)
10492
output, err := cmd.Output()
105-
if err != nil {
106-
t.Fatalf("Error executing helper binary: %s\n", err)
107-
}
93+
require.NoError(t, err)
94+
10895
t.Log(string(output))
109-
assert.Equal(t, string(output), "\""+helperBinary+"\"\n", "Output should match the helper binary path")
96+
assert.Equal(t, "\""+helperBinary+"\"\n", string(output), "Output should match the helper binary path")
11097
})
11198

11299
t.Run("symlink from PATH", func(t *testing.T) {
@@ -119,10 +106,9 @@ func TestExecutable(t *testing.T) {
119106

120107
cmd := exec.CommandContext(ctx, filepath.Base(symlinkBinary), helperExecutableCommand)
121108
output, err := cmd.Output()
122-
if err != nil {
123-
t.Fatalf("Error executing helper binary: %s\n", err)
124-
}
109+
require.NoError(t, err)
110+
125111
t.Log(string(output))
126-
assert.Equal(t, string(output), "\""+symlinkBinary+"\"\n", "Output should match the helper binary path")
112+
assert.Equal(t, "\""+symlinkBinary+"\"\n", string(output), "Output should match the helper binary path")
127113
})
128114
}

0 commit comments

Comments
 (0)