package services import ( "context" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" api "edge-infra.dev/pkg/edge/device-registrar/api/v1alpha1" ) func injectmockClientDiscover(router *gin.Engine, mockClient client.Client, t *testing.T) { router.Use( // Inject the mock client into the context func(c *gin.Context) { c.Set("k8sClient", mockClient) c.Next() k8sClient, exists := c.Get("k8sClient") // Assert that k8sClient is not nil and exists assert.True(t, exists, "k8sClient should exist in the context") assert.NotNil(t, k8sClient, "k8sClient should not be nil") }, ) } func TestDiscovery(t *testing.T) { router, scheme := setupTest() discovery := api.Discovery{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "device-registrar-clients", }, Spec: api.DiscoverySpec{ Name: "example-discovery", URL: "example-url.com/config", }, } device := api.ExternalDevice{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "device-registrar-clients", }, Spec: api.ExternalDeviceSpec{ SN: "my-serial-number", Name: "test-device-name", }, } mockClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&discovery, &device).Build() injectmockClientDiscover(router, mockClient, t) // register endpoint router.GET("/discover/:serviceName", DiscoverService) // Create a new HTTP request without a payload req, _ := http.NewRequest(http.MethodGet, "/discover/example-discovery", nil) req.Header.Set("X-Client-DN", "OU=urn:storeID:my-store-id=urn:deviceName:test-device-name+OU=urn:SN:my-serial-number") w := httptest.NewRecorder() router.ServeHTTP(w, req) // status code 200 assert.Equal(t, http.StatusOK, w.Code, "Expected status code 200") assert.Contains(t, w.Body.String(), "name") assert.Contains(t, w.Body.String(), "url") assert.Equal(t, w.Body.String(), `{"name":"example-discovery","url":"example-url.com/config"}`) } func TestNoDiscovery(t *testing.T) { router, scheme := setupTest() device := api.ExternalDevice{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "device-registrar-clients", }, Spec: api.ExternalDeviceSpec{ SN: "my-serial-number", Name: "test-device-name", }, } mockClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&device).Build() injectmockClientDiscover(router, mockClient, t) // register endpoint router.GET("/discover/:serviceName", DiscoverService) // Create a new HTTP request without a payload req, _ := http.NewRequest(http.MethodGet, "/discover/example-discovery", nil) req.Header.Set("X-Client-DN", "OU=urn:storeID:my-store-id=urn:deviceName:test-device-name+OU=urn:SN:my-serial-number") w := httptest.NewRecorder() router.ServeHTTP(w, req) // status code 200 assert.Equal(t, http.StatusOK, w.Code, "Expected status code 200") assert.Contains(t, w.Body.String(), "name") assert.Contains(t, w.Body.String(), "url") assert.Equal(t, w.Body.String(), `{"name":"example-discovery","url":null}`) } func TestMissingServiceName(t *testing.T) { router, scheme := setupTest() device := api.ExternalDevice{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "device-registrar-clients", }, Spec: api.ExternalDeviceSpec{ SN: "my-serial-number", Name: "test-device-name", }, } mockClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&device).Build() injectmockClientDiscover(router, mockClient, t) // register endpoint router.GET("/discover/:serviceName", DiscoverService) // Create a new HTTP request without a payload req, _ := http.NewRequest(http.MethodGet, "/discover/", nil) req.Header.Set("X-Client-DN", "OU=urn:storeID:my-store-id=urn:deviceName:test-device-name+OU=urn:SN:my-serial-number") w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, w.Body.String(), "404 page not found") } func TestEmptyDiscoveryList(t *testing.T) { router, scheme := setupTest() device := api.ExternalDevice{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "device-registrar-clients", }, Spec: api.ExternalDeviceSpec{ SN: "my-serial-number", Name: "test-device-name", }, } mockClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&device).Build() injectmockClientDiscover(router, mockClient, t) // register endpoint router.GET("/discover/:serviceName", DiscoverService) req, _ := http.NewRequest(http.MethodGet, "/discover/example-discovery", nil) req.Header.Set("X-Client-DN", "OU=urn:storeID:my-store-id=urn:deviceName:test-device-name+OU=urn:SN:my-serial-number") w := httptest.NewRecorder() router.ServeHTTP(w, req) // status code 200 assert.Equal(t, http.StatusOK, w.Code, "Expected status code 200") assert.Equal(t, w.Body.String(), `{"name":"example-discovery","url":null}`) } func TestDiscoveryNoHeader(t *testing.T) { router, scheme := setupTest() mockClient := fake.NewClientBuilder().WithScheme(scheme).Build() injectmockClientDiscover(router, mockClient, t) // register endpoint router.GET("/discover/:serviceName", DiscoverService) // Create a new HTTP request without a payload req, _ := http.NewRequest(http.MethodGet, "/discover/example-discovery", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) // status code 401 assert.Equal(t, http.StatusUnauthorized, w.Code, "Expected status code 401") assert.Equal(t, w.Body.String(), `{"error":"X-Client-DN is required"}`) } func TestDiscoveryIncorrectSN(t *testing.T) { router, scheme := setupTest() device := api.ExternalDevice{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "device-registrar-clients", }, Spec: api.ExternalDeviceSpec{ SN: "my-serial-number-different", Name: "test-device-name", }, } mockClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&device).Build() injectmockClientDiscover(router, mockClient, t) // register endpoint router.GET("/discover/:serviceName", DiscoverService) // Create a new HTTP request without a payload req, _ := http.NewRequest(http.MethodGet, "/discover/example-discovery", nil) req.Header.Set("X-Client-DN", "OU=urn:storeID:my-store-id=urn:deviceName:test-device-name+OU=urn:SN:my-serial-number") w := httptest.NewRecorder() router.ServeHTTP(w, req) // status code 401 assert.Equal(t, http.StatusUnauthorized, w.Code, "Expected status code 401") assert.Equal(t, w.Body.String(), `{"error":"Unauthorized Serial Number"}`) } func TestDiscoveryNoSN(t *testing.T) { router, scheme := setupTest() mockClient := fake.NewClientBuilder().WithScheme(scheme).Build() injectmockClientDiscover(router, mockClient, t) // register endpoint router.GET("/discover/:serviceName", DiscoverService) // Create a new HTTP request without a payload req, _ := http.NewRequest(http.MethodGet, "/discover/example-discovery", nil) req.Header.Set("X-Client-DN", "OU=urn:storeID:my-store-id=urn:deviceName:test-device-name") w := httptest.NewRecorder() router.ServeHTTP(w, req) // status code 401 assert.Equal(t, http.StatusUnauthorized, w.Code, "Expected status code 401") assert.Equal(t, w.Body.String(), `{"error":"Serial Number is required in X-Client-DN"}`) } func TestParseSN(t *testing.T) { sn := parseSerialNumber("OU=urn:storeID:my-store-id+OU=urn:deviceName:test-device-name+OU=urn:SN:a1b2c3d4") assert.Equal(t, sn, "a1b2c3d4") } func TestIsSNAuthorized(t *testing.T) { _, scheme := setupTest() device := api.ExternalDevice{ ObjectMeta: metav1.ObjectMeta{ Name: "example", Namespace: "device-registrar-clients", }, Spec: api.ExternalDeviceSpec{ SN: "my-serial-number", Name: "test-device-name", }, } ctx := context.Background() mockClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&device).Build() assert.True(t, isSNAuthorized(ctx, mockClient, "my-serial-number")) assert.False(t, isSNAuthorized(ctx, mockClient, "different-serial-number")) }