From 75b77935a7174dab84d21d27653682ca5e61a962 Mon Sep 17 00:00:00 2001 From: ChrisJBurns <29541485+ChrisJBurns@users.noreply.github.com> Date: Thu, 4 Sep 2025 21:37:35 +0100 Subject: [PATCH 1/2] adds missing tests Signed-off-by: ChrisJBurns <29541485+ChrisJBurns@users.noreply.github.com> --- pkg/core/workload_test.go | 248 +++++++++++++++++++++++++ pkg/env/env_test.go | 61 ++++++ pkg/errors/errors_test.go | 275 ++++++++++++++++++++++++++++ pkg/transport/errors/errors_test.go | 50 +++++ pkg/versions/version_test.go | 149 +++++++++++++++ 5 files changed, 783 insertions(+) create mode 100644 pkg/core/workload_test.go create mode 100644 pkg/env/env_test.go create mode 100644 pkg/errors/errors_test.go create mode 100644 pkg/transport/errors/errors_test.go create mode 100644 pkg/versions/version_test.go diff --git a/pkg/core/workload_test.go b/pkg/core/workload_test.go new file mode 100644 index 000000000..03bd8927a --- /dev/null +++ b/pkg/core/workload_test.go @@ -0,0 +1,248 @@ +package core + +import ( + "reflect" + "testing" + "time" + + "github.com/stacklok/toolhive/pkg/container/runtime" + "github.com/stacklok/toolhive/pkg/transport/types" +) + +func TestSortWorkloadsByName(t *testing.T) { + baseTime := time.Now() + + tests := []struct { + name string + workloads []Workload + want []Workload + }{ + { + name: "sort alphabetically", + workloads: []Workload{ + { + Name: "zebra", + Package: "package1", + URL: "http://localhost:8001", + Port: 8001, + ToolType: "mcp", + TransportType: types.TransportTypeSSE, + Status: runtime.WorkloadStatusRunning, + CreatedAt: baseTime, + }, + { + Name: "apple", + Package: "package2", + URL: "http://localhost:8002", + Port: 8002, + ToolType: "mcp", + TransportType: types.TransportTypeSSE, + Status: runtime.WorkloadStatusRunning, + CreatedAt: baseTime, + }, + { + Name: "mango", + Package: "package3", + URL: "http://localhost:8003", + Port: 8003, + ToolType: "mcp", + TransportType: types.TransportTypeSSE, + Status: runtime.WorkloadStatusRunning, + CreatedAt: baseTime, + }, + }, + want: []Workload{ + { + Name: "apple", + Package: "package2", + URL: "http://localhost:8002", + Port: 8002, + ToolType: "mcp", + TransportType: types.TransportTypeSSE, + Status: runtime.WorkloadStatusRunning, + CreatedAt: baseTime, + }, + { + Name: "mango", + Package: "package3", + URL: "http://localhost:8003", + Port: 8003, + ToolType: "mcp", + TransportType: types.TransportTypeSSE, + Status: runtime.WorkloadStatusRunning, + CreatedAt: baseTime, + }, + { + Name: "zebra", + Package: "package1", + URL: "http://localhost:8001", + Port: 8001, + ToolType: "mcp", + TransportType: types.TransportTypeSSE, + Status: runtime.WorkloadStatusRunning, + CreatedAt: baseTime, + }, + }, + }, + { + name: "already sorted", + workloads: []Workload{ + {Name: "aaa"}, + {Name: "bbb"}, + {Name: "ccc"}, + }, + want: []Workload{ + {Name: "aaa"}, + {Name: "bbb"}, + {Name: "ccc"}, + }, + }, + { + name: "reverse order", + workloads: []Workload{ + {Name: "ccc"}, + {Name: "bbb"}, + {Name: "aaa"}, + }, + want: []Workload{ + {Name: "aaa"}, + {Name: "bbb"}, + {Name: "ccc"}, + }, + }, + { + name: "with numbers", + workloads: []Workload{ + {Name: "server-10"}, + {Name: "server-2"}, + {Name: "server-1"}, + {Name: "server-20"}, + }, + want: []Workload{ + {Name: "server-1"}, + {Name: "server-10"}, + {Name: "server-2"}, + {Name: "server-20"}, + }, + }, + { + name: "empty slice", + workloads: []Workload{}, + want: []Workload{}, + }, + { + name: "single element", + workloads: []Workload{ + {Name: "single"}, + }, + want: []Workload{ + {Name: "single"}, + }, + }, + { + name: "case sensitive sorting", + workloads: []Workload{ + {Name: "Zebra"}, + {Name: "apple"}, + {Name: "Banana"}, + {Name: "cherry"}, + }, + want: []Workload{ + {Name: "Banana"}, + {Name: "Zebra"}, + {Name: "apple"}, + {Name: "cherry"}, + }, + }, + { + name: "with special characters", + workloads: []Workload{ + {Name: "server_b"}, + {Name: "server-a"}, + {Name: "server.c"}, + {Name: "server@d"}, + }, + want: []Workload{ + {Name: "server-a"}, + {Name: "server.c"}, + {Name: "server@d"}, + {Name: "server_b"}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Make a copy to avoid modifying the test data + workloadsCopy := make([]Workload, len(tt.workloads)) + copy(workloadsCopy, tt.workloads) + + SortWorkloadsByName(workloadsCopy) + + if !reflect.DeepEqual(workloadsCopy, tt.want) { + t.Errorf("SortWorkloadsByName() got = %v, want %v", workloadsCopy, tt.want) + } + }) + } +} + +func TestWorkload_Fields(t *testing.T) { + now := time.Now() + w := Workload{ + Name: "test-workload", + Package: "test-package", + URL: "http://localhost:8080", + Port: 8080, + ToolType: "mcp", + TransportType: types.TransportTypeStdio, + Status: runtime.WorkloadStatusRunning, + StatusContext: "healthy", + CreatedAt: now, + Labels: map[string]string{ + "env": "test", + }, + Group: "test-group", + ToolsFilter: []string{"tool1", "tool2"}, + Remote: true, + } + + if w.Name != "test-workload" { + t.Errorf("Name = %v, want %v", w.Name, "test-workload") + } + if w.Package != "test-package" { + t.Errorf("Package = %v, want %v", w.Package, "test-package") + } + if w.URL != "http://localhost:8080" { + t.Errorf("URL = %v, want %v", w.URL, "http://localhost:8080") + } + if w.Port != 8080 { + t.Errorf("Port = %v, want %v", w.Port, 8080) + } + if w.ToolType != "mcp" { + t.Errorf("ToolType = %v, want %v", w.ToolType, "mcp") + } + if w.TransportType != types.TransportTypeStdio { + t.Errorf("TransportType = %v, want %v", w.TransportType, types.TransportTypeStdio) + } + if w.Status != runtime.WorkloadStatusRunning { + t.Errorf("Status = %v, want %v", w.Status, runtime.WorkloadStatusRunning) + } + if w.StatusContext != "healthy" { + t.Errorf("StatusContext = %v, want %v", w.StatusContext, "healthy") + } + if !w.CreatedAt.Equal(now) { + t.Errorf("CreatedAt = %v, want %v", w.CreatedAt, now) + } + if len(w.Labels) != 1 || w.Labels["env"] != "test" { + t.Errorf("Labels = %v, want %v", w.Labels, map[string]string{"env": "test"}) + } + if w.Group != "test-group" { + t.Errorf("Group = %v, want %v", w.Group, "test-group") + } + if len(w.ToolsFilter) != 2 || w.ToolsFilter[0] != "tool1" || w.ToolsFilter[1] != "tool2" { + t.Errorf("ToolsFilter = %v, want %v", w.ToolsFilter, []string{"tool1", "tool2"}) + } + if !w.Remote { + t.Errorf("Remote = %v, want %v", w.Remote, true) + } +} \ No newline at end of file diff --git a/pkg/env/env_test.go b/pkg/env/env_test.go new file mode 100644 index 000000000..acbb7bb9d --- /dev/null +++ b/pkg/env/env_test.go @@ -0,0 +1,61 @@ +package env + +import ( + "os" + "testing" +) + +func TestOSReader_Getenv(t *testing.T) { + testKey := "TEST_ENV_VARIABLE_FOR_TESTING" + testValue := "test_value_123" + + // Set an environment variable for testing + originalValue, wasSet := os.LookupEnv(testKey) + os.Setenv(testKey, testValue) + defer func() { + if wasSet { + os.Setenv(testKey, originalValue) + } else { + os.Unsetenv(testKey) + } + }() + + reader := &OSReader{} + + tests := []struct { + name string + key string + want string + }{ + { + name: "existing environment variable", + key: testKey, + want: testValue, + }, + { + name: "non-existing environment variable", + key: "NONEXISTENT_ENV_VAR_TESTING_12345", + want: "", + }, + { + name: "empty key", + key: "", + want: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := reader.Getenv(tt.key) + if got != tt.want { + t.Errorf("OSReader.Getenv() = %v, want %v", got, tt.want) + } + }) + } +} + +// TestReader_InterfaceCompliance ensures OSReader implements the Reader interface +func TestReader_InterfaceCompliance(t *testing.T) { + var _ Reader = &OSReader{} + // If this compiles, the test passes +} \ No newline at end of file diff --git a/pkg/errors/errors_test.go b/pkg/errors/errors_test.go new file mode 100644 index 000000000..3a5f5a908 --- /dev/null +++ b/pkg/errors/errors_test.go @@ -0,0 +1,275 @@ +package errors + +import ( + "errors" + "testing" +) + +func TestError_Error(t *testing.T) { + tests := []struct { + name string + err *Error + want string + }{ + { + name: "error with cause", + err: &Error{ + Type: ErrInvalidArgument, + Message: "test message", + Cause: errors.New("underlying error"), + }, + want: "invalid_argument: test message: underlying error", + }, + { + name: "error without cause", + err: &Error{ + Type: ErrContainerRuntime, + Message: "test message", + Cause: nil, + }, + want: "container_runtime: test message", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.err.Error() + if got != tt.want { + t.Errorf("Error.Error() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestError_Unwrap(t *testing.T) { + cause := errors.New("underlying error") + err := &Error{ + Type: ErrInternal, + Message: "test message", + Cause: cause, + } + + if got := err.Unwrap(); got != cause { + t.Errorf("Error.Unwrap() = %v, want %v", got, cause) + } + + errNoCause := &Error{ + Type: ErrInternal, + Message: "test message", + Cause: nil, + } + + if got := errNoCause.Unwrap(); got != nil { + t.Errorf("Error.Unwrap() = %v, want nil", got) + } +} + +func TestNewError(t *testing.T) { + cause := errors.New("underlying error") + err := NewError(ErrInvalidArgument, "test message", cause) + + if err.Type != ErrInvalidArgument { + t.Errorf("NewError().Type = %v, want %v", err.Type, ErrInvalidArgument) + } + if err.Message != "test message" { + t.Errorf("NewError().Message = %v, want %v", err.Message, "test message") + } + if err.Cause != cause { + t.Errorf("NewError().Cause = %v, want %v", err.Cause, cause) + } +} + +func TestNewErrorConstructors(t *testing.T) { + cause := errors.New("cause") + + tests := []struct { + name string + constructor func(string, error) *Error + wantType string + }{ + { + name: "NewInvalidArgumentError", + constructor: NewInvalidArgumentError, + wantType: ErrInvalidArgument, + }, + { + name: "NewContainerRuntimeError", + constructor: NewContainerRuntimeError, + wantType: ErrContainerRuntime, + }, + { + name: "NewContainerNotFoundError", + constructor: NewContainerNotFoundError, + wantType: ErrContainerNotFound, + }, + { + name: "NewContainerAlreadyExistsError", + constructor: NewContainerAlreadyExistsError, + wantType: ErrContainerAlreadyExists, + }, + { + name: "NewContainerNotRunningError", + constructor: NewContainerNotRunningError, + wantType: ErrContainerNotRunning, + }, + { + name: "NewContainerAlreadyRunningError", + constructor: NewContainerAlreadyRunningError, + wantType: ErrContainerAlreadyRunning, + }, + { + name: "NewRunConfigNotFoundError", + constructor: NewRunConfigNotFoundError, + wantType: ErrRunConfigNotFound, + }, + { + name: "NewGroupAlreadyExistsError", + constructor: NewGroupAlreadyExistsError, + wantType: ErrGroupAlreadyExists, + }, + { + name: "NewGroupNotFoundError", + constructor: NewGroupNotFoundError, + wantType: ErrGroupNotFound, + }, + { + name: "NewTransportError", + constructor: NewTransportError, + wantType: ErrTransport, + }, + { + name: "NewPermissionsError", + constructor: NewPermissionsError, + wantType: ErrPermissions, + }, + { + name: "NewInternalError", + constructor: NewInternalError, + wantType: ErrInternal, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.constructor("test message", cause) + if err.Type != tt.wantType { + t.Errorf("%s().Type = %v, want %v", tt.name, err.Type, tt.wantType) + } + if err.Message != "test message" { + t.Errorf("%s().Message = %v, want %v", tt.name, err.Message, "test message") + } + if err.Cause != cause { + t.Errorf("%s().Cause = %v, want %v", tt.name, err.Cause, cause) + } + }) + } +} + +func TestErrorTypeCheckers(t *testing.T) { + tests := []struct { + name string + err error + checker func(error) bool + want bool + }{ + { + name: "IsInvalidArgument with matching error", + err: NewInvalidArgumentError("test", nil), + checker: IsInvalidArgument, + want: true, + }, + { + name: "IsInvalidArgument with non-matching error", + err: NewContainerRuntimeError("test", nil), + checker: IsInvalidArgument, + want: false, + }, + { + name: "IsInvalidArgument with non-Error type", + err: errors.New("regular error"), + checker: IsInvalidArgument, + want: false, + }, + { + name: "IsContainerRuntime with matching error", + err: NewContainerRuntimeError("test", nil), + checker: IsContainerRuntime, + want: true, + }, + { + name: "IsContainerNotFound with matching error", + err: NewContainerNotFoundError("test", nil), + checker: IsContainerNotFound, + want: true, + }, + { + name: "IsContainerAlreadyExists with matching error", + err: NewContainerAlreadyExistsError("test", nil), + checker: IsContainerAlreadyExists, + want: true, + }, + { + name: "IsContainerNotRunning with matching error", + err: NewContainerNotRunningError("test", nil), + checker: IsContainerNotRunning, + want: true, + }, + { + name: "IsContainerAlreadyRunning with matching error", + err: NewContainerAlreadyRunningError("test", nil), + checker: IsContainerAlreadyRunning, + want: true, + }, + { + name: "IsRunConfigNotFound with matching error", + err: NewRunConfigNotFoundError("test", nil), + checker: IsRunConfigNotFound, + want: true, + }, + { + name: "IsGroupAlreadyExists with matching error", + err: NewGroupAlreadyExistsError("test", nil), + checker: IsGroupAlreadyExists, + want: true, + }, + { + name: "IsGroupNotFound with matching error", + err: NewGroupNotFoundError("test", nil), + checker: IsGroupNotFound, + want: true, + }, + { + name: "IsTransport with matching error", + err: NewTransportError("test", nil), + checker: IsTransport, + want: true, + }, + { + name: "IsPermissions with matching error", + err: NewPermissionsError("test", nil), + checker: IsPermissions, + want: true, + }, + { + name: "IsInternal with matching error", + err: NewInternalError("test", nil), + checker: IsInternal, + want: true, + }, + { + name: "IsInternal with nil error", + err: nil, + checker: IsInternal, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.checker(tt.err) + if got != tt.want { + t.Errorf("%s() = %v, want %v", tt.name, got, tt.want) + } + }) + } +} \ No newline at end of file diff --git a/pkg/transport/errors/errors_test.go b/pkg/transport/errors/errors_test.go new file mode 100644 index 000000000..077e10216 --- /dev/null +++ b/pkg/transport/errors/errors_test.go @@ -0,0 +1,50 @@ +package errors + +import ( + "errors" + "testing" +) + +func TestErrUnsupportedTransport(t *testing.T) { + if ErrUnsupportedTransport == nil { + t.Error("ErrUnsupportedTransport should not be nil") + } + + expectedMsg := "unsupported transport type" + if ErrUnsupportedTransport.Error() != expectedMsg { + t.Errorf("ErrUnsupportedTransport.Error() = %v, want %v", ErrUnsupportedTransport.Error(), expectedMsg) + } + + // Test that it's a distinct error + if errors.Is(ErrUnsupportedTransport, ErrContainerNameNotSet) { + t.Error("ErrUnsupportedTransport should not be equal to ErrContainerNameNotSet") + } + + // Test error wrapping + wrappedErr := errors.Join(ErrUnsupportedTransport, errors.New("additional context")) + if !errors.Is(wrappedErr, ErrUnsupportedTransport) { + t.Error("Wrapped error should still match ErrUnsupportedTransport") + } +} + +func TestErrContainerNameNotSet(t *testing.T) { + if ErrContainerNameNotSet == nil { + t.Error("ErrContainerNameNotSet should not be nil") + } + + expectedMsg := "container name not set" + if ErrContainerNameNotSet.Error() != expectedMsg { + t.Errorf("ErrContainerNameNotSet.Error() = %v, want %v", ErrContainerNameNotSet.Error(), expectedMsg) + } + + // Test that it's a distinct error + if errors.Is(ErrContainerNameNotSet, ErrUnsupportedTransport) { + t.Error("ErrContainerNameNotSet should not be equal to ErrUnsupportedTransport") + } + + // Test error wrapping + wrappedErr := errors.Join(ErrContainerNameNotSet, errors.New("additional context")) + if !errors.Is(wrappedErr, ErrContainerNameNotSet) { + t.Error("Wrapped error should still match ErrContainerNameNotSet") + } +} \ No newline at end of file diff --git a/pkg/versions/version_test.go b/pkg/versions/version_test.go new file mode 100644 index 000000000..f05aef97d --- /dev/null +++ b/pkg/versions/version_test.go @@ -0,0 +1,149 @@ +package versions + +import ( + "fmt" + "runtime" + "strings" + "testing" +) + +func TestGetVersionInfo(t *testing.T) { + // Save original values + origVersion := Version + origCommit := Commit + origBuildDate := BuildDate + + tests := []struct { + name string + version string + commit string + buildDate string + wantCheck func(VersionInfo) bool + }{ + { + name: "dev version with unknown commit", + version: "dev", + commit: unknownStr, + buildDate: unknownStr, + wantCheck: func(v VersionInfo) bool { + // When version is "dev" and commit is unknown, version should be "build-unknown" + return strings.HasPrefix(v.Version, "build-") && + v.Commit == unknownStr && + v.BuildDate == unknownStr && + v.GoVersion == runtime.Version() && + v.Platform == fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH) + }, + }, + { + name: "dev version with commit", + version: "dev", + commit: "abc123def456789", + buildDate: unknownStr, + wantCheck: func(v VersionInfo) bool { + // When version is "dev" with a commit, version should be "build-abc123de" (8 chars) + return v.Version == "build-abc123de" && + v.Commit == "abc123def456789" && + v.BuildDate == unknownStr && + v.GoVersion == runtime.Version() && + v.Platform == fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH) + }, + }, + { + name: "release version", + version: "v1.2.3", + commit: "abc123def456789", + buildDate: "2024-01-15T10:30:00Z", + wantCheck: func(v VersionInfo) bool { + return v.Version == "v1.2.3" && + v.Commit == "abc123def456789" && + v.BuildDate == "2024-01-15 10:30:00 UTC" && + v.GoVersion == runtime.Version() && + v.Platform == fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH) + }, + }, + { + name: "custom build version", + version: "custom-build-1", + commit: "xyz789", + buildDate: "2024-03-20T15:45:30Z", + wantCheck: func(v VersionInfo) bool { + return v.Version == "custom-build-1" && + v.Commit == "xyz789" && + v.BuildDate == "2024-03-20 15:45:30 UTC" && + v.GoVersion == runtime.Version() && + v.Platform == fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH) + }, + }, + { + name: "invalid date format", + version: "v2.0.0", + commit: "def456", + buildDate: "not-a-date", + wantCheck: func(v VersionInfo) bool { + return v.Version == "v2.0.0" && + v.Commit == "def456" && + v.BuildDate == "not-a-date" && // Should remain unchanged if not parseable + v.GoVersion == runtime.Version() && + v.Platform == fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH) + }, + }, + { + name: "dev version with short commit", + version: "dev", + commit: "short", + buildDate: unknownStr, + wantCheck: func(v VersionInfo) bool { + // When commit is shorter than 8 chars, it should use the full length + return v.Version == "build-short" && + v.Commit == "short" && + v.BuildDate == unknownStr + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Set test values + Version = tt.version + Commit = tt.commit + BuildDate = tt.buildDate + + got := GetVersionInfo() + + if !tt.wantCheck(got) { + t.Errorf("GetVersionInfo() check failed, got = %+v", got) + } + }) + } + + // Restore original values + Version = origVersion + Commit = origCommit + BuildDate = origBuildDate +} + +func TestVersionInfo_Fields(t *testing.T) { + vi := VersionInfo{ + Version: "test-version", + Commit: "test-commit", + BuildDate: "test-date", + GoVersion: "test-go-version", + Platform: "test-platform", + } + + if vi.Version != "test-version" { + t.Errorf("Version = %v, want %v", vi.Version, "test-version") + } + if vi.Commit != "test-commit" { + t.Errorf("Commit = %v, want %v", vi.Commit, "test-commit") + } + if vi.BuildDate != "test-date" { + t.Errorf("BuildDate = %v, want %v", vi.BuildDate, "test-date") + } + if vi.GoVersion != "test-go-version" { + t.Errorf("GoVersion = %v, want %v", vi.GoVersion, "test-go-version") + } + if vi.Platform != "test-platform" { + t.Errorf("Platform = %v, want %v", vi.Platform, "test-platform") + } +} \ No newline at end of file From 75b4633e76835a4cc18725897ab6f547271b51ff Mon Sep 17 00:00:00 2001 From: ChrisJBurns <29541485+ChrisJBurns@users.noreply.github.com> Date: Thu, 4 Sep 2025 22:55:25 +0100 Subject: [PATCH 2/2] lint Signed-off-by: ChrisJBurns <29541485+ChrisJBurns@users.noreply.github.com> --- pkg/core/workload_test.go | 5 ++++- pkg/env/env_test.go | 13 ++++++++----- pkg/errors/errors_test.go | 16 ++++++++++++---- pkg/transport/errors/errors_test.go | 4 +++- pkg/versions/version_test.go | 9 ++++++--- 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/pkg/core/workload_test.go b/pkg/core/workload_test.go index 03bd8927a..ac94c5f29 100644 --- a/pkg/core/workload_test.go +++ b/pkg/core/workload_test.go @@ -10,6 +10,7 @@ import ( ) func TestSortWorkloadsByName(t *testing.T) { + t.Parallel() baseTime := time.Now() tests := []struct { @@ -173,6 +174,7 @@ func TestSortWorkloadsByName(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() // Make a copy to avoid modifying the test data workloadsCopy := make([]Workload, len(tt.workloads)) copy(workloadsCopy, tt.workloads) @@ -187,6 +189,7 @@ func TestSortWorkloadsByName(t *testing.T) { } func TestWorkload_Fields(t *testing.T) { + t.Parallel() now := time.Now() w := Workload{ Name: "test-workload", @@ -245,4 +248,4 @@ func TestWorkload_Fields(t *testing.T) { if !w.Remote { t.Errorf("Remote = %v, want %v", w.Remote, true) } -} \ No newline at end of file +} diff --git a/pkg/env/env_test.go b/pkg/env/env_test.go index acbb7bb9d..d6564e719 100644 --- a/pkg/env/env_test.go +++ b/pkg/env/env_test.go @@ -5,20 +5,21 @@ import ( "testing" ) -func TestOSReader_Getenv(t *testing.T) { +func TestOSReader_Getenv(t *testing.T) { //nolint:paralleltest // Modifies environment variables + // Cannot run in parallel because it modifies environment variables testKey := "TEST_ENV_VARIABLE_FOR_TESTING" testValue := "test_value_123" // Set an environment variable for testing originalValue, wasSet := os.LookupEnv(testKey) os.Setenv(testKey, testValue) - defer func() { + t.Cleanup(func() { if wasSet { os.Setenv(testKey, originalValue) } else { os.Unsetenv(testKey) } - }() + }) reader := &OSReader{} @@ -44,8 +45,9 @@ func TestOSReader_Getenv(t *testing.T) { }, } - for _, tt := range tests { + for _, tt := range tests { //nolint:paralleltest // Test modifies environment variables t.Run(tt.name, func(t *testing.T) { + // Cannot run in parallel because parent test modifies environment variables got := reader.Getenv(tt.key) if got != tt.want { t.Errorf("OSReader.Getenv() = %v, want %v", got, tt.want) @@ -56,6 +58,7 @@ func TestOSReader_Getenv(t *testing.T) { // TestReader_InterfaceCompliance ensures OSReader implements the Reader interface func TestReader_InterfaceCompliance(t *testing.T) { + t.Parallel() var _ Reader = &OSReader{} // If this compiles, the test passes -} \ No newline at end of file +} diff --git a/pkg/errors/errors_test.go b/pkg/errors/errors_test.go index 3a5f5a908..a8a0fde73 100644 --- a/pkg/errors/errors_test.go +++ b/pkg/errors/errors_test.go @@ -6,10 +6,11 @@ import ( ) func TestError_Error(t *testing.T) { + t.Parallel() tests := []struct { - name string - err *Error - want string + name string + err *Error + want string }{ { name: "error with cause", @@ -33,6 +34,7 @@ func TestError_Error(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() got := tt.err.Error() if got != tt.want { t.Errorf("Error.Error() = %v, want %v", got, tt.want) @@ -42,6 +44,7 @@ func TestError_Error(t *testing.T) { } func TestError_Unwrap(t *testing.T) { + t.Parallel() cause := errors.New("underlying error") err := &Error{ Type: ErrInternal, @@ -65,6 +68,7 @@ func TestError_Unwrap(t *testing.T) { } func TestNewError(t *testing.T) { + t.Parallel() cause := errors.New("underlying error") err := NewError(ErrInvalidArgument, "test message", cause) @@ -80,6 +84,7 @@ func TestNewError(t *testing.T) { } func TestNewErrorConstructors(t *testing.T) { + t.Parallel() cause := errors.New("cause") tests := []struct { @@ -151,6 +156,7 @@ func TestNewErrorConstructors(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() err := tt.constructor("test message", cause) if err.Type != tt.wantType { t.Errorf("%s().Type = %v, want %v", tt.name, err.Type, tt.wantType) @@ -166,6 +172,7 @@ func TestNewErrorConstructors(t *testing.T) { } func TestErrorTypeCheckers(t *testing.T) { + t.Parallel() tests := []struct { name string err error @@ -266,10 +273,11 @@ func TestErrorTypeCheckers(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() got := tt.checker(tt.err) if got != tt.want { t.Errorf("%s() = %v, want %v", tt.name, got, tt.want) } }) } -} \ No newline at end of file +} diff --git a/pkg/transport/errors/errors_test.go b/pkg/transport/errors/errors_test.go index 077e10216..6466a8119 100644 --- a/pkg/transport/errors/errors_test.go +++ b/pkg/transport/errors/errors_test.go @@ -6,6 +6,7 @@ import ( ) func TestErrUnsupportedTransport(t *testing.T) { + t.Parallel() if ErrUnsupportedTransport == nil { t.Error("ErrUnsupportedTransport should not be nil") } @@ -28,6 +29,7 @@ func TestErrUnsupportedTransport(t *testing.T) { } func TestErrContainerNameNotSet(t *testing.T) { + t.Parallel() if ErrContainerNameNotSet == nil { t.Error("ErrContainerNameNotSet should not be nil") } @@ -47,4 +49,4 @@ func TestErrContainerNameNotSet(t *testing.T) { if !errors.Is(wrappedErr, ErrContainerNameNotSet) { t.Error("Wrapped error should still match ErrContainerNameNotSet") } -} \ No newline at end of file +} diff --git a/pkg/versions/version_test.go b/pkg/versions/version_test.go index f05aef97d..3ca2ad3fa 100644 --- a/pkg/versions/version_test.go +++ b/pkg/versions/version_test.go @@ -7,7 +7,8 @@ import ( "testing" ) -func TestGetVersionInfo(t *testing.T) { +func TestGetVersionInfo(t *testing.T) { //nolint:paralleltest // Modifies global variables + // Cannot run in parallel because it modifies global variables // Save original values origVersion := Version origCommit := Commit @@ -101,8 +102,9 @@ func TestGetVersionInfo(t *testing.T) { }, } - for _, tt := range tests { + for _, tt := range tests { //nolint:paralleltest // Test modifies global variables t.Run(tt.name, func(t *testing.T) { + // Cannot run in parallel because parent test modifies global variables // Set test values Version = tt.version Commit = tt.commit @@ -123,6 +125,7 @@ func TestGetVersionInfo(t *testing.T) { } func TestVersionInfo_Fields(t *testing.T) { + t.Parallel() vi := VersionInfo{ Version: "test-version", Commit: "test-commit", @@ -146,4 +149,4 @@ func TestVersionInfo_Fields(t *testing.T) { if vi.Platform != "test-platform" { t.Errorf("Platform = %v, want %v", vi.Platform, "test-platform") } -} \ No newline at end of file +}