github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/admin/controller_test.go (about) 1 // TODO: move most of these tests to pkg/api 2 package admin_test 3 4 import ( 5 "bytes" 6 "context" 7 "encoding/json" 8 "fmt" 9 "io" 10 "net/http" 11 "net/http/httptest" 12 13 "github.com/pyroscope-io/pyroscope/pkg/api" 14 "github.com/pyroscope-io/pyroscope/pkg/model/appmetadata" 15 16 . "github.com/onsi/ginkgo/v2" 17 . "github.com/onsi/gomega" 18 "github.com/sirupsen/logrus/hooks/test" 19 20 "github.com/pyroscope-io/pyroscope/pkg/admin" 21 "github.com/pyroscope-io/pyroscope/pkg/model" 22 ) 23 24 type mockStorage struct { 25 getAppsResult []appmetadata.ApplicationMetadata 26 deleteResult error 27 } 28 29 func (m mockStorage) List(ctx context.Context) ([]appmetadata.ApplicationMetadata, error) { 30 return m.getAppsResult, nil 31 } 32 33 func (m mockStorage) Delete(ctx context.Context, appname string) error { 34 return m.deleteResult 35 } 36 37 type mockUserService struct{} 38 39 func (mockUserService) UpdateUserByName(context.Context, string, model.UpdateUserParams) (model.User, error) { 40 return model.User{}, nil 41 } 42 43 type mockStorageService struct{} 44 45 func (mockStorageService) Cleanup(context.Context) error { 46 return nil 47 } 48 49 var _ = Describe("controller", func() { 50 Describe("/v1/apps", func() { 51 var svr *admin.Server 52 var response *httptest.ResponseRecorder 53 var appSvc admin.ApplicationListerAndDeleter 54 55 // create a server 56 BeforeEach(func() { 57 appSvc = mockStorage{ 58 getAppsResult: []appmetadata.ApplicationMetadata{ 59 {FQName: "app1"}, 60 {FQName: "app2"}, 61 }, 62 deleteResult: nil, 63 } 64 }) 65 66 JustBeforeEach(func() { 67 // create a null logger, since we aren't interested 68 logger, _ := test.NewNullLogger() 69 70 ctrl := admin.NewController(logger, appSvc, mockUserService{}, mockStorageService{}) 71 httpServer := &admin.UdsHTTPServer{} 72 server, err := admin.NewServer(logger, ctrl, httpServer) 73 74 Expect(err).ToNot(HaveOccurred()) 75 svr = server 76 response = httptest.NewRecorder() 77 }) 78 79 Describe("GET", func() { 80 Context("when everything is right", func() { 81 It("returns list of apps successfully", func() { 82 request, err := http.NewRequest(http.MethodGet, "/v1/apps", nil) 83 Expect(err).ToNot(HaveOccurred()) 84 85 svr.Handler.ServeHTTP(response, request) 86 87 body, err := io.ReadAll(response.Body) 88 Expect(err).To(BeNil()) 89 90 Expect(response.Code).To(Equal(http.StatusOK)) 91 Expect(string(body)).To(Equal(`[{"name":"app1"},{"name":"app2"}] 92 `)) 93 }) 94 95 }) 96 }) 97 98 Describe("DELETE", func() { 99 Context("when everything is right", func() { 100 It("returns StatusOK", func() { 101 // we are kinda robbing here 102 // since the server and client are defined in the same package 103 payload := api.DeleteAppInput{Name: "myapp"} 104 marshalledPayload, err := json.Marshal(payload) 105 request, err := http.NewRequest(http.MethodDelete, "/v1/apps", bytes.NewBuffer(marshalledPayload)) 106 Expect(err).ToNot(HaveOccurred()) 107 108 svr.Handler.ServeHTTP(response, request) 109 Expect(response.Code).To(Equal(http.StatusOK)) 110 }) 111 }) 112 113 Context("when there's an error", func() { 114 Context("with the payload", func() { 115 BeforeEach(func() { 116 appSvc = mockStorage{ 117 deleteResult: model.ValidationError{}, 118 } 119 }) 120 121 It("returns BadRequest", func() { 122 request, err := http.NewRequest(http.MethodDelete, "/v1/apps", bytes.NewBuffer([]byte(``))) 123 Expect(err).ToNot(HaveOccurred()) 124 125 svr.Handler.ServeHTTP(response, request) 126 Expect(response.Code).To(Equal(http.StatusBadRequest)) 127 }) 128 }) 129 130 Context("with the server", func() { 131 BeforeEach(func() { 132 appSvc = mockStorage{ 133 deleteResult: fmt.Errorf("error"), 134 } 135 }) 136 137 It("returns InternalServerError", func() { 138 // we are kinda robbing here 139 // since the server and client are defined in the same package 140 payload := api.DeleteAppInput{Name: "myapp"} 141 marshalledPayload, err := json.Marshal(payload) 142 request, err := http.NewRequest(http.MethodDelete, "/v1/apps", bytes.NewBuffer(marshalledPayload)) 143 Expect(err).ToNot(HaveOccurred()) 144 145 svr.Handler.ServeHTTP(response, request) 146 Expect(response.Code).To(Equal(http.StatusInternalServerError)) 147 }) 148 }) 149 }) 150 }) 151 152 DescribeTable("Non supported requests return 405 (method not allowed)", 153 func(method string) { 154 request, _ := http.NewRequest(method, "/v1/apps", nil) 155 svr.Handler.ServeHTTP(response, request) 156 Expect(response.Code).To(Equal(405)) 157 }, 158 Entry("POST", http.MethodPost), 159 Entry("PUT", http.MethodPost), 160 Entry("NON_VALID_METHOD", http.MethodPost), 161 ) 162 }) 163 })