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  }