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  })