errs_test.gno

4.63 Kb ยท 220 lines
  1package errs
  2
  3import (
  4	"testing"
  5)
  6
  7// testError is a simple error implementation for testing
  8type testError struct {
  9	msg string
 10}
 11
 12func (e *testError) Error() string {
 13	return e.msg
 14}
 15
 16func newError(msg string) error {
 17	return &testError{msg: msg}
 18}
 19
 20func TestCombine(t *testing.T) {
 21	tests := []struct {
 22		name     string
 23		errors   []error
 24		expected string
 25	}{
 26		{
 27			name:     "single error",
 28			errors:   []error{newError("error1"), nil},
 29			expected: "error1",
 30		},
 31		{
 32			name:     "multiple errors",
 33			errors:   []error{newError("error1"), newError("error2"), newError("error3")},
 34			expected: "error1; error2; error3",
 35		},
 36		{
 37			name:     "mixed nil and non-nil",
 38			errors:   []error{nil, newError("error1"), nil, newError("error2")},
 39			expected: "error1; error2",
 40		},
 41		{
 42			name:     "both nil (2)",
 43			errors:   []error{nil, nil},
 44			expected: "",
 45		},
 46		{
 47			name:     "first nil (2)",
 48			errors:   []error{nil, newError("error2")},
 49			expected: "error2",
 50		},
 51		{
 52			name:     "second nil (2)",
 53			errors:   []error{newError("error1"), nil},
 54			expected: "error1",
 55		},
 56		{
 57			name:     "both non-nil (2)",
 58			errors:   []error{newError("error1"), newError("error2")},
 59			expected: "error1; error2",
 60		},
 61	}
 62
 63	for _, tt := range tests {
 64		err := Combine(tt.errors...)
 65		if tt.expected == "" {
 66			if err != nil {
 67				t.Errorf("%s: expected nil error, got %v", tt.name, err)
 68			}
 69			continue
 70		}
 71
 72		if err == nil {
 73			t.Errorf("%s: expected non-nil error", tt.name)
 74			continue
 75		}
 76
 77		if got := err.Error(); got != tt.expected {
 78			t.Errorf("%s: expected %q, got %q", tt.name, tt.expected, got)
 79		}
 80	}
 81}
 82
 83func TestErrors(t *testing.T) {
 84	err1 := newError("error1")
 85	err2 := newError("error2")
 86	combined := Combine(err1, err2)
 87
 88	tests := []struct {
 89		name          string
 90		err           error
 91		expectedCount int
 92	}{
 93		{
 94			name:          "nil error",
 95			err:           nil,
 96			expectedCount: 0,
 97		},
 98		{
 99			name:          "single error",
100			err:           err1,
101			expectedCount: 1,
102		},
103		{
104			name:          "multiple errors",
105			err:           combined,
106			expectedCount: 2,
107		},
108	}
109
110	for _, tt := range tests {
111		errs := Errors(tt.err)
112		if len(errs) != tt.expectedCount {
113			t.Errorf("%s: expected %d errors, got %d", tt.name, tt.expectedCount, len(errs))
114		}
115	}
116}
117
118func TestMultiErrorString(t *testing.T) {
119	tests := []struct {
120		name     string
121		errors   []error
122		expected string
123	}{
124		{
125			name:     "nil errors",
126			errors:   nil,
127			expected: "",
128		},
129		{
130			name:     "empty errors",
131			errors:   []error{},
132			expected: "",
133		},
134		{
135			name:     "single error",
136			errors:   []error{newError("error1")},
137			expected: "the following errors occurred:\n -  error1",
138		},
139		{
140			name:     "multiple errors",
141			errors:   []error{newError("error1"), newError("error2")},
142			expected: "the following errors occurred:\n -  error1\n -  error2",
143		},
144	}
145
146	for _, tt := range tests {
147		t.Run(tt.name, func(t *testing.T) {
148			merr := &multiError{errors: tt.errors}
149			if got := merr.String(); got != tt.expected {
150				t.Errorf("multiError.String() = %q, want %q", got, tt.expected)
151			}
152		})
153	}
154}
155
156func TestCombineEdgeCases(t *testing.T) {
157	err1 := newError("error1")
158	err2 := newError("error2")
159	err3 := newError("error3")
160
161	merr := Combine(err1, err2)
162
163	tests := []struct {
164		name     string
165		errors   []error
166		expected string
167	}{
168		{
169			name:     "append to multiError",
170			errors:   []error{merr, err3},
171			expected: "error1; error2; error3",
172		},
173		{
174			name:     "prepend to multiError",
175			errors:   []error{err3, merr},
176			expected: "error3; error1; error2",
177		},
178	}
179
180	for _, tt := range tests {
181		t.Run(tt.name, func(t *testing.T) {
182			err := Combine(tt.errors...)
183			if got := err.Error(); got != tt.expected {
184				t.Errorf("Combine() = %q, want %q", got, tt.expected)
185			}
186		})
187	}
188}
189
190func TestUnwrapNilReceiver(t *testing.T) {
191	var merr *multiError
192	errs := merr.Unwrap()
193	if errs != nil {
194		t.Errorf("Expected nil slice for nil receiver, got %v", errs)
195	}
196}
197
198func TestMultiErrorUnwrap(t *testing.T) {
199	var nilMulti *multiError
200	if got := nilMulti.Unwrap(); got != nil {
201		t.Errorf("Unwrap on nil receiver: expected nil, got %v", got)
202	}
203
204	empty := &multiError{errors: nil}
205	if got := empty.Unwrap(); got != nil {
206		t.Errorf("Unwrap on empty: expected nil, got %v", got)
207	}
208
209	single := &multiError{errors: []error{newError("foo")}}
210	got := single.Unwrap()
211	if len(got) != 1 || got[0].Error() != "foo" {
212		t.Errorf("Unwrap on single: expected [foo], got %v", got)
213	}
214
215	multi := &multiError{errors: []error{newError("foo"), newError("bar")}}
216	got = multi.Unwrap()
217	if len(got) != 2 || got[0].Error() != "foo" || got[1].Error() != "bar" {
218		t.Errorf("Unwrap on multi: expected [foo bar], got %v", got)
219	}
220}