github.com/pelicanplatform/pelican@v1.0.5/namespace_registry/registry_ui_test.go (about) 1 package nsregistry 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/elliptic" 6 "crypto/rand" 7 "encoding/json" 8 "fmt" 9 "net/http" 10 "net/http/httptest" 11 "testing" 12 13 "github.com/gin-gonic/gin" 14 "github.com/lestrrat-go/jwx/v2/jwa" 15 "github.com/lestrrat-go/jwx/v2/jwk" 16 "github.com/pkg/errors" 17 "github.com/stretchr/testify/assert" 18 "github.com/stretchr/testify/require" 19 ) 20 21 func GenerateMockJWKS() (string, error) { 22 // Create a private key to use for the test 23 privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 24 if err != nil { 25 return "", errors.Wrap(err, "Error generating private key") 26 } 27 28 // Convert from raw ecdsa to jwk.Key 29 pKey, err := jwk.FromRaw(privateKey) 30 if err != nil { 31 return "", errors.Wrap(err, "Unable to convert ecdsa.PrivateKey to jwk.Key") 32 } 33 34 //Assign Key id to the private key 35 err = jwk.AssignKeyID(pKey) 36 if err != nil { 37 return "", errors.Wrap(err, "Error assigning kid to private key") 38 } 39 40 //Set an algorithm for the key 41 err = pKey.Set(jwk.AlgorithmKey, jwa.ES256) 42 if err != nil { 43 return "", errors.Wrap(err, "Unable to set algorithm for pKey") 44 } 45 46 publicKey, err := pKey.PublicKey() 47 if err != nil { 48 return "", errors.Wrap(err, "Unable to get the public key from private key") 49 } 50 51 jwks := jwk.NewSet() 52 err = jwks.AddKey(publicKey) 53 if err != nil { 54 return "", errors.Wrap(err, "Unable to add public key to the jwks") 55 } 56 57 jsonData, err := json.MarshalIndent(jwks, "", " ") 58 if err != nil { 59 return "", errors.Wrap(err, "Unable to marshall the json into string") 60 } 61 // Append a new line to the JSON data 62 jsonData = append(jsonData, '\n') 63 64 return string(jsonData), nil 65 } 66 67 func TestListNamespaces(t *testing.T) { 68 // Initialize the mock database 69 err := setupMockNamespaceDB() 70 if err != nil { 71 t.Fatalf("Failed to set up mock namespace DB: %v", err) 72 } 73 defer teardownMockNamespaceDB() 74 75 router := gin.Default() 76 77 router.GET("/namespaces", listNamespaces) 78 79 tests := []struct { 80 description string 81 serverType string 82 expectedCode int 83 emptyDB bool 84 expectedData []Namespace 85 }{ 86 { 87 description: "valid-request-with-empty-db", 88 serverType: string(OriginType), 89 expectedCode: http.StatusOK, 90 emptyDB: true, 91 expectedData: []Namespace{}, 92 }, 93 { 94 description: "valid-request-with-origin-type", 95 serverType: string(OriginType), 96 expectedCode: http.StatusOK, 97 expectedData: mockNssWithOrigins, 98 }, 99 { 100 description: "valid-request-with-cache-type", 101 serverType: string(CacheType), 102 expectedCode: http.StatusOK, 103 expectedData: mockNssWithCaches, 104 }, 105 { 106 description: "valid-request-without-type", 107 serverType: "", 108 expectedCode: http.StatusOK, 109 expectedData: mockNssWithMixed, 110 }, 111 { 112 description: "invalid-request-parameters", 113 serverType: "random_type", // some invalid query string 114 expectedCode: http.StatusBadRequest, 115 expectedData: nil, 116 }, 117 } 118 119 for _, tc := range tests { 120 t.Run(tc.description, func(t *testing.T) { 121 if !tc.emptyDB { 122 err := insertMockDBData(mockNssWithMixed) 123 if err != nil { 124 t.Fatalf("Failed to set up mock data: %v", err) 125 } 126 } 127 defer func() { 128 err := resetNamespaceDB() 129 if err != nil { 130 t.Fatalf("Failed to reset mock namespace DB: %v", err) 131 } 132 }() 133 134 // Create a request to the endpoint 135 w := httptest.NewRecorder() 136 requestURL := "" 137 if tc.serverType != "" { 138 requestURL = "/namespaces?server_type=" + tc.serverType 139 } else { 140 requestURL = "/namespaces" 141 } 142 req, _ := http.NewRequest("GET", requestURL, nil) 143 router.ServeHTTP(w, req) 144 145 // Check the response 146 assert.Equal(t, tc.expectedCode, w.Code) 147 148 if tc.expectedCode == http.StatusOK { 149 var got []Namespace 150 err := json.Unmarshal(w.Body.Bytes(), &got) 151 if err != nil { 152 t.Fatalf("Failed to unmarshal response body: %v", err) 153 } 154 assert.True(t, compareNamespaces(tc.expectedData, got, true), "Response data does not match expected") 155 } 156 }) 157 } 158 } 159 160 func TestGetNamespaceJWKS(t *testing.T) { 161 mockPublicKey, err := GenerateMockJWKS() 162 if err != nil { 163 t.Fatalf("Failed to set up mock public key: %v", err) 164 } 165 // Initialize the mock database 166 err = setupMockNamespaceDB() 167 if err != nil { 168 t.Fatalf("Failed to set up mock namespace DB: %v", err) 169 } 170 defer teardownMockNamespaceDB() 171 172 router := gin.Default() 173 174 router.GET("/test/:id/pubkey", getNamespaceJWKS) 175 176 tests := []struct { 177 description string 178 requestId string 179 expectedCode int 180 emptyDB bool 181 expectedData string 182 }{ 183 { 184 description: "valid-request-with-empty-key", 185 requestId: "1", 186 expectedCode: http.StatusOK, 187 expectedData: mockPublicKey, 188 }, 189 { 190 description: "invalid-request-with-str-id", 191 requestId: "crazy-id", 192 expectedCode: http.StatusBadRequest, 193 expectedData: "", 194 }, 195 { 196 description: "invalid-request-with-0-id", 197 requestId: "0", 198 expectedCode: http.StatusBadRequest, 199 }, 200 { 201 description: "invalid-request-with-neg-id", 202 requestId: "-10000", 203 expectedCode: http.StatusBadRequest, 204 }, 205 { 206 description: "invalid-request-with-empty-id", 207 requestId: "", 208 expectedCode: http.StatusBadRequest, 209 }, 210 { 211 description: "invalid-request-with-id-not-found", 212 requestId: "100", 213 expectedCode: http.StatusNotFound, 214 }, 215 } 216 217 for _, tc := range tests { 218 t.Run(tc.description, func(t *testing.T) { 219 if !tc.emptyDB { 220 err := insertMockDBData([]Namespace{ 221 { 222 ID: 1, 223 Prefix: "/origin1", 224 Pubkey: mockPublicKey, 225 }, 226 }) 227 if err != nil { 228 t.Fatalf("Failed to set up mock data: %v", err) 229 } 230 231 } 232 defer func() { 233 err := resetNamespaceDB() 234 if err != nil { 235 t.Fatalf("Failed to reset mock namespace DB: %v", err) 236 } 237 }() 238 239 // Create a request to the endpoint 240 w := httptest.NewRecorder() 241 requestURL := fmt.Sprint("/test/", tc.requestId, "/pubkey") 242 req, _ := http.NewRequest("GET", requestURL, nil) 243 router.ServeHTTP(w, req) 244 245 // Check the response 246 require.Equal(t, tc.expectedCode, w.Code) 247 248 if tc.expectedCode == http.StatusOK { 249 assert.Equal(t, tc.expectedData, w.Body.String()) 250 } 251 }) 252 } 253 }