119 lines
3.2 KiB
Go
119 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
messages "git.tornberg.me/go-cart-actor/proto"
|
|
"google.golang.org/grpc"
|
|
)
|
|
|
|
// TestCartActorMutationAndState validates end-to-end gRPC mutation + state retrieval
|
|
// against a locally started gRPC server (single-node scenario).
|
|
// This test uses the oneof MutationEnvelope directly to avoid hitting external product
|
|
// fetching logic (FetchItem) which would require network I/O.
|
|
func TestCartActorMutationAndState(t *testing.T) {
|
|
// Setup local grain pool + synced pool (no discovery, single host)
|
|
pool := NewGrainLocalPool(1024, time.Minute, spawn)
|
|
synced, err := NewSyncedPool(pool, "127.0.0.1", nil)
|
|
if err != nil {
|
|
t.Fatalf("NewSyncedPool error: %v", err)
|
|
}
|
|
|
|
// Start gRPC server (CartActor + ControlPlane) on :1337
|
|
grpcSrv, err := StartGRPCServer(":1337", pool, synced)
|
|
if err != nil {
|
|
t.Fatalf("StartGRPCServer error: %v", err)
|
|
}
|
|
defer grpcSrv.GracefulStop()
|
|
|
|
// Dial the local server
|
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
defer cancel()
|
|
conn, err := grpc.DialContext(ctx, "127.0.0.1:1337",
|
|
grpc.WithInsecure(),
|
|
grpc.WithBlock(),
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("grpc.Dial error: %v", err)
|
|
}
|
|
defer conn.Close()
|
|
|
|
cartClient := messages.NewCartActorClient(conn)
|
|
|
|
// Create a short cart id (<=16 chars so it fits into the fixed CartId 16-byte array cleanly)
|
|
cartID := fmt.Sprintf("cart-%d", time.Now().UnixNano())
|
|
|
|
// Build an AddItem payload (bypasses FetchItem to keep test deterministic)
|
|
addItem := &messages.AddItem{
|
|
ItemId: 1,
|
|
Quantity: 1,
|
|
Price: 1000,
|
|
OrgPrice: 1000,
|
|
Sku: "test-sku",
|
|
Name: "Test SKU",
|
|
Image: "/img.png",
|
|
Stock: 2, // InStock
|
|
Tax: 2500,
|
|
Country: "se",
|
|
}
|
|
|
|
// Build oneof envelope directly (no legacy handler/enum)
|
|
envelope := &messages.MutationEnvelope{
|
|
CartId: cartID,
|
|
ClientTimestamp: time.Now().Unix(),
|
|
Mutation: &messages.MutationEnvelope_AddItem{
|
|
AddItem: addItem,
|
|
},
|
|
}
|
|
|
|
// Issue Mutate RPC
|
|
mutResp, err := cartClient.Mutate(context.Background(), envelope)
|
|
if err != nil {
|
|
t.Fatalf("Mutate RPC error: %v", err)
|
|
}
|
|
if mutResp.StatusCode != 200 {
|
|
t.Fatalf("Mutate returned non-200 status: %d, error: %s", mutResp.StatusCode, mutResp.GetError())
|
|
}
|
|
|
|
// Validate the response state
|
|
state := mutResp.GetState()
|
|
if state == nil {
|
|
t.Fatalf("Mutate response state is nil")
|
|
}
|
|
|
|
if len(state.Items) != 1 {
|
|
t.Fatalf("Expected 1 item after mutation, got %d", len(state.Items))
|
|
}
|
|
if state.Items[0].Sku != "test-sku" {
|
|
t.Fatalf("Unexpected item SKU: %s", state.Items[0].Sku)
|
|
}
|
|
|
|
// Issue GetState RPC
|
|
getResp, err := cartClient.GetState(context.Background(), &messages.StateRequest{
|
|
CartId: cartID,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("GetState RPC error: %v", err)
|
|
}
|
|
if getResp.StatusCode != 200 {
|
|
t.Fatalf("GetState returned non-200 status: %d, error: %s", getResp.StatusCode, getResp.GetError())
|
|
}
|
|
|
|
state2 := getResp.GetState()
|
|
if state2 == nil {
|
|
t.Fatalf("GetState response state is nil")
|
|
}
|
|
|
|
if len(state2.Items) != 1 {
|
|
t.Fatalf("Expected 1 item in GetState, got %d", len(state2.Items))
|
|
}
|
|
if state2.Items[0].Sku != "test-sku" {
|
|
t.Fatalf("Unexpected SKU in GetState: %s", state2.Items[0].Sku)
|
|
}
|
|
}
|
|
|
|
// Legacy serialization helper removed (oneof envelope used directly)
|