Files
onix/pkg/plugin/implementation/registry/registry_test.go
2025-09-19 12:29:25 +05:30

205 lines
5.8 KiB
Go

package registry
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/beckn-one/beckn-onix/pkg/model"
)
// TestValidate ensures the config validation logic works correctly.
func TestValidate(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
config *Config
expectedErr string
}{
{
name: "should return error for nil config",
config: nil,
expectedErr: "registry config cannot be nil",
},
{
name: "should return error for empty URL",
config: &Config{URL: ""},
expectedErr: "registry URL cannot be empty",
},
{
name: "should succeed for valid config",
config: &Config{URL: "http://localhost:8080"},
expectedErr: "",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := validate(tc.config)
if tc.expectedErr != "" {
if err == nil {
t.Fatalf("expected an error but got none")
}
if err.Error() != tc.expectedErr {
t.Errorf("expected error message '%s', but got '%s'", tc.expectedErr, err.Error())
}
} else {
if err != nil {
t.Fatalf("expected no error, but got: %v", err)
}
}
})
}
}
// TestNew tests the constructor for the RegistryClient.
func TestNew(t *testing.T) {
t.Parallel()
t.Run("should fail with invalid config", func(t *testing.T) {
_, _, err := New(context.Background(), &Config{URL: ""})
if err == nil {
t.Fatal("expected an error for invalid config but got none")
}
})
t.Run("should succeed with valid config and set defaults", func(t *testing.T) {
cfg := &Config{URL: "http://test.com"}
client, closer, err := New(context.Background(), cfg)
if err != nil {
t.Fatalf("expected no error, but got: %v", err)
}
if client == nil {
t.Fatal("expected client to be non-nil")
}
if closer == nil {
t.Fatal("expected closer to be non-nil")
}
// Check if default retry settings are applied (go-retryablehttp defaults)
if client.client.RetryMax != 4 {
t.Errorf("expected default RetryMax of 4, but got %d", client.client.RetryMax)
}
})
t.Run("should apply custom retry settings", func(t *testing.T) {
cfg := &Config{
URL: "http://test.com",
RetryMax: 10,
RetryWaitMin: 100 * time.Millisecond,
RetryWaitMax: 1 * time.Second,
}
client, _, err := New(context.Background(), cfg)
if err != nil {
t.Fatalf("expected no error, but got: %v", err)
}
if client.client.RetryMax != cfg.RetryMax {
t.Errorf("expected RetryMax to be %d, but got %d", cfg.RetryMax, client.client.RetryMax)
}
if client.client.RetryWaitMin != cfg.RetryWaitMin {
t.Errorf("expected RetryWaitMin to be %v, but got %v", cfg.RetryWaitMin, client.client.RetryWaitMin)
}
if client.client.RetryWaitMax != cfg.RetryWaitMax {
t.Errorf("expected RetryWaitMax to be %v, but got %v", cfg.RetryWaitMax, client.client.RetryWaitMax)
}
})
}
// TestRegistryClient_Lookup tests the Lookup method.
func TestRegistryClient_Lookup(t *testing.T) {
t.Parallel()
t.Run("should succeed and unmarshal response", func(t *testing.T) {
expectedSubs := []model.Subscription{
{
KeyID: "test-key",
SigningPublicKey: "test-signing-key",
EncrPublicKey: "test-encryption-key",
ValidFrom: time.Now(),
ValidUntil: time.Now().Add(24 * time.Hour),
Status: "SUBSCRIBED",
},
{
KeyID: "test-key-2",
SigningPublicKey: "test-signing-key-2",
EncrPublicKey: "test-encryption-key-2",
ValidFrom: time.Now(),
ValidUntil: time.Now().Add(48 * time.Hour),
Status: "SUBSCRIBED",
},
}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/lookup" {
t.Errorf("expected path '/lookup', got '%s'", r.URL.Path)
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(expectedSubs); err != nil {
t.Fatalf("failed to write response: %v", err)
}
}))
defer server.Close()
client, closer, err := New(context.Background(), &Config{URL: server.URL})
if err != nil {
t.Fatalf("failed to create client: %v", err)
}
defer closer()
results, err := client.Lookup(context.Background(), &model.Subscription{})
if err != nil {
t.Fatalf("lookup failed: %v", err)
}
if len(results) != len(expectedSubs) {
t.Fatalf("expected %d results, but got %d", len(expectedSubs), len(results))
}
if results[0].SubscriberID != expectedSubs[0].SubscriberID {
t.Errorf("expected subscriber ID '%s', got '%s'", expectedSubs[0].SubscriberID, results[0].SubscriberID)
}
})
t.Run("should fail on non-200 status", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadRequest)
}))
defer server.Close()
client, closer, err := New(context.Background(), &Config{URL: server.URL})
if err != nil {
t.Fatalf("failed to create client: %v", err)
}
defer closer()
_, err = client.Lookup(context.Background(), &model.Subscription{})
if err == nil {
t.Fatal("expected an error but got none")
}
})
t.Run("should fail on bad JSON response", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, `[{"subscriber_id": "bad-json"`) // Malformed JSON
}))
defer server.Close()
client, closer, err := New(context.Background(), &Config{URL: server.URL, RetryMax: 1})
if err != nil {
t.Fatalf("failed to create client: %v", err)
}
defer closer()
_, err = client.Lookup(context.Background(), &model.Subscription{})
if err == nil {
t.Fatal("expected an unmarshaling error but got none")
}
})
}