Skip to content

Commit 525db1b

Browse files
authored
Merge pull request #8 from tstromberg/main
Add missing logo png's & multierror_test
2 parents a9230b1 + 82f23e7 commit 525db1b

File tree

4 files changed

+322
-0
lines changed

4 files changed

+322
-0
lines changed

go.sum

Whitespace-only changes.

media/logo-small.png

24 KB
Loading

media/logo.png

91.2 KB
Loading

pkg/datastore/multierror_test.go

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

0 commit comments

Comments
 (0)