Skip to content

Commit b59d3d7

Browse files
authored
Structure main_test using the Testify Suite package (#169)
* Implement test suite * Add context * Implementing TearDownTest
1 parent d81358c commit b59d3d7

File tree

1 file changed

+77
-100
lines changed

1 file changed

+77
-100
lines changed

apm-lambda-extension/main_test.go

Lines changed: 77 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"elastic/apm-lambda-extension/logsapi"
2626
"encoding/json"
2727
"fmt"
28+
"github.com/stretchr/testify/suite"
2829
"net"
2930
"net/http"
3031
"net/http/httptest"
@@ -283,193 +284,169 @@ func eventQueueGenerator(inputQueue []MockEvent, eventsChannel chan MockEvent) {
283284
}
284285

285286
// TESTS
286-
func TestMain(m *testing.M) {
287+
type MainUnitTestsSuite struct {
288+
suite.Suite
289+
eventsChannel chan MockEvent
290+
lambdaServer *httptest.Server
291+
apmServer *httptest.Server
292+
apmServerInternals *APMServerInternals
293+
ctx context.Context
294+
cancel context.CancelFunc
295+
}
296+
297+
func TestMainUnitTestsSuite(t *testing.T) {
298+
suite.Run(t, new(MainUnitTestsSuite))
299+
}
300+
301+
// This function executes before each test case
302+
func (suite *MainUnitTestsSuite) SetupTest() {
303+
suite.ctx, suite.cancel = context.WithCancel(context.Background())
287304
http.DefaultServeMux = new(http.ServeMux)
288-
code := m.Run()
289-
os.Exit(code)
305+
suite.eventsChannel = make(chan MockEvent, 100)
306+
suite.lambdaServer, suite.apmServer, suite.apmServerInternals = initMockServers(suite.eventsChannel)
307+
extension.SetApmServerTransportState(extension.Healthy, suite.ctx)
290308
}
291309

292-
// TestStandardEventsChain checks a nominal sequence of events (fast APM server, only one standard event)
293-
func TestStandardEventsChain(t *testing.T) {
294-
eventsChannel := make(chan MockEvent, 100)
295-
lambdaServer, apmServer, apmServerInternals := initMockServers(eventsChannel)
296-
defer lambdaServer.Close()
297-
defer apmServer.Close()
310+
// This function executes after each test case
311+
func (suite *MainUnitTestsSuite) TearDownTest() {
312+
suite.lambdaServer.Close()
313+
suite.apmServer.Close()
314+
suite.cancel()
315+
}
298316

317+
// TestStandardEventsChain checks a nominal sequence of events (fast APM server, only one standard event)
318+
func (suite *MainUnitTestsSuite) TestStandardEventsChain() {
299319
eventsChain := []MockEvent{
300320
{Type: InvokeStandard, APMServerBehavior: TimelyResponse, ExecutionDuration: 1, Timeout: 5},
301321
}
302-
eventQueueGenerator(eventsChain, eventsChannel)
303-
assert.NotPanics(t, main)
304-
assert.True(t, strings.Contains(apmServerInternals.Data, string(TimelyResponse)))
322+
eventQueueGenerator(eventsChain, suite.eventsChannel)
323+
assert.NotPanics(suite.T(), main)
324+
assert.True(suite.T(), strings.Contains(suite.apmServerInternals.Data, string(TimelyResponse)))
305325
}
306326

307327
// TestFlush checks if the flushed param does not cause a panic or an unexpected behavior
308-
func TestFlush(t *testing.T) {
309-
eventsChannel := make(chan MockEvent, 100)
310-
lambdaServer, apmServer, apmServerInternals := initMockServers(eventsChannel)
311-
defer lambdaServer.Close()
312-
defer apmServer.Close()
313-
328+
func (suite *MainUnitTestsSuite) TestFlush() {
314329
eventsChain := []MockEvent{
315330
{Type: InvokeStandardFlush, APMServerBehavior: TimelyResponse, ExecutionDuration: 1, Timeout: 5},
316331
}
317-
eventQueueGenerator(eventsChain, eventsChannel)
318-
assert.NotPanics(t, main)
319-
assert.True(t, strings.Contains(apmServerInternals.Data, string(TimelyResponse)))
332+
eventQueueGenerator(eventsChain, suite.eventsChannel)
333+
assert.NotPanics(suite.T(), main)
334+
assert.True(suite.T(), strings.Contains(suite.apmServerInternals.Data, string(TimelyResponse)))
320335
}
321336

322337
// TestWaitGroup checks if there is no race condition between the main waitgroups (issue #128)
323-
func TestWaitGroup(t *testing.T) {
324-
eventsChannel := make(chan MockEvent, 100)
325-
lambdaServer, apmServer, apmServerInternals := initMockServers(eventsChannel)
326-
defer lambdaServer.Close()
327-
defer apmServer.Close()
328-
338+
func (suite *MainUnitTestsSuite) TestWaitGroup() {
329339
eventsChain := []MockEvent{
330340
{Type: InvokeWaitgroupsRace, APMServerBehavior: TimelyResponse, ExecutionDuration: 1, Timeout: 500},
331341
}
332-
eventQueueGenerator(eventsChain, eventsChannel)
333-
assert.NotPanics(t, main)
334-
assert.True(t, strings.Contains(apmServerInternals.Data, string(TimelyResponse)))
342+
eventQueueGenerator(eventsChain, suite.eventsChannel)
343+
assert.NotPanics(suite.T(), main)
344+
assert.True(suite.T(), strings.Contains(suite.apmServerInternals.Data, string(TimelyResponse)))
335345
}
336346

337347
// TestAPMServerDown tests that main does not panic nor runs indefinitely when the APM server is inactive.
338-
func TestAPMServerDown(t *testing.T) {
339-
eventsChannel := make(chan MockEvent, 100)
340-
lambdaServer, apmServer, apmServerInternals := initMockServers(eventsChannel)
341-
defer lambdaServer.Close()
342-
apmServer.Close()
343-
348+
func (suite *MainUnitTestsSuite) TestAPMServerDown() {
349+
suite.apmServer.Close()
344350
eventsChain := []MockEvent{
345351
{Type: InvokeStandard, APMServerBehavior: TimelyResponse, ExecutionDuration: 1, Timeout: 5},
346352
}
347-
eventQueueGenerator(eventsChain, eventsChannel)
348-
assert.NotPanics(t, main)
349-
assert.False(t, strings.Contains(apmServerInternals.Data, string(TimelyResponse)))
353+
eventQueueGenerator(eventsChain, suite.eventsChannel)
354+
assert.NotPanics(suite.T(), main)
355+
assert.False(suite.T(), strings.Contains(suite.apmServerInternals.Data, string(TimelyResponse)))
350356
}
351357

352358
// TestAPMServerHangs tests that main does not panic nor runs indefinitely when the APM server does not respond.
353-
func TestAPMServerHangs(t *testing.T) {
354-
extension.SetApmServerTransportState(extension.Healthy, context.Background())
355-
eventsChannel := make(chan MockEvent, 100)
356-
lambdaServer, apmServer, apmServerInternals := initMockServers(eventsChannel)
357-
defer lambdaServer.Close()
358-
defer apmServer.Close()
359-
359+
func (suite *MainUnitTestsSuite) TestAPMServerHangs() {
360360
eventsChain := []MockEvent{
361361
{Type: InvokeStandard, APMServerBehavior: Hangs, ExecutionDuration: 1, Timeout: 5},
362362
}
363-
eventQueueGenerator(eventsChain, eventsChannel)
364-
assert.NotPanics(t, main)
365-
assert.False(t, strings.Contains(apmServerInternals.Data, string(Hangs)))
366-
apmServerInternals.UnlockSignalChannel <- struct{}{}
363+
eventQueueGenerator(eventsChain, suite.eventsChannel)
364+
assert.NotPanics(suite.T(), main)
365+
assert.False(suite.T(), strings.Contains(suite.apmServerInternals.Data, string(Hangs)))
366+
suite.apmServerInternals.UnlockSignalChannel <- struct{}{}
367367
}
368368

369369
// TestAPMServerRecovery tests a scenario where the APM server recovers after hanging.
370370
// The default forwarder timeout is 3 seconds, so we wait 5 seconds until we unlock that hanging state.
371371
// Hence, the APM server is waked up just in time to process the TimelyResponse data frame.
372-
func TestAPMServerRecovery(t *testing.T) {
373-
extension.SetApmServerTransportState(extension.Healthy, context.Background())
372+
func (suite *MainUnitTestsSuite) TestAPMServerRecovery() {
374373
if err := os.Setenv("ELASTIC_APM_DATA_FORWARDER_TIMEOUT_SECONDS", "1"); err != nil {
375-
t.Fail()
374+
suite.T().Fail()
376375
}
377376
if err := os.Setenv("ELASTIC_APM_LOG_LEVEL", "trace"); err != nil {
378-
t.Fail()
377+
suite.T().Fail()
379378
}
380-
eventsChannel := make(chan MockEvent, 100)
381-
lambdaServer, apmServer, apmServerInternals := initMockServers(eventsChannel)
382-
defer lambdaServer.Close()
383-
defer apmServer.Close()
384379

385380
eventsChain := []MockEvent{
386381
{Type: InvokeStandard, APMServerBehavior: Hangs, ExecutionDuration: 1, Timeout: 5},
387382
{Type: InvokeStandard, APMServerBehavior: TimelyResponse, ExecutionDuration: 1, Timeout: 5},
388383
}
389-
eventQueueGenerator(eventsChain, eventsChannel)
384+
eventQueueGenerator(eventsChain, suite.eventsChannel)
390385
go func() {
391386
time.Sleep(2500 * time.Millisecond) // Cannot multiply time.Second by a float
392-
apmServerInternals.UnlockSignalChannel <- struct{}{}
387+
suite.apmServerInternals.UnlockSignalChannel <- struct{}{}
393388
}()
394-
assert.NotPanics(t, main)
395-
assert.True(t, strings.Contains(apmServerInternals.Data, string(Hangs)))
396-
assert.True(t, strings.Contains(apmServerInternals.Data, string(TimelyResponse)))
389+
assert.NotPanics(suite.T(), main)
390+
assert.True(suite.T(), strings.Contains(suite.apmServerInternals.Data, string(Hangs)))
391+
assert.True(suite.T(), strings.Contains(suite.apmServerInternals.Data, string(TimelyResponse)))
397392
if err := os.Setenv("ELASTIC_APM_DATA_FORWARDER_TIMEOUT_SECONDS", ""); err != nil {
398-
t.Fail()
393+
suite.T().Fail()
399394
}
400395
}
401396

402397
// TestGracePeriodHangs verifies that the WaitforGracePeriod goroutine ends when main() ends.
403398
// This can be checked by asserting that apmTransportStatus is pending after the execution of main.
404-
func TestGracePeriodHangs(t *testing.T) {
399+
func (suite *MainUnitTestsSuite) TestGracePeriodHangs() {
405400
extension.ApmServerTransportState.Status = extension.Pending
406401
extension.ApmServerTransportState.ReconnectionCount = 100
407-
eventsChannel := make(chan MockEvent, 100)
408-
lambdaServer, apmServer, apmServerInternals := initMockServers(eventsChannel)
409-
defer lambdaServer.Close()
410-
defer apmServer.Close()
411402

412403
eventsChain := []MockEvent{
413404
{Type: InvokeStandard, APMServerBehavior: Hangs, ExecutionDuration: 1, Timeout: 5},
414405
}
415-
eventQueueGenerator(eventsChain, eventsChannel)
416-
assert.NotPanics(t, main)
406+
eventQueueGenerator(eventsChain, suite.eventsChannel)
407+
assert.NotPanics(suite.T(), main)
417408

418409
time.Sleep(100 * time.Millisecond)
419-
apmServerInternals.UnlockSignalChannel <- struct{}{}
420-
defer assert.Equal(t, extension.IsTransportStatusHealthyOrPending(), true)
410+
suite.apmServerInternals.UnlockSignalChannel <- struct{}{}
411+
defer assert.Equal(suite.T(), extension.IsTransportStatusHealthyOrPending(), true)
421412
}
422413

423414
// TestAPMServerCrashesDuringExecution tests that main does not panic nor runs indefinitely when the APM server crashes
424415
// during execution.
425-
func TestAPMServerCrashesDuringExecution(t *testing.T) {
426-
eventsChannel := make(chan MockEvent, 100)
427-
lambdaServer, apmServer, apmServerInternals := initMockServers(eventsChannel)
428-
defer lambdaServer.Close()
429-
defer apmServer.Close()
430-
416+
func (suite *MainUnitTestsSuite) TestAPMServerCrashesDuringExecution() {
431417
eventsChain := []MockEvent{
432418
{Type: InvokeStandard, APMServerBehavior: Crashes, ExecutionDuration: 1, Timeout: 5},
433419
}
434-
eventQueueGenerator(eventsChain, eventsChannel)
435-
assert.NotPanics(t, main)
436-
assert.False(t, strings.Contains(apmServerInternals.Data, string(Crashes)))
420+
eventQueueGenerator(eventsChain, suite.eventsChannel)
421+
assert.NotPanics(suite.T(), main)
422+
assert.False(suite.T(), strings.Contains(suite.apmServerInternals.Data, string(Crashes)))
437423
}
438424

439425
// TestFullChannel checks that an overload of APM data chunks is handled correctly, events dropped beyond the 100th one
440426
// if no space left in channel, no panic, no infinite hanging.
441-
func TestFullChannel(t *testing.T) {
442-
eventsChannel := make(chan MockEvent, 1000)
443-
lambdaServer, apmServer, apmServerInternals := initMockServers(eventsChannel)
444-
defer lambdaServer.Close()
445-
defer apmServer.Close()
446-
427+
func (suite *MainUnitTestsSuite) TestFullChannel() {
447428
eventsChain := []MockEvent{
448429
{Type: InvokeMultipleTransactionsOverload, APMServerBehavior: TimelyResponse, ExecutionDuration: 0.1, Timeout: 5},
449430
}
450-
eventQueueGenerator(eventsChain, eventsChannel)
451-
assert.NotPanics(t, main)
452-
assert.True(t, strings.Contains(apmServerInternals.Data, string(TimelyResponse)))
431+
eventQueueGenerator(eventsChain, suite.eventsChannel)
432+
assert.NotPanics(suite.T(), main)
433+
assert.True(suite.T(), strings.Contains(suite.apmServerInternals.Data, string(TimelyResponse)))
453434
}
454435

455436
// TestFullChannelSlowAPMServer tests what happens when the APM Data channel is full and the APM server is slow
456437
// (send strategy : background)
457-
func TestFullChannelSlowAPMServer(t *testing.T) {
438+
func (suite *MainUnitTestsSuite) TestFullChannelSlowAPMServer() {
458439
if err := os.Setenv("ELASTIC_APM_SEND_STRATEGY", "background"); err != nil {
459-
t.Fail()
440+
suite.T().Fail()
460441
}
461-
eventsChannel := make(chan MockEvent, 1000)
462-
lambdaServer, apmServer, _ := initMockServers(eventsChannel)
463-
defer lambdaServer.Close()
464-
defer apmServer.Close()
465442

466443
eventsChain := []MockEvent{
467444
{Type: InvokeMultipleTransactionsOverload, APMServerBehavior: SlowResponse, ExecutionDuration: 0.01, Timeout: 5},
468445
}
469-
eventQueueGenerator(eventsChain, eventsChannel)
470-
assert.NotPanics(t, main)
446+
eventQueueGenerator(eventsChain, suite.eventsChannel)
447+
assert.NotPanics(suite.T(), main)
471448
// The test should not hang
472449
if err := os.Setenv("ELASTIC_APM_SEND_STRATEGY", "syncflush"); err != nil {
473-
t.Fail()
450+
suite.T().Fail()
474451
}
475452
}

0 commit comments

Comments
 (0)