Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Just switch the import path from `cloud.google.com/go/datastore` to `github.com/

These features are unsupported just because we haven't found a use for the feature yet. PRs welcome:

* Embedded structs, nested slices, map types, some advanced query features (streaming aggregations, OR filters).
* Nested slices, map types, some advanced query features (streaming aggregations, OR filters).

## Testing

Expand Down
94 changes: 94 additions & 0 deletions pkg/datastore/batch_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package datastore_test

import (
"context"
"fmt"
"testing"

"github.com/codeGROOVE-dev/ds9/pkg/datastore"
)

func TestBatchOperations(t *testing.T) {
client, cleanup := datastore.NewMockClient(t)
defer cleanup()

ctx := context.Background()

type Item struct {
ID int
}

// Number of items > 1000 to test batching limits
// Put limit: 500, Get limit: 1000
const count = 1200
keys := make([]*datastore.Key, count)
items := make([]Item, count)

for i := range count {
keys[i] = datastore.NameKey("Item", fmt.Sprintf("item-%d", i), nil)
items[i] = Item{ID: i}
}

// Test PutMulti
if _, err := client.PutMulti(ctx, keys, items); err != nil {
t.Fatalf("PutMulti failed: %v", err)
}

// Test GetMulti
results := make([]Item, count)
if err := client.GetMulti(ctx, keys, &results); err != nil {
t.Fatalf("GetMulti failed: %v", err)
}

for i := range count {
if results[i].ID != i {
t.Errorf("Item %d mismatch: got %d, want %d", i, results[i].ID, i)
}
}

// Test DeleteMulti
if err := client.DeleteMulti(ctx, keys); err != nil {
t.Fatalf("DeleteMulti failed: %v", err)
}

// Verify deletion
err := client.GetMulti(ctx, keys, &results)
// Should return MultiError with all ErrNoSuchEntity
if err == nil {
t.Fatal("Expected error after deletion, got nil")
}
}

func TestAllocateIDsBatch(t *testing.T) {
client, cleanup := datastore.NewMockClient(t)
defer cleanup()

ctx := context.Background()

// Test AllocateIDs > 500
const count = 600
keys := make([]*datastore.Key, count)
for i := range count {
keys[i] = datastore.IncompleteKey("Item", nil)
}

allocated, err := client.AllocateIDs(ctx, keys)
if err != nil {
t.Fatalf("AllocateIDs failed: %v", err)
}

if len(allocated) != count {
t.Fatalf("Expected %d keys, got %d", count, len(allocated))
}

seen := make(map[int64]bool)
for i, k := range allocated {
if k.Incomplete() {
t.Errorf("Key %d is incomplete", i)
}
if seen[k.ID] {
t.Errorf("Duplicate ID %d at index %d", k.ID, i)
}
seen[k.ID] = true
}
}
19 changes: 8 additions & 11 deletions pkg/datastore/encode_coverage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ func TestEncodeValue_ReflectionSlices(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := encodeValue(tt.value)
result, err := encodeAny(tt.value)
if err != nil {
t.Errorf("encodeValue(%v) failed: %v", tt.value, err)
t.Errorf("encodeAny(%v) failed: %v", tt.value, err)
}
if result == nil {
t.Error("Expected non-nil result")
Expand All @@ -63,17 +63,14 @@ func TestEncodeValue_Errors(t *testing.T) {
"channel type",
make(chan int),
},
{
"struct type",
struct{ Name string }{Name: "test"},
},
// Note: struct types are now supported as nested entities
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := encodeValue(tt.value)
_, err := encodeAny(tt.value)
if err == nil {
t.Errorf("encodeValue(%T) should have returned an error", tt.value)
t.Errorf("encodeAny(%T) should have returned an error", tt.value)
}
})
}
Expand All @@ -86,7 +83,7 @@ func TestEncodeValue_TimeSlice(t *testing.T) {

timeSlice := []time.Time{now, later}

result, err := encodeValue(timeSlice)
result, err := encodeAny(timeSlice)
if err != nil {
t.Fatalf("encodeValue failed for time slice: %v", err)
}
Expand Down Expand Up @@ -122,7 +119,7 @@ func TestEncodeValue_EmptySlices(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := encodeValue(tt.value)
result, err := encodeAny(tt.value)
if err != nil {
t.Errorf("encodeValue failed: %v", err)
}
Expand All @@ -148,7 +145,7 @@ func TestEncodeValue_SingleElementSlices(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := encodeValue(tt.value)
result, err := encodeAny(tt.value)
if err != nil {
t.Errorf("encodeValue failed: %v", err)
}
Expand Down
Loading