@@ -25,7 +25,6 @@ import (
25
25
"elastic/apm-lambda-extension/logsapi"
26
26
"encoding/json"
27
27
"fmt"
28
- "github.com/stretchr/testify/suite"
29
28
"io/ioutil"
30
29
"net"
31
30
"net/http"
@@ -81,9 +80,7 @@ type ApmInfo struct {
81
80
Version string `json:"version"`
82
81
}
83
82
84
- func initMockServers (eventsChannel chan MockEvent ) (* httptest.Server , * httptest.Server , * MockServerInternals , * MockServerInternals ) {
85
-
86
- // Mock APM Server
83
+ func newMockApmServer (t * testing.T ) (* MockServerInternals , * httptest.Server ) {
87
84
var apmServerInternals MockServerInternals
88
85
apmServerInternals .WaitForUnlockSignal = true
89
86
apmServerInternals .UnlockSignalChannel = make (chan struct {})
@@ -135,16 +132,21 @@ func initMockServers(eventsChannel chan MockEvent) (*httptest.Server, *httptest.
135
132
}
136
133
}
137
134
}))
135
+
138
136
if err := os .Setenv ("ELASTIC_APM_LAMBDA_APM_SERVER" , apmServer .URL ); err != nil {
139
137
extension .Log .Fatalf ("Could not set environment variable : %v" , err )
140
- return nil , nil , nil , nil
138
+ return nil , nil
141
139
}
142
140
if err := os .Setenv ("ELASTIC_APM_SECRET_TOKEN" , "none" ); err != nil {
143
141
extension .Log .Fatalf ("Could not set environment variable : %v" , err )
144
- return nil , nil , nil , nil
142
+ return nil , nil
145
143
}
146
144
147
- // Mock Lambda Server
145
+ t .Cleanup (func () { apmServer .Close () })
146
+ return & apmServerInternals , apmServer
147
+ }
148
+
149
+ func newMockLambdaServer (t * testing.T , eventsChannel chan MockEvent ) * MockServerInternals {
148
150
var lambdaServerInternals MockServerInternals
149
151
lambdaServer := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
150
152
switch r .RequestURI {
@@ -184,7 +186,7 @@ func initMockServers(eventsChannel chan MockEvent) (*httptest.Server, *httptest.
184
186
strippedLambdaURL := slicedLambdaURL [1 ]
185
187
if err := os .Setenv ("AWS_LAMBDA_RUNTIME_API" , strippedLambdaURL ); err != nil {
186
188
extension .Log .Fatalf ("Could not set environment variable : %v" , err )
187
- return nil , nil , nil , nil
189
+ return nil
188
190
}
189
191
extensionClient = extension .NewClient (os .Getenv ("AWS_LAMBDA_RUNTIME_API" ))
190
192
@@ -196,10 +198,26 @@ func initMockServers(eventsChannel chan MockEvent) (*httptest.Server, *httptest.
196
198
}
197
199
if err = os .Setenv ("ELASTIC_APM_DATA_RECEIVER_SERVER_PORT" , fmt .Sprint (extensionPort )); err != nil {
198
200
extension .Log .Fatalf ("Could not set environment variable : %v" , err )
199
- return nil , nil , nil , nil
201
+ return nil
202
+ }
203
+
204
+ t .Cleanup (func () { lambdaServer .Close () })
205
+ return & lambdaServerInternals
206
+ }
207
+
208
+ // TODO : Move logger out of extension package and stop using it as a package-level variable
209
+ func newLogger (t * testing.T , logLevel string ) {
210
+ if err := os .Setenv ("ELASTIC_APM_LOG_LEVEL" , logLevel ); err != nil {
211
+ t .Fail ()
200
212
}
213
+ }
201
214
202
- return lambdaServer , apmServer , & apmServerInternals , & lambdaServerInternals
215
+ func newTestStructs (t * testing.T ) (context.Context , chan MockEvent ) {
216
+ http .DefaultServeMux = new (http.ServeMux )
217
+ ctx , cancel := context .WithCancel (context .Background ())
218
+ t .Cleanup (func () { cancel () })
219
+ eventsChannel := make (chan MockEvent , 100 )
220
+ return ctx , eventsChannel
203
221
}
204
222
205
223
func processMockEvent (currId string , event MockEvent , extensionPort string , internals * MockServerInternals ) {
@@ -319,187 +337,213 @@ func eventQueueGenerator(inputQueue []MockEvent, eventsChannel chan MockEvent) {
319
337
}
320
338
}
321
339
322
- // TESTS
323
- type MainUnitTestsSuite struct {
324
- suite.Suite
325
- eventsChannel chan MockEvent
326
- lambdaServer * httptest.Server
327
- apmServer * httptest.Server
328
- apmServerInternals * MockServerInternals
329
- lambdaServerInternals * MockServerInternals
330
- ctx context.Context
331
- cancel context.CancelFunc
332
- }
333
-
334
- func TestMainUnitTestsSuite (t * testing.T ) {
335
- suite .Run (t , new (MainUnitTestsSuite ))
336
- }
337
-
338
- // This function executes before each test case
339
- func (suite * MainUnitTestsSuite ) SetupTest () {
340
- if err := os .Setenv ("ELASTIC_APM_LOG_LEVEL" , "trace" ); err != nil {
341
- suite .T ().Fail ()
342
- }
343
- suite .ctx , suite .cancel = context .WithCancel (context .Background ())
344
- http .DefaultServeMux = new (http.ServeMux )
345
- suite .eventsChannel = make (chan MockEvent , 100 )
346
- suite .lambdaServer , suite .apmServer , suite .apmServerInternals , suite .lambdaServerInternals = initMockServers (suite .eventsChannel )
347
- }
348
-
349
- // This function executes after each test case
350
- func (suite * MainUnitTestsSuite ) TearDownTest () {
351
- suite .lambdaServer .Close ()
352
- suite .apmServer .Close ()
353
- suite .cancel ()
354
- }
355
-
356
340
// TestStandardEventsChain checks a nominal sequence of events (fast APM server, only one standard event)
357
- func (suite * MainUnitTestsSuite ) TestStandardEventsChain () {
341
+ func TestStandardEventsChain (t * testing.T ) {
342
+ newLogger (t , "trace" )
343
+ _ , eventsChannel := newTestStructs (t )
344
+ apmServerInternals , _ := newMockApmServer (t )
345
+ newMockLambdaServer (t , eventsChannel )
346
+
358
347
eventsChain := []MockEvent {
359
348
{Type : InvokeStandard , APMServerBehavior : TimelyResponse , ExecutionDuration : 1 , Timeout : 5 },
360
349
}
361
- eventQueueGenerator (eventsChain , suite . eventsChannel )
362
- assert .NotPanics (suite . T () , main )
363
- assert .True (suite . T () , strings .Contains (suite . apmServerInternals .Data , string (TimelyResponse )))
350
+ eventQueueGenerator (eventsChain , eventsChannel )
351
+ assert .NotPanics (t , main )
352
+ assert .True (t , strings .Contains (apmServerInternals .Data , string (TimelyResponse )))
364
353
}
365
354
366
355
// TestFlush checks if the flushed param does not cause a panic or an unexpected behavior
367
- func (suite * MainUnitTestsSuite ) TestFlush () {
356
+ func TestFlush (t * testing.T ) {
357
+ newLogger (t , "trace" )
358
+ _ , eventsChannel := newTestStructs (t )
359
+ apmServerInternals , _ := newMockApmServer (t )
360
+ newMockLambdaServer (t , eventsChannel )
361
+
368
362
eventsChain := []MockEvent {
369
363
{Type : InvokeStandardFlush , APMServerBehavior : TimelyResponse , ExecutionDuration : 1 , Timeout : 5 },
370
364
}
371
- eventQueueGenerator (eventsChain , suite . eventsChannel )
372
- assert .NotPanics (suite . T () , main )
373
- assert .True (suite . T () , strings .Contains (suite . apmServerInternals .Data , string (TimelyResponse )))
365
+ eventQueueGenerator (eventsChain , eventsChannel )
366
+ assert .NotPanics (t , main )
367
+ assert .True (t , strings .Contains (apmServerInternals .Data , string (TimelyResponse )))
374
368
}
375
369
376
370
// TestWaitGroup checks if there is no race condition between the main waitgroups (issue #128)
377
- func (suite * MainUnitTestsSuite ) TestWaitGroup () {
371
+ func TestWaitGroup (t * testing.T ) {
372
+ newLogger (t , "trace" )
373
+ _ , eventsChannel := newTestStructs (t )
374
+ apmServerInternals , _ := newMockApmServer (t )
375
+ newMockLambdaServer (t , eventsChannel )
376
+
378
377
eventsChain := []MockEvent {
379
378
{Type : InvokeWaitgroupsRace , APMServerBehavior : TimelyResponse , ExecutionDuration : 1 , Timeout : 500 },
380
379
}
381
- eventQueueGenerator (eventsChain , suite . eventsChannel )
382
- assert .NotPanics (suite . T () , main )
383
- assert .True (suite . T () , strings .Contains (suite . apmServerInternals .Data , string (TimelyResponse )))
380
+ eventQueueGenerator (eventsChain , eventsChannel )
381
+ assert .NotPanics (t , main )
382
+ assert .True (t , strings .Contains (apmServerInternals .Data , string (TimelyResponse )))
384
383
}
385
384
386
385
// TestAPMServerDown tests that main does not panic nor runs indefinitely when the APM server is inactive.
387
- func (suite * MainUnitTestsSuite ) TestAPMServerDown () {
388
- suite .apmServer .Close ()
386
+ func TestAPMServerDown (t * testing.T ) {
387
+ newLogger (t , "trace" )
388
+ _ , eventsChannel := newTestStructs (t )
389
+ apmServerInternals , apmServer := newMockApmServer (t )
390
+ newMockLambdaServer (t , eventsChannel )
391
+
392
+ apmServer .Close ()
389
393
eventsChain := []MockEvent {
390
394
{Type : InvokeStandard , APMServerBehavior : TimelyResponse , ExecutionDuration : 1 , Timeout : 5 },
391
395
}
392
- eventQueueGenerator (eventsChain , suite . eventsChannel )
393
- assert .NotPanics (suite . T () , main )
394
- assert .False (suite . T () , strings .Contains (suite . apmServerInternals .Data , string (TimelyResponse )))
396
+ eventQueueGenerator (eventsChain , eventsChannel )
397
+ assert .NotPanics (t , main )
398
+ assert .False (t , strings .Contains (apmServerInternals .Data , string (TimelyResponse )))
395
399
}
396
400
397
401
// TestAPMServerHangs tests that main does not panic nor runs indefinitely when the APM server does not respond.
398
- func (suite * MainUnitTestsSuite ) TestAPMServerHangs () {
402
+ func TestAPMServerHangs (t * testing.T ) {
403
+ newLogger (t , "trace" )
404
+ _ , eventsChannel := newTestStructs (t )
405
+ apmServerInternals , _ := newMockApmServer (t )
406
+ newMockLambdaServer (t , eventsChannel )
407
+
399
408
eventsChain := []MockEvent {
400
409
{Type : InvokeStandard , APMServerBehavior : Hangs , ExecutionDuration : 1 , Timeout : 500 },
401
410
}
402
- eventQueueGenerator (eventsChain , suite . eventsChannel )
403
- assert .NotPanics (suite . T () , main )
404
- assert .False (suite . T () , strings .Contains (suite . apmServerInternals .Data , string (Hangs )))
405
- suite . apmServerInternals .UnlockSignalChannel <- struct {}{}
411
+ eventQueueGenerator (eventsChain , eventsChannel )
412
+ assert .NotPanics (t , main )
413
+ assert .False (t , strings .Contains (apmServerInternals .Data , string (Hangs )))
414
+ apmServerInternals .UnlockSignalChannel <- struct {}{}
406
415
}
407
416
408
417
// TestAPMServerRecovery tests a scenario where the APM server recovers after hanging.
409
418
// The default forwarder timeout is 3 seconds, so we wait 5 seconds until we unlock that hanging state.
410
419
// Hence, the APM server is waked up just in time to process the TimelyResponse data frame.
411
- func (suite * MainUnitTestsSuite ) TestAPMServerRecovery () {
420
+ func TestAPMServerRecovery (t * testing.T ) {
421
+ newLogger (t , "trace" )
422
+ _ , eventsChannel := newTestStructs (t )
423
+ apmServerInternals , _ := newMockApmServer (t )
424
+ newMockLambdaServer (t , eventsChannel )
425
+
412
426
if err := os .Setenv ("ELASTIC_APM_DATA_FORWARDER_TIMEOUT_SECONDS" , "1" ); err != nil {
413
- suite . T () .Fail ()
427
+ t .Fail ()
414
428
}
415
429
416
430
eventsChain := []MockEvent {
417
431
{Type : InvokeStandard , APMServerBehavior : Hangs , ExecutionDuration : 1 , Timeout : 5 },
418
432
{Type : InvokeStandard , APMServerBehavior : TimelyResponse , ExecutionDuration : 1 , Timeout : 5 },
419
433
}
420
- eventQueueGenerator (eventsChain , suite . eventsChannel )
434
+ eventQueueGenerator (eventsChain , eventsChannel )
421
435
go func () {
422
436
time .Sleep (2500 * time .Millisecond ) // Cannot multiply time.Second by a float
423
- suite . apmServerInternals .UnlockSignalChannel <- struct {}{}
437
+ apmServerInternals .UnlockSignalChannel <- struct {}{}
424
438
}()
425
- assert .NotPanics (suite . T () , main )
426
- assert .True (suite . T () , strings .Contains (suite . apmServerInternals .Data , string (Hangs )))
427
- assert .True (suite . T () , strings .Contains (suite . apmServerInternals .Data , string (TimelyResponse )))
439
+ assert .NotPanics (t , main )
440
+ assert .True (t , strings .Contains (apmServerInternals .Data , string (Hangs )))
441
+ assert .True (t , strings .Contains (apmServerInternals .Data , string (TimelyResponse )))
428
442
if err := os .Setenv ("ELASTIC_APM_DATA_FORWARDER_TIMEOUT_SECONDS" , "" ); err != nil {
429
- suite . T () .Fail ()
443
+ t .Fail ()
430
444
}
431
445
}
432
446
433
447
// TestGracePeriodHangs verifies that the WaitforGracePeriod goroutine ends when main() ends.
434
448
// This can be checked by asserting that apmTransportStatus is pending after the execution of main.
435
- func (suite * MainUnitTestsSuite ) TestGracePeriodHangs () {
449
+ func TestGracePeriodHangs (t * testing.T ) {
450
+ newLogger (t , "trace" )
451
+ _ , eventsChannel := newTestStructs (t )
452
+ apmServerInternals , _ := newMockApmServer (t )
453
+ newMockLambdaServer (t , eventsChannel )
454
+
436
455
eventsChain := []MockEvent {
437
456
{Type : InvokeStandard , APMServerBehavior : Hangs , ExecutionDuration : 1 , Timeout : 500 },
438
457
}
439
- eventQueueGenerator (eventsChain , suite . eventsChannel )
440
- assert .NotPanics (suite . T () , main )
458
+ eventQueueGenerator (eventsChain , eventsChannel )
459
+ assert .NotPanics (t , main )
441
460
442
461
time .Sleep (100 * time .Millisecond )
443
- suite . apmServerInternals .UnlockSignalChannel <- struct {}{}
462
+ apmServerInternals .UnlockSignalChannel <- struct {}{}
444
463
}
445
464
446
465
// TestAPMServerCrashesDuringExecution tests that main does not panic nor runs indefinitely when the APM server crashes
447
466
// during execution.
448
- func (suite * MainUnitTestsSuite ) TestAPMServerCrashesDuringExecution () {
467
+ func TestAPMServerCrashesDuringExecution (t * testing.T ) {
468
+ newLogger (t , "trace" )
469
+ _ , eventsChannel := newTestStructs (t )
470
+ apmServerInternals , _ := newMockApmServer (t )
471
+ newMockLambdaServer (t , eventsChannel )
472
+
449
473
eventsChain := []MockEvent {
450
474
{Type : InvokeStandard , APMServerBehavior : Crashes , ExecutionDuration : 1 , Timeout : 5 },
451
475
}
452
- eventQueueGenerator (eventsChain , suite . eventsChannel )
453
- assert .NotPanics (suite . T () , main )
454
- assert .False (suite . T () , strings .Contains (suite . apmServerInternals .Data , string (Crashes )))
476
+ eventQueueGenerator (eventsChain , eventsChannel )
477
+ assert .NotPanics (t , main )
478
+ assert .False (t , strings .Contains (apmServerInternals .Data , string (Crashes )))
455
479
}
456
480
457
481
// TestFullChannel checks that an overload of APM data chunks is handled correctly, events dropped beyond the 100th one
458
482
// if no space left in channel, no panic, no infinite hanging.
459
- func (suite * MainUnitTestsSuite ) TestFullChannel () {
483
+ func TestFullChannel (t * testing.T ) {
484
+ newLogger (t , "trace" )
485
+ _ , eventsChannel := newTestStructs (t )
486
+ apmServerInternals , _ := newMockApmServer (t )
487
+ newMockLambdaServer (t , eventsChannel )
488
+
460
489
eventsChain := []MockEvent {
461
490
{Type : InvokeMultipleTransactionsOverload , APMServerBehavior : TimelyResponse , ExecutionDuration : 0.1 , Timeout : 5 },
462
491
}
463
- eventQueueGenerator (eventsChain , suite . eventsChannel )
464
- assert .NotPanics (suite . T () , main )
465
- assert .True (suite . T () , strings .Contains (suite . apmServerInternals .Data , string (TimelyResponse )))
492
+ eventQueueGenerator (eventsChain , eventsChannel )
493
+ assert .NotPanics (t , main )
494
+ assert .True (t , strings .Contains (apmServerInternals .Data , string (TimelyResponse )))
466
495
}
467
496
468
497
// TestFullChannelSlowAPMServer tests what happens when the APM Data channel is full and the APM server is slow
469
498
// (send strategy : background)
470
- func (suite * MainUnitTestsSuite ) TestFullChannelSlowAPMServer () {
499
+ func TestFullChannelSlowAPMServer (t * testing.T ) {
500
+ newLogger (t , "trace" )
501
+ _ , eventsChannel := newTestStructs (t )
502
+ newMockApmServer (t )
503
+ newMockLambdaServer (t , eventsChannel )
504
+
471
505
if err := os .Setenv ("ELASTIC_APM_SEND_STRATEGY" , "background" ); err != nil {
472
- suite . T () .Fail ()
506
+ t .Fail ()
473
507
}
474
508
475
509
eventsChain := []MockEvent {
476
510
{Type : InvokeMultipleTransactionsOverload , APMServerBehavior : SlowResponse , ExecutionDuration : 0.01 , Timeout : 5 },
477
511
}
478
- eventQueueGenerator (eventsChain , suite . eventsChannel )
479
- assert .NotPanics (suite . T () , main )
512
+ eventQueueGenerator (eventsChain , eventsChannel )
513
+ assert .NotPanics (t , main )
480
514
// The test should not hang
481
515
if err := os .Setenv ("ELASTIC_APM_SEND_STRATEGY" , "syncflush" ); err != nil {
482
- suite . T () .Fail ()
516
+ t .Fail ()
483
517
}
484
518
}
485
519
486
520
// TestInfoRequest checks if the extension is able to retrieve APM server info (/ endpoint) (fast APM server, only one standard event)
487
- func (suite * MainUnitTestsSuite ) TestInfoRequest () {
521
+ func TestInfoRequest (t * testing.T ) {
522
+ newLogger (t , "trace" )
523
+ _ , eventsChannel := newTestStructs (t )
524
+ newMockApmServer (t )
525
+ lambdaServerInternals := newMockLambdaServer (t , eventsChannel )
526
+
488
527
eventsChain := []MockEvent {
489
528
{Type : InvokeStandardInfo , APMServerBehavior : TimelyResponse , ExecutionDuration : 1 , Timeout : 5 },
490
529
}
491
- eventQueueGenerator (eventsChain , suite . eventsChannel )
492
- assert .NotPanics (suite . T () , main )
493
- assert .True (suite . T () , strings .Contains (suite . lambdaServerInternals .Data , "7814d524d3602e70b703539c57568cba6964fc20" ))
530
+ eventQueueGenerator (eventsChain , eventsChannel )
531
+ assert .NotPanics (t , main )
532
+ assert .True (t , strings .Contains (lambdaServerInternals .Data , "7814d524d3602e70b703539c57568cba6964fc20" ))
494
533
}
495
534
496
535
// TestInfoRequest checks if the extension times out when unable to retrieve APM server info (/ endpoint)
497
- func (suite * MainUnitTestsSuite ) TestInfoRequestHangs () {
536
+ func TestInfoRequestHangs (t * testing.T ) {
537
+ newLogger (t , "trace" )
538
+ _ , eventsChannel := newTestStructs (t )
539
+ apmServerInternals , _ := newMockApmServer (t )
540
+ lambdaServerInternals := newMockLambdaServer (t , eventsChannel )
541
+
498
542
eventsChain := []MockEvent {
499
543
{Type : InvokeStandardInfo , APMServerBehavior : Hangs , ExecutionDuration : 1 , Timeout : 500 },
500
544
}
501
- eventQueueGenerator (eventsChain , suite . eventsChannel )
502
- assert .NotPanics (suite . T () , main )
503
- assert .False (suite . T () , strings .Contains (suite . lambdaServerInternals .Data , "7814d524d3602e70b703539c57568cba6964fc20" ))
504
- suite . apmServerInternals .UnlockSignalChannel <- struct {}{}
545
+ eventQueueGenerator (eventsChain , eventsChannel )
546
+ assert .NotPanics (t , main )
547
+ assert .False (t , strings .Contains (lambdaServerInternals .Data , "7814d524d3602e70b703539c57568cba6964fc20" ))
548
+ apmServerInternals .UnlockSignalChannel <- struct {}{}
505
549
}
0 commit comments