github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/chat/localizer_test.go (about) 1 package chat 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/keybase/client/go/chat/globals" 9 "github.com/keybase/client/go/chat/types" 10 "github.com/keybase/client/go/chat/utils" 11 "github.com/keybase/client/go/kbtest" 12 "github.com/keybase/client/go/protocol/chat1" 13 "github.com/stretchr/testify/require" 14 ) 15 16 func TestLocalizerPipeline(t *testing.T) { 17 ctx, world, ri2, _, sender, _ := setupTest(t, 3) 18 defer world.Cleanup() 19 20 ri := ri2.(*kbtest.ChatRemoteMock) 21 u := world.GetUsers()[0] 22 u1 := world.GetUsers()[1] 23 u2 := world.GetUsers()[2] 24 uid := u.User.GetUID().ToBytes() 25 tc := world.Tcs[u.Username] 26 <-tc.Context().ConvLoader.Stop(ctx) 27 28 var convs []chat1.Conversation 29 _, conv := newConv(ctx, t, tc, uid, ri, sender, u.Username+","+u1.Username) 30 convs = append(convs, conv) 31 _, conv = newConv(ctx, t, tc, uid, ri, sender, u.Username+","+u2.Username) 32 convs = append(convs, conv) 33 _, conv = newConv(ctx, t, tc, uid, ri, sender, u.Username+","+u2.Username+","+u1.Username) 34 convs = append(convs, conv) 35 36 delay := 2 * time.Second 37 pipeline := newLocalizerPipeline(tc.Context()) 38 jobCh := make(chan *localizerPipelineJob) 39 pipeline.useGateCh = true 40 pipeline.jobPulledCh = jobCh 41 pipeline.start(ctx) 42 runLocalize := func() chan types.AsyncInboxResult { 43 localizeCh := make(chan types.AsyncInboxResult, 1) 44 localizer := newNonblockingLocalizer(tc.Context(), pipeline, localizeCh) 45 _, err := localizer.Localize(ctx, uid, types.Inbox{ 46 ConvsUnverified: utils.RemoteConvs(convs), 47 }, nil) 48 require.NoError(t, err) 49 require.NotNil(t, <-localizeCh) 50 return localizeCh 51 } 52 unGateAndCheck := func(job *localizerPipelineJob, localizeCh chan types.AsyncInboxResult) { 53 select { 54 case job.gateCh <- struct{}{}: 55 case <-time.After(delay): 56 require.Fail(t, "unable to ungate") 57 } 58 select { 59 case res := <-localizeCh: 60 require.Nil(t, res.ConvLocal.Error) 61 case <-time.After(delay): 62 require.Fail(t, "no result") 63 } 64 } 65 getJob := func() *localizerPipelineJob { 66 select { 67 case job := <-jobCh: 68 return job 69 case <-time.After(delay): 70 require.Fail(t, "no job") 71 } 72 return nil 73 } 74 noRes := func(ch chan types.AsyncInboxResult) { 75 select { 76 case v := <-ch: 77 require.Fail(t, fmt.Sprintf("should be no job: %#v", v)) 78 default: 79 } 80 } 81 resClosed := func(ch chan types.AsyncInboxResult) { 82 select { 83 case v := <-ch: 84 require.True(t, v.Conv.GetConvID().IsNil()) 85 case <-time.After(delay): 86 require.Fail(t, "no close") 87 } 88 } 89 90 t.Logf("basic") 91 localizeCh := runLocalize() 92 job := getJob() 93 noRes(localizeCh) 94 unGateAndCheck(job, localizeCh) 95 unGateAndCheck(job, localizeCh) 96 unGateAndCheck(job, localizeCh) 97 resClosed(localizeCh) 98 99 t.Logf("suspend") 100 localizeCh = runLocalize() 101 job = getJob() 102 noRes(localizeCh) 103 unGateAndCheck(job, localizeCh) 104 require.False(t, pipeline.suspend(ctx)) 105 unGateAndCheck(job, localizeCh) 106 unGateAndCheck(job, localizeCh) 107 resClosed(localizeCh) 108 pipeline.resume(ctx) 109 110 t.Logf("suspend (cancelable)") 111 ctx = globals.CtxAddLocalizerCancelable(ctx) 112 localizeCh = runLocalize() 113 job = getJob() 114 noRes(localizeCh) 115 unGateAndCheck(job, localizeCh) 116 require.True(t, pipeline.suspend(ctx)) 117 pipeline.resume(ctx) 118 job = getJob() 119 unGateAndCheck(job, localizeCh) 120 unGateAndCheck(job, localizeCh) 121 resClosed(localizeCh) 122 123 t.Logf("suspend multiple") 124 ctx = globals.CtxAddLocalizerCancelable(ctx) 125 localizeCh = runLocalize() 126 job = getJob() 127 noRes(localizeCh) 128 unGateAndCheck(job, localizeCh) 129 require.True(t, pipeline.suspend(ctx)) 130 require.False(t, pipeline.suspend(ctx)) 131 pipeline.resume(ctx) 132 noRes(localizeCh) 133 pipeline.resume(ctx) 134 job = getJob() 135 unGateAndCheck(job, localizeCh) 136 unGateAndCheck(job, localizeCh) 137 resClosed(localizeCh) 138 }