github.com/epsagon/epsagon-go@v1.39.0/wrappers/fiber/fiber_test.go (about) 1 package epsagonfiber 2 3 import ( 4 "encoding/json" 5 "io/ioutil" 6 "net/http" 7 "net/http/httptest" 8 "strings" 9 "testing" 10 "time" 11 12 "github.com/epsagon/epsagon-go/epsagon" 13 "github.com/epsagon/epsagon-go/protocol" 14 "github.com/epsagon/epsagon-go/tracer" 15 16 "github.com/gofiber/fiber/v2" 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 ) 20 21 func TestHandlerWrapper(t *testing.T) { 22 RegisterFailHandler(Fail) 23 RunSpecs(t, "Fiber Wrapper") 24 } 25 26 const SanityPath = "/test" 27 const SanityHTTPMethod = "GET" 28 const ResponseData = "Hello world" 29 30 func verifyResponseSuccess(response *http.Response, err error) { 31 Expect(err).To(BeNil()) 32 defer response.Body.Close() 33 responseData, err := ioutil.ReadAll(response.Body) 34 Expect(err).To(BeNil()) 35 responseString := string(responseData) 36 Expect(responseString).To(Equal(ResponseData)) 37 } 38 39 var _ = Describe("fiber_middleware", func() { 40 Describe("FiberEpsagonMiddleware", func() { 41 var ( 42 events []*protocol.Event 43 exceptions []*protocol.Exception 44 config *epsagon.Config 45 app *fiber.App 46 called bool 47 request *http.Request 48 ) 49 BeforeEach(func() { 50 config = &epsagon.Config{Config: tracer.Config{ 51 Disable: true, 52 TestMode: true, 53 }} 54 events = make([]*protocol.Event, 0, 5) 55 exceptions = make([]*protocol.Exception, 0) 56 tracer.GlobalTracer = &tracer.MockedEpsagonTracer{ 57 Events: &events, 58 Exceptions: &exceptions, 59 Labels: make(map[string]interface{}), 60 Config: &config.Config, 61 } 62 request = httptest.NewRequest(SanityHTTPMethod, SanityPath, nil) 63 app = fiber.New() 64 called = false 65 epsagonMiddleware := &FiberEpsagonMiddleware{ 66 Config: config, 67 } 68 app.Use(epsagonMiddleware.HandlerFunc()) 69 app.Get(SanityPath, func(c *fiber.Ctx) error { 70 called = true 71 return c.SendString(ResponseData) 72 }) 73 }) 74 Context("Happy Flows", func() { 75 It("calls the original handler", func() { 76 _, err := app.Test(request) 77 Expect(err).To(BeNil()) 78 Expect(called).To(Equal(true)) 79 }) 80 It("validates the original handler response", func() { 81 resp, err := app.Test(request) 82 verifyResponseSuccess(resp, err) 83 Expect(called).To(Equal(true)) 84 }) 85 It("creates a runner & trigger events", func() { 86 eventsRecievedChan := make(chan bool) 87 tracer.GlobalTracer = &tracer.MockedEpsagonTracer{ 88 Events: &events, 89 Exceptions: &exceptions, 90 Labels: make(map[string]interface{}), 91 Config: &config.Config, 92 DelayAddEvent: true, 93 DelayedEventsChan: eventsRecievedChan, 94 } 95 resp, err := app.Test(request) 96 verifyResponseSuccess(resp, err) 97 Expect(called).To(Equal(true)) 98 timer := time.NewTimer(time.Second * 10) 99 for eventsRecieved := 0; eventsRecieved < 2; { 100 select { 101 case <-eventsRecievedChan: 102 eventsRecieved++ 103 case <-timer.C: 104 // timeout - events should have been recieved 105 Expect(false).To(Equal(true)) 106 } 107 } 108 Expect(len(events)).To(Equal(2)) 109 var runnerEvent *protocol.Event 110 for _, event := range events { 111 if event.Origin == "runner" { 112 runnerEvent = event 113 } 114 } 115 Expect(runnerEvent).NotTo(Equal(nil)) 116 Expect(runnerEvent.Resource.Type).To(Equal("fiber")) 117 Expect(runnerEvent.Resource.Name).To(Equal("/test")) 118 }) 119 It("Validates runner event", func() { 120 eventsRecievedChan := make(chan bool) 121 tracer.GlobalTracer = &tracer.MockedEpsagonTracer{ 122 Events: &events, 123 Exceptions: &exceptions, 124 Labels: make(map[string]interface{}), 125 Config: &config.Config, 126 DelayAddEvent: true, 127 DelayedEventsChan: eventsRecievedChan, 128 } 129 bodyString := "hello world" 130 postRequest := httptest.NewRequest( 131 "POST", 132 "/test?hello=world&good=bye", 133 strings.NewReader(bodyString)) 134 app.Post(SanityPath, func(c *fiber.Ctx) error { 135 requestBody := c.Body() 136 if string(requestBody) != bodyString { 137 panic("unexpected request body") 138 } 139 called = true 140 return c.SendString(ResponseData) 141 }) 142 143 resp, err := app.Test(postRequest) 144 verifyResponseSuccess(resp, err) 145 Expect(called).To(Equal(true)) 146 timer := time.NewTimer(time.Second * 10) 147 for eventsRecieved := 0; eventsRecieved < 2; { 148 select { 149 case <-eventsRecievedChan: 150 eventsRecieved++ 151 case <-timer.C: 152 // timeout - events should have been recieved 153 Expect(false).To(Equal(true)) 154 } 155 } 156 Expect(len(events)).To(Equal(2)) 157 var triggerEvent *protocol.Event 158 for _, event := range events { 159 if event.Origin == "trigger" { 160 triggerEvent = event 161 } 162 } 163 Expect(triggerEvent).NotTo(Equal(nil)) 164 Expect(triggerEvent.Resource.Name).To(Equal("example.com")) 165 Expect(triggerEvent.Resource.Type).To(Equal("http")) 166 Expect(triggerEvent.Resource.Operation).To(Equal("POST")) 167 expectedQuery, _ := json.Marshal(map[string]string{ 168 "hello": "world", "good": "bye"}) 169 Expect(triggerEvent.Resource.Metadata["query_string_params"]).To( 170 Equal(string(expectedQuery))) 171 Expect(triggerEvent.Resource.Metadata["path"]).To( 172 Equal("/test")) 173 Expect(triggerEvent.Resource.Metadata["request_body"]).To( 174 Equal(bodyString)) 175 Expect(triggerEvent.Resource.Metadata["response_body"]).To(Equal(ResponseData)) 176 Expect(triggerEvent.Resource.Metadata["status_code"]).To( 177 Equal("200")) 178 }) 179 It("Validates runner event, metadataOnly is true", func() { 180 eventsRecievedChan := make(chan bool) 181 config := &epsagon.Config{Config: tracer.Config{ 182 Disable: true, 183 TestMode: true, 184 MetadataOnly: true, 185 }} 186 tracer.GlobalTracer = &tracer.MockedEpsagonTracer{ 187 Events: &events, 188 Exceptions: &exceptions, 189 Labels: make(map[string]interface{}), 190 Config: &config.Config, 191 DelayAddEvent: true, 192 DelayedEventsChan: eventsRecievedChan, 193 } 194 bodyString := "hello world" 195 postRequest := httptest.NewRequest( 196 "POST", 197 "/test?hello=world&good=bye", 198 strings.NewReader(bodyString)) 199 app.Post(SanityPath, func(c *fiber.Ctx) error { 200 requestBody := c.Body() 201 if string(requestBody) != bodyString { 202 panic("unexpected request body") 203 } 204 called = true 205 return c.SendString(ResponseData) 206 }) 207 resp, err := app.Test(postRequest) 208 verifyResponseSuccess(resp, err) 209 Expect(called).To(Equal(true)) 210 timer := time.NewTimer(time.Second * 10) 211 for eventsRecieved := 0; eventsRecieved < 2; { 212 select { 213 case <-eventsRecievedChan: 214 eventsRecieved++ 215 case <-timer.C: 216 // timeout - events should have been recieved 217 Expect(false).To(Equal(true)) 218 } 219 } 220 Expect(len(events)).To(Equal(2)) 221 var triggerEvent *protocol.Event 222 for _, event := range events { 223 if event.Origin == "trigger" { 224 triggerEvent = event 225 } 226 } 227 Expect(triggerEvent).NotTo(Equal(nil)) 228 Expect(triggerEvent.Resource.Name).To(Equal("example.com")) 229 Expect(triggerEvent.Resource.Type).To(Equal("http")) 230 Expect(triggerEvent.Resource.Operation).To(Equal("POST")) 231 Expect(triggerEvent.Resource.Metadata).To(Not(ContainElement("query_string_params"))) 232 Expect(triggerEvent.Resource.Metadata).To(Not(ContainElement("request_body"))) 233 Expect(triggerEvent.Resource.Metadata).To(Not(ContainElement("response_body"))) 234 Expect(triggerEvent.Resource.Metadata["path"]).To( 235 Equal("/test")) 236 Expect(triggerEvent.Resource.Metadata["status_code"]).To( 237 Equal("200")) 238 239 }) 240 }) 241 Context("Error Flows", func() { 242 It("Epsagon failure - start tracer", func() { 243 config := &epsagon.Config{Config: tracer.Config{ 244 Disable: true, 245 TestMode: true, 246 }} 247 tracer.GlobalTracer = &tracer.MockedEpsagonTracer{ 248 Events: &events, 249 Exceptions: &exceptions, 250 Labels: make(map[string]interface{}), 251 Config: &config.Config, 252 PanicStart: true, 253 } 254 resp, err := app.Test(request) 255 verifyResponseSuccess(resp, err) 256 Expect(called).To(Equal(true)) 257 }) 258 It("Epsagon failure - add event", func() { 259 config := &epsagon.Config{Config: tracer.Config{ 260 Disable: true, 261 TestMode: true, 262 }} 263 tracer.GlobalTracer = &tracer.MockedEpsagonTracer{ 264 Events: &events, 265 Exceptions: &exceptions, 266 Labels: make(map[string]interface{}), 267 Config: &config.Config, 268 PanicAddEvent: true, 269 } 270 resp, err := app.Test(request) 271 verifyResponseSuccess(resp, err) 272 Expect(called).To(Equal(true)) 273 }) 274 It("Epsagon failure - stop tracer", func() { 275 config := &epsagon.Config{Config: tracer.Config{ 276 Disable: true, 277 TestMode: true, 278 }} 279 tracer.GlobalTracer = &tracer.MockedEpsagonTracer{ 280 Events: &events, 281 Exceptions: &exceptions, 282 Labels: make(map[string]interface{}), 283 Config: &config.Config, 284 PanicStop: true, 285 } 286 resp, err := app.Test(request) 287 verifyResponseSuccess(resp, err) 288 Expect(called).To(Equal(true)) 289 }) 290 }) 291 }) 292 })