github.com/awesome-flow/flow@v0.0.3-0.20190918184116-508d75d68a2c/pkg/corev1alpha1/actor/buffer_test.go (about) 1 package actor 2 3 import ( 4 "reflect" 5 "sync" 6 "testing" 7 8 core "github.com/awesome-flow/flow/pkg/corev1alpha1" 9 coretest "github.com/awesome-flow/flow/pkg/corev1alpha1/test" 10 "github.com/awesome-flow/flow/pkg/types" 11 "github.com/awesome-flow/flow/pkg/util" 12 testutil "github.com/awesome-flow/flow/pkg/util/test" 13 flowtest "github.com/awesome-flow/flow/pkg/util/test/corev1alpha1" 14 ) 15 16 func TestBufferRetry(t *testing.T) { 17 tests := []struct { 18 name string 19 counts []uint32 20 statuses []core.MsgStatus 21 expcnt int 22 expstatus core.MsgStatus 23 }{ 24 { 25 name: "instant done", 26 counts: []uint32{0}, 27 statuses: []core.MsgStatus{core.MsgStatusDone}, 28 expcnt: 1, 29 expstatus: core.MsgStatusDone, 30 }, 31 { 32 name: "partial send", 33 counts: []uint32{0}, 34 statuses: []core.MsgStatus{core.MsgStatusPartialSend}, 35 expcnt: 1, 36 expstatus: core.MsgStatusPartialSend, 37 }, 38 { 39 name: "fail first and done", 40 counts: []uint32{0, 1}, 41 statuses: []core.MsgStatus{core.MsgStatusFailed, core.MsgStatusDone}, 42 expcnt: 2, 43 expstatus: core.MsgStatusDone, 44 }, 45 { 46 name: "fails maxAttempts-1 times", 47 counts: []uint32{0, DefaultBufMaxAttempts - 1}, 48 statuses: []core.MsgStatus{core.MsgStatusFailed, core.MsgStatusDone}, 49 expcnt: DefaultBufMaxAttempts, 50 expstatus: core.MsgStatusDone, 51 }, 52 { 53 name: "fails maxAttempts times", 54 counts: []uint32{0, DefaultBufMaxAttempts}, 55 statuses: []core.MsgStatus{core.MsgStatusFailed, core.MsgStatusDone}, 56 expcnt: DefaultBufMaxAttempts, 57 expstatus: core.MsgStatusFailed, 58 }, 59 } 60 61 t.Parallel() 62 63 for _, testCase := range tests { 64 t.Run(testCase.name, func(t *testing.T) { 65 ctx, err := coretest.NewContextWithConfig(map[string]interface{}{"system.maxprocs": 1 + testutil.RandInt(4)}) 66 if err != nil { 67 t.Fatalf("failed to create a context: %s", err) 68 } 69 if err := ctx.Start(); err != nil { 70 t.Fatalf("failed to start context: %s", err) 71 } 72 defer ctx.Stop() 73 74 buf, err := NewBuffer("buffer", ctx, core.Params(nil)) 75 if err != nil { 76 t.Fatalf("failed to create a new buffer: %s", err) 77 } 78 act, err := flowtest.NewTestActor("test-actor", ctx, core.Params(nil)) 79 if err != nil { 80 t.Fatalf("failed to create a new test actor: %s", err) 81 } 82 nthreads, ok := ctx.Config().Get(types.NewKey("system.maxprocs")) 83 if !ok { 84 t.Fatalf("failed to fetch `system.maxprocs` config") 85 } 86 if err := buf.Connect(nthreads.(int), act); err != nil { 87 t.Fatalf("failed to connect test actor to buf: %s", err) 88 } 89 90 mailbox := make(chan *core.Message, testCase.expcnt) 91 defer close(mailbox) 92 93 var cnt uint32 94 var lock sync.Mutex 95 act.(*flowtest.TestActor).OnReceive(func(msg *core.Message) { 96 lock.Lock() 97 defer lock.Unlock() 98 act.(*flowtest.TestActor).Flush() 99 mailbox <- msg 100 var lastix int 101 for ix, v := range testCase.counts { 102 if v > cnt { 103 break 104 } 105 lastix = ix 106 } 107 msg.Complete(testCase.statuses[lastix]) 108 cnt++ 109 }) 110 111 if err := util.ExecEnsure( 112 act.Start, 113 buf.Start, 114 ); err != nil { 115 t.Fatalf("failed to start actor: %s", err) 116 } 117 118 defer util.ExecEnsure( 119 buf.Stop, 120 act.Stop, 121 ) 122 123 msg := core.NewMessage(testutil.RandBytes(1024)) 124 if err := buf.Receive(msg); err != nil { 125 t.Fatalf("buffer failed to receive a message: %s", err) 126 } 127 128 status := msg.Await() 129 if status != testCase.expstatus { 130 t.Fatalf("unexpected status: got: %d, want: %d", status, testCase.expstatus) 131 } 132 133 if len(mailbox) != testCase.expcnt { 134 t.Fatalf("unexpected length of the mailbox: got: %d, want: %d", len(mailbox), testCase.expcnt) 135 } 136 137 for i := 0; i < testCase.expcnt; i++ { 138 rcvmsg := <-mailbox 139 if !reflect.DeepEqual(rcvmsg.Body(), msg.Body()) { 140 t.Fatalf("unexpected contents of the mailbox: got: %+v, want: %+v", rcvmsg, msg) 141 } 142 } 143 }) 144 } 145 }