github.com/alwitt/goutils@v0.6.4/event_processing_test.go (about)

     1  package goutils
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"reflect"
     7  	"sync"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/apex/log"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  func TestTaskParamProcessing(t *testing.T) {
    16  	assert := assert.New(t)
    17  
    18  	ctxt, cancel := context.WithCancel(context.Background())
    19  	defer cancel()
    20  	uut, err := GetNewTaskProcessorInstance(ctxt, "testing", 4, log.Fields{"instance": "unit-tester"})
    21  	assert.Nil(err)
    22  	defer func() {
    23  		assert.Nil(uut.StopEventLoop())
    24  	}()
    25  	uutCast, ok := uut.(*taskProcessorImpl)
    26  	assert.True(ok)
    27  
    28  	// Case 1: no executor map
    29  	{
    30  		assert.NotNil(uutCast.processNewTaskParam("hello"))
    31  	}
    32  
    33  	type testStruct1 struct{}
    34  	type testStruct2 struct{}
    35  	type testStruct3 struct{}
    36  
    37  	executorMap := map[reflect.Type]TaskProcessorSupportHandler{
    38  		reflect.TypeOf(testStruct1{}): func(p interface{}) error {
    39  			return nil
    40  		},
    41  	}
    42  
    43  	// Case 2: define a executor map
    44  	{
    45  		assert.Nil(uut.SetTaskExecutionMap(executorMap))
    46  		assert.Nil(uutCast.processNewTaskParam(testStruct1{}))
    47  		assert.NotNil(uutCast.processNewTaskParam(testStruct2{}))
    48  		assert.NotNil(uutCast.processNewTaskParam(&testStruct3{}))
    49  	}
    50  
    51  	executorMap = map[reflect.Type]TaskProcessorSupportHandler{
    52  		reflect.TypeOf(testStruct1{}): func(p interface{}) error { return nil },
    53  		reflect.TypeOf(testStruct3{}): func(p interface{}) error { return fmt.Errorf("Dummy error") },
    54  	}
    55  
    56  	// Case 3: change executor map
    57  	{
    58  		assert.Nil(uut.SetTaskExecutionMap(executorMap))
    59  		assert.Nil(uutCast.processNewTaskParam(testStruct1{}))
    60  		assert.NotNil(uutCast.processNewTaskParam(&testStruct2{}))
    61  		assert.NotNil(uutCast.processNewTaskParam(testStruct3{}))
    62  	}
    63  
    64  	// Case 4: append to existing map
    65  	{
    66  		assert.Nil(uut.AddToTaskExecutionMap(
    67  			reflect.TypeOf(&testStruct2{}), func(p interface{}) error { return nil },
    68  		))
    69  		assert.Nil(uutCast.processNewTaskParam(testStruct1{}))
    70  		assert.Nil(uutCast.processNewTaskParam(&testStruct2{}))
    71  		assert.NotNil(uutCast.processNewTaskParam(testStruct3{}))
    72  	}
    73  }
    74  
    75  func TestTaskDemuxProcessing(t *testing.T) {
    76  	assert := assert.New(t)
    77  	log.SetLevel(log.DebugLevel)
    78  
    79  	wg := sync.WaitGroup{}
    80  	defer wg.Wait()
    81  	ctxt, cancel := context.WithCancel(context.Background())
    82  	defer cancel()
    83  
    84  	{
    85  		_, err := GetNewTaskDemuxProcessorInstance(
    86  			ctxt, "testing", 4, 0, log.Fields{"instance": "unit-tester"},
    87  		)
    88  		assert.NotNil(err)
    89  	}
    90  
    91  	uut, err := GetNewTaskDemuxProcessorInstance(
    92  		ctxt, "testing", 4, 3, log.Fields{"instance": "unit-tester"},
    93  	)
    94  	assert.Nil(err)
    95  	defer func() {
    96  		assert.Nil(uut.StopEventLoop())
    97  	}()
    98  
    99  	// recast to source
   100  	uutc := uut.(*taskDemuxProcessorImpl)
   101  	assert.Equal(0, uutc.routeIdx)
   102  
   103  	// start the built in processes
   104  	assert.Nil(uut.StartEventLoop(&wg))
   105  
   106  	path1 := 0
   107  	path2 := 0
   108  	path3 := 0
   109  
   110  	type testStruct1 struct{}
   111  	type testStruct2 struct{}
   112  	type testStruct3 struct{}
   113  
   114  	testWG := sync.WaitGroup{}
   115  	pathCB1 := func(p interface{}) error {
   116  		path1++
   117  		testWG.Done()
   118  		return nil
   119  	}
   120  	pathCB2 := func(p interface{}) error {
   121  		path2++
   122  		testWG.Done()
   123  		return nil
   124  	}
   125  	pathCB3 := func(p interface{}) error {
   126  		path3++
   127  		testWG.Done()
   128  		return nil
   129  	}
   130  
   131  	executorMap := map[reflect.Type]TaskProcessorSupportHandler{
   132  		reflect.TypeOf(testStruct1{}): pathCB1,
   133  		reflect.TypeOf(testStruct2{}): pathCB2,
   134  		reflect.TypeOf(testStruct3{}): pathCB3,
   135  	}
   136  
   137  	assert.Nil(uut.SetTaskExecutionMap(executorMap))
   138  
   139  	// Case 1: trigger
   140  	{
   141  		testWG.Add(1)
   142  		useContext, cancel := context.WithTimeout(context.Background(), time.Second)
   143  		assert.Nil(uut.Submit(useContext, testStruct1{}))
   144  		cancel()
   145  		testWG.Wait()
   146  		assert.Equal(1, path1)
   147  		assert.Equal(1, uutc.routeIdx)
   148  	}
   149  
   150  	// Case 2: trigger
   151  	{
   152  		testWG.Add(1)
   153  		useContext, cancel := context.WithTimeout(context.Background(), time.Second)
   154  		assert.Nil(uut.Submit(useContext, testStruct1{}))
   155  		cancel()
   156  		testWG.Wait()
   157  		assert.Equal(2, path1)
   158  		assert.Equal(2, uutc.routeIdx)
   159  	}
   160  
   161  	// Case 3: trigger back to back
   162  	{
   163  		testWG.Add(2)
   164  		useContext, cancel := context.WithTimeout(context.Background(), time.Second)
   165  		assert.Nil(uut.Submit(useContext, testStruct2{}))
   166  		cancel()
   167  		useContext, cancel = context.WithTimeout(context.Background(), time.Second)
   168  		assert.Nil(uut.Submit(useContext, testStruct3{}))
   169  		cancel()
   170  		testWG.Wait()
   171  		assert.Equal(1, path2)
   172  		assert.Equal(1, path3)
   173  		assert.Equal(1, uutc.routeIdx)
   174  	}
   175  }