forked from codeGROOVE-dev/ds9
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmultierror_test.go
More file actions
322 lines (266 loc) · 8.35 KB
/
multierror_test.go
File metadata and controls
322 lines (266 loc) · 8.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
package datastore_test
import (
"context"
"errors"
"testing"
"github.com/codeGROOVE-dev/ds9/pkg/datastore"
)
// TestMultiErrorGetMulti tests that GetMulti returns MultiError with per-item errors
func TestMultiErrorGetMulti(t *testing.T) {
client, cleanup := datastore.NewMockClient(t)
defer cleanup()
ctx := context.Background()
// Create some test entities
type TestEntity struct {
Name string
Age int
}
key1 := datastore.NameKey("TestEntity", "exists1", nil)
key2 := datastore.NameKey("TestEntity", "notfound", nil)
key3 := datastore.NameKey("TestEntity", "exists2", nil)
// Put only key1 and key3
entity1 := &TestEntity{Name: "Alice", Age: 30}
entity3 := &TestEntity{Name: "Charlie", Age: 35}
if _, err := client.Put(ctx, key1, entity1); err != nil {
t.Fatalf("Put failed: %v", err)
}
if _, err := client.Put(ctx, key3, entity3); err != nil {
t.Fatalf("Put failed: %v", err)
}
// GetMulti with missing key
keys := []*datastore.Key{key1, key2, key3}
dst := make([]TestEntity, len(keys))
err := client.GetMulti(ctx, keys, &dst)
if err == nil {
t.Fatal("Expected error for missing entity, got nil")
}
// Check that it's a MultiError
var multiErr datastore.MultiError
ok := errors.As(err, &multiErr)
if !ok {
t.Fatalf("Expected MultiError, got %T: %v", err, err)
}
// Verify the MultiError has correct length
if len(multiErr) != len(keys) {
t.Errorf("Expected MultiError length %d, got %d", len(keys), len(multiErr))
}
// Verify individual errors
if multiErr[0] != nil {
t.Errorf("Expected no error for key1, got: %v", multiErr[0])
}
if !errors.Is(multiErr[1], datastore.ErrNoSuchEntity) {
t.Errorf("Expected ErrNoSuchEntity for key2, got: %v", multiErr[1])
}
if multiErr[2] != nil {
t.Errorf("Expected no error for key3, got: %v", multiErr[2])
}
// Verify successful entities were decoded
if dst[0].Name != "Alice" {
t.Errorf("Expected dst[0].Name = 'Alice', got %q", dst[0].Name)
}
if dst[2].Name != "Charlie" {
t.Errorf("Expected dst[2].Name = 'Charlie', got %q", dst[2].Name)
}
}
// TestMultiErrorGetMulti_AllMissing tests GetMulti when all keys are missing
func TestMultiErrorGetMulti_AllMissing(t *testing.T) {
client, cleanup := datastore.NewMockClient(t)
defer cleanup()
ctx := context.Background()
type TestEntity struct {
Name string
}
keys := []*datastore.Key{
datastore.NameKey("TestEntity", "missing1", nil),
datastore.NameKey("TestEntity", "missing2", nil),
}
dst := make([]TestEntity, len(keys))
err := client.GetMulti(ctx, keys, &dst)
if err == nil {
t.Fatal("Expected error for missing entities, got nil")
}
var multiErr datastore.MultiError
ok := errors.As(err, &multiErr)
if !ok {
t.Fatalf("Expected MultiError, got %T", err)
}
for i, e := range multiErr {
if !errors.Is(e, datastore.ErrNoSuchEntity) {
t.Errorf("Expected ErrNoSuchEntity at index %d, got: %v", i, e)
}
}
}
// TestMultiErrorGetMulti_NilKeys tests GetMulti with nil keys
func TestMultiErrorGetMulti_NilKeys(t *testing.T) {
client, cleanup := datastore.NewMockClient(t)
defer cleanup()
ctx := context.Background()
type TestEntity struct {
Name string
}
key1 := datastore.NameKey("TestEntity", "valid", nil)
keys := []*datastore.Key{key1, nil, datastore.NameKey("TestEntity", "valid2", nil)}
dst := make([]TestEntity, len(keys))
err := client.GetMulti(ctx, keys, &dst)
if err == nil {
t.Fatal("Expected error for nil key, got nil")
}
var multiErr datastore.MultiError
ok := errors.As(err, &multiErr)
if !ok {
t.Fatalf("Expected MultiError, got %T", err)
}
if multiErr[0] != nil {
t.Errorf("Expected no error for key[0], got: %v", multiErr[0])
}
if multiErr[1] == nil {
t.Error("Expected error for nil key at index 1")
} else if !errors.Is(multiErr[1], datastore.ErrInvalidKey) {
t.Errorf("Expected ErrInvalidKey for nil key, got: %v", multiErr[1])
}
if multiErr[2] != nil {
t.Errorf("Expected no error for key[2], got: %v", multiErr[2])
}
}
// TestMultiErrorPutMulti tests that PutMulti returns MultiError for encoding errors
func TestMultiErrorPutMulti(t *testing.T) {
client, cleanup := datastore.NewMockClient(t)
defer cleanup()
ctx := context.Background()
type TestEntity struct {
Name string
}
key1 := datastore.NameKey("TestEntity", "valid1", nil)
key2 := datastore.NameKey("TestEntity", "valid2", nil)
keys := []*datastore.Key{key1, nil, key2}
entitiesWithNil := []TestEntity{
{Name: "Alice"},
{Name: "Bob"},
{Name: "Charlie"},
}
// Try to put with a nil key
_, err := client.PutMulti(ctx, keys, entitiesWithNil)
if err == nil {
t.Fatal("Expected error for nil key, got nil")
}
var multiErr datastore.MultiError
ok := errors.As(err, &multiErr)
if !ok {
t.Fatalf("Expected MultiError, got %T: %v", err, err)
}
if len(multiErr) != len(keys) {
t.Errorf("Expected MultiError length %d, got %d", len(keys), len(multiErr))
}
if multiErr[0] != nil {
t.Errorf("Expected no error for key[0], got: %v", multiErr[0])
}
if !errors.Is(multiErr[1], datastore.ErrInvalidKey) {
t.Errorf("Expected ErrInvalidKey for nil key, got: %v", multiErr[1])
}
if multiErr[2] != nil {
t.Errorf("Expected no error for key[2], got: %v", multiErr[2])
}
}
// TestMultiErrorDeleteMulti tests that DeleteMulti returns MultiError for invalid keys
func TestMultiErrorDeleteMulti(t *testing.T) {
client, cleanup := datastore.NewMockClient(t)
defer cleanup()
ctx := context.Background()
key1 := datastore.NameKey("TestEntity", "valid1", nil)
key2 := datastore.NameKey("TestEntity", "valid2", nil)
keys := []*datastore.Key{key1, nil, key2}
err := client.DeleteMulti(ctx, keys)
if err == nil {
t.Fatal("Expected error for nil key, got nil")
}
var multiErr datastore.MultiError
ok := errors.As(err, &multiErr)
if !ok {
t.Fatalf("Expected MultiError, got %T", err)
}
if len(multiErr) != len(keys) {
t.Errorf("Expected MultiError length %d, got %d", len(keys), len(multiErr))
}
if multiErr[0] != nil {
t.Errorf("Expected no error for key[0], got: %v", multiErr[0])
}
if !errors.Is(multiErr[1], datastore.ErrInvalidKey) {
t.Errorf("Expected ErrInvalidKey for nil key, got: %v", multiErr[1])
}
if multiErr[2] != nil {
t.Errorf("Expected no error for key[2], got: %v", multiErr[2])
}
}
// TestMultiErrorFormatting tests the MultiError.Error() method
func TestMultiErrorFormatting(t *testing.T) {
tests := []struct {
name string
err datastore.MultiError
expected string
}{
{
name: "zero errors",
err: datastore.MultiError{nil, nil},
expected: "(0 errors)",
},
{
name: "one error",
err: datastore.MultiError{errors.New("first error"), nil},
expected: "first error",
},
{
name: "two errors",
err: datastore.MultiError{errors.New("first error"), errors.New("second error")},
expected: "first error (and 1 other error)",
},
{
name: "three errors",
err: datastore.MultiError{errors.New("first error"), errors.New("second error"), errors.New("third error")},
expected: "first error (and 2 other errors)",
},
{
name: "mixed nil and errors",
err: datastore.MultiError{nil, errors.New("second error"), nil, errors.New("fourth error")},
expected: "second error (and 1 other error)",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := tt.err.Error()
if result != tt.expected {
t.Errorf("Expected %q, got %q", tt.expected, result)
}
})
}
}
// TestMultiErrorGetMulti_Success tests that no error is returned when all gets succeed
func TestMultiErrorGetMulti_Success(t *testing.T) {
client, cleanup := datastore.NewMockClient(t)
defer cleanup()
ctx := context.Background()
type TestEntity struct {
Name string
}
key1 := datastore.NameKey("TestEntity", "exists1", nil)
key2 := datastore.NameKey("TestEntity", "exists2", nil)
entity1 := &TestEntity{Name: "Alice"}
entity2 := &TestEntity{Name: "Bob"}
if _, err := client.Put(ctx, key1, entity1); err != nil {
t.Fatalf("Put failed: %v", err)
}
if _, err := client.Put(ctx, key2, entity2); err != nil {
t.Fatalf("Put failed: %v", err)
}
keys := []*datastore.Key{key1, key2}
dst := make([]TestEntity, len(keys))
err := client.GetMulti(ctx, keys, &dst)
if err != nil {
t.Errorf("Expected no error, got: %v", err)
}
if dst[0].Name != "Alice" {
t.Errorf("Expected dst[0].Name = 'Alice', got %q", dst[0].Name)
}
if dst[1].Name != "Bob" {
t.Errorf("Expected dst[1].Name = 'Bob', got %q", dst[1].Name)
}
}