Skip to content

Commit 0b79738

Browse files
committed
test: add errors.Is and errors.As compatibility tests
1 parent f2c9faa commit 0b79738

File tree

2 files changed

+87
-25
lines changed

2 files changed

+87
-25
lines changed

cmd/tempo/initcmd/init_test.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ func TestInitCommand(t *testing.T) {
5454
}
5555

5656
// Run the init command
57-
app := &cli.Command{}
58-
app.Commands = []*cli.Command{
57+
cliApp := &cli.Command{}
58+
cliApp.Commands = []*cli.Command{
5959
SetupInitCommand(cliCtx),
6060
}
6161

6262
output, err := testhelpers.CaptureStdout(func() {
6363
args := []string{"tempo", "init", "--base-folder", baseFolder}
64-
err := app.Run(context.Background(), args)
64+
err := cliApp.Run(context.Background(), args)
6565
if err != nil {
6666
t.Fatalf("Unexpected error: %v", err)
6767
}
@@ -106,13 +106,13 @@ func TestInitCommand_FailsOnExistingConfigFile(t *testing.T) {
106106
t.Fatalf("Failed to create config file: %v", err)
107107
}
108108

109-
app := &cli.Command{}
110-
app.Commands = []*cli.Command{
109+
cliApp := &cli.Command{}
110+
cliApp.Commands = []*cli.Command{
111111
SetupInitCommand(cliCtx),
112112
}
113113

114114
args := []string{"tempo", "init", "--base-folder", tempDir}
115-
err = app.Run(context.Background(), args)
115+
err = cliApp.Run(context.Background(), args)
116116

117117
if err == nil {
118118
t.Fatal("Expected error, but got none")
@@ -138,8 +138,8 @@ func TestInitCommand_FailsOnUnwritableConfigFile(t *testing.T) {
138138
CWD: tempDir,
139139
}
140140

141-
app := &cli.Command{}
142-
app.Commands = []*cli.Command{
141+
cliApp := &cli.Command{}
142+
cliApp.Commands = []*cli.Command{
143143
SetupInitCommand(cliCtx),
144144
}
145145

@@ -172,7 +172,7 @@ func TestInitCommand_FailsOnUnwritableConfigFile(t *testing.T) {
172172

173173
// Step 3: Run `init` again, expecting a write error
174174
args := []string{"tempo", "init", "--base-folder", tempDir}
175-
err = app.Run(context.Background(), args)
175+
err = cliApp.Run(context.Background(), args)
176176

177177
if err == nil {
178178
t.Fatal("Expected error due to unwritable file, but got none")
@@ -224,13 +224,13 @@ func TestInitCommand_UsesDefaultTemplateExtensions(t *testing.T) {
224224
// Override config to simulate missing extensions
225225
cliCtx.Config.Templates.Extensions = []string{} // Force empty slice
226226

227-
app := &cli.Command{}
228-
app.Commands = []*cli.Command{
227+
cliApp := &cli.Command{}
228+
cliApp.Commands = []*cli.Command{
229229
SetupInitCommand(cliCtx),
230230
}
231231

232232
args := []string{"tempo", "init", "--base-folder", tempDir}
233-
err := app.Run(context.Background(), args)
233+
err := cliApp.Run(context.Background(), args)
234234

235235
if err != nil {
236236
t.Fatalf("Unexpected error: %v", err)
@@ -380,8 +380,8 @@ func TestInitCommand_FailsOnConfigFileCheckError(t *testing.T) {
380380
CWD: tempDir,
381381
}
382382

383-
app := &cli.Command{}
384-
app.Commands = []*cli.Command{
383+
cliApp := &cli.Command{}
384+
cliApp.Commands = []*cli.Command{
385385
SetupInitCommand(cliCtx),
386386
}
387387

@@ -393,7 +393,7 @@ func TestInitCommand_FailsOnConfigFileCheckError(t *testing.T) {
393393

394394
// Step 2: Run `init`, expecting an error
395395
args := []string{"tempo", "init", "--base-folder", tempDir}
396-
err := app.Run(context.Background(), args)
396+
err := cliApp.Run(context.Background(), args)
397397
if err == nil {
398398
t.Fatal("Expected error due to file existence check failure, but got none")
399399
}
@@ -413,8 +413,8 @@ func TestInitCommand_FailsOnMissingGoMod(t *testing.T) {
413413
CWD: tempDir,
414414
}
415415

416-
app := &cli.Command{}
417-
app.Commands = []*cli.Command{
416+
cliApp := &cli.Command{}
417+
cliApp.Commands = []*cli.Command{
418418
SetupInitCommand(cliCtx),
419419
}
420420

@@ -428,7 +428,7 @@ func TestInitCommand_FailsOnMissingGoMod(t *testing.T) {
428428

429429
// Run `init`, expecting an error due to missing go.mod
430430
args := []string{"tempo", "init", "--base-folder", tempDir}
431-
err := app.Run(context.Background(), args)
431+
err := cliApp.Run(context.Background(), args)
432432

433433
if err == nil {
434434
t.Fatal("Expected error due to missing go.mod file, but got none")

internal/errors/errors_test.go

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -296,27 +296,27 @@ func TestAnyToStringSlice(t *testing.T) {
296296
expected []string
297297
}{
298298
{
299-
name: "Convert mixed types",
299+
name: "Convert mixed types",
300300
input: []any{"one", 2, 3.14, true},
301301
expected: []string{"one", "2", "3.14", "true"},
302302
},
303303
{
304-
name: "Convert single-element slice",
304+
name: "Convert single-element slice",
305305
input: []any{42},
306306
expected: []string{"42"},
307307
},
308308
{
309-
name: "Convert empty slice",
309+
name: "Convert empty slice",
310310
input: []any{},
311311
expected: []string{},
312312
},
313313
{
314-
name: "Convert slice with special characters",
315-
input: []any{"$#@!", "你好", "😊"},
316-
expected: []string{"$#@!", "你好", "😊"},
314+
name: "Convert slice with special characters",
315+
input: []any{"$#@!", "hello", "world"},
316+
expected: []string{"$#@!", "hello", "world"},
317317
},
318318
{
319-
name: "Convert slice with nil values",
319+
name: "Convert slice with nil values",
320320
input: []any{nil, "test", nil},
321321
expected: []string{"<nil>", "test", "<nil>"},
322322
},
@@ -331,3 +331,65 @@ func TestAnyToStringSlice(t *testing.T) {
331331
})
332332
}
333333
}
334+
335+
// TestErrorsIs validates that errors.Is works correctly with TempoError chain.
336+
func TestErrorsIs(t *testing.T) {
337+
// Create a base sentinel error
338+
baseErr := errors.New("base error")
339+
340+
// Wrap it with TempoError
341+
wrappedErr := Wrap("wrapped error", baseErr)
342+
343+
// Double wrap
344+
doubleWrapped := Wrap("double wrapped", wrappedErr)
345+
346+
// Test errors.Is finds the base error in the chain
347+
if !errors.Is(wrappedErr, baseErr) {
348+
t.Error("errors.Is should find baseErr in wrappedErr")
349+
}
350+
351+
if !errors.Is(doubleWrapped, baseErr) {
352+
t.Error("errors.Is should find baseErr in doubleWrapped")
353+
}
354+
355+
// Test that unrelated error is not found
356+
unrelatedErr := errors.New("unrelated")
357+
if errors.Is(doubleWrapped, unrelatedErr) {
358+
t.Error("errors.Is should not find unrelatedErr in doubleWrapped")
359+
}
360+
}
361+
362+
// TestErrorsAs validates that errors.As works correctly with TempoError chain.
363+
func TestErrorsAs(t *testing.T) {
364+
// Create a TempoError
365+
tempoErr := NewTempoError("tempo error", nil).WithCode(500)
366+
367+
// Wrap it with another TempoError
368+
wrappedErr := Wrap("wrapped error", tempoErr)
369+
370+
// Test errors.As finds the inner TempoError
371+
var target *TempoError
372+
if !errors.As(wrappedErr, &target) {
373+
t.Error("errors.As should find TempoError in wrappedErr")
374+
}
375+
376+
// The first match should be the outer error
377+
if target.Message != "wrapped error" {
378+
t.Errorf("Expected 'wrapped error', got %q", target.Message)
379+
}
380+
381+
// Test with standard error wrapped inside
382+
stdErr := errors.New("standard error")
383+
wrappedStd := Wrap("wrapped std", stdErr)
384+
385+
var tempoTarget *TempoError
386+
if !errors.As(wrappedStd, &tempoTarget) {
387+
t.Error("errors.As should find TempoError wrapper")
388+
}
389+
390+
// Verify Unwrap chain works
391+
unwrapped := errors.Unwrap(tempoTarget)
392+
if unwrapped != stdErr {
393+
t.Errorf("Expected unwrapped error to be stdErr, got %v", unwrapped)
394+
}
395+
}

0 commit comments

Comments
 (0)