package cache import ( rpc "buf.build/gen/go/interplex-ai/schemas/grpc/go/protobuf/schema/v1/schemav1grpc" schemav1 "buf.build/gen/go/interplex-ai/schemas/protocolbuffers/go/protobuf/schema/v1" "context" "errors" "google.golang.org/grpc" "net" "testing" ) func TestInterplexCache(t *testing.T) { cache := &InterplexCache{ configuration: InterplexCacheConfiguration{ ConnectionString: "localhost:50051", }, } // Mock GRPC server setup errChan := make(chan error, 1) go func() { lis, err := net.Listen("tcp", ":50051") if err != nil { errChan <- err return } s := grpc.NewServer() rpc.RegisterCacheServiceServer(s, &mockCacheService{}) if err := s.Serve(lis); err != nil { errChan <- err return } }() // Check if server startup failed select { case err := <-errChan: if err != nil { t.Fatalf("failed to start mock server: %v", err) } default: // Server started successfully } t.Run("TestStore", func(t *testing.T) { err := cache.Store("key1", "value1") if err != nil { t.Errorf("Error storing value: %v", err) } }) t.Run("TestLoad", func(t *testing.T) { value, err := cache.Load("key1") if err != nil { t.Errorf("Error loading value: %v", err) } if value != "value1" { t.Errorf("Expected value1, got %v", value) } }) t.Run("TestExists", func(t *testing.T) { exists := cache.Exists("key1") if !exists { t.Errorf("Expected key1 to exist") } }) } // TestInterplexCacheClientError ensures Store and Load return the connection // error instead of panicking when grpc.NewClient fails. On error grpc.NewClient // returns a nil *ClientConn, so a deferred conn.Close() placed before the error // check dereferences nil. func TestInterplexCacheClientError(t *testing.T) { // Store/Load overwrite the connection string with localhost:8084 when // INTERPLEX_LOCAL_MODE is set, which would bypass grpc.NewClient. Pin it empty // so the invalid connection string is exercised regardless of the environment. t.Setenv("INTERPLEX_LOCAL_MODE", "") // An invalid URL escape makes grpc.NewClient fail and return a nil conn. cache := &InterplexCache{ configuration: InterplexCacheConfiguration{ ConnectionString: "dns://%zz", }, } t.Run("Store", func(t *testing.T) { if err := cache.Store("key1", "value1"); err == nil { t.Error("expected an error for an invalid connection string, got nil") } }) t.Run("Load", func(t *testing.T) { if _, err := cache.Load("key1"); err == nil { t.Error("expected an error for an invalid connection string, got nil") } }) } type mockCacheService struct { rpc.UnimplementedCacheServiceServer data map[string]string } func (m *mockCacheService) Set(ctx context.Context, req *schemav1.SetRequest) (*schemav1.SetResponse, error) { if m.data == nil { m.data = make(map[string]string) } m.data[req.Key] = req.Value return &schemav1.SetResponse{}, nil } func (m *mockCacheService) Get(ctx context.Context, req *schemav1.GetRequest) (*schemav1.GetResponse, error) { value, exists := m.data[req.Key] if !exists { return nil, errors.New("key not found") } return &schemav1.GetResponse{Value: value}, nil }