github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/service/gregor_test.go (about)

     1  package service
     2  
     3  import (
     4  	"crypto/rand"
     5  	"errors"
     6  	"fmt"
     7  	"testing"
     8  	"time"
     9  
    10  	"golang.org/x/net/context"
    11  
    12  	"github.com/keybase/client/go/badges"
    13  	"github.com/keybase/client/go/chat"
    14  	"github.com/keybase/client/go/chat/globals"
    15  	"github.com/keybase/client/go/gregor"
    16  	grclient "github.com/keybase/client/go/gregor/client"
    17  	"github.com/keybase/client/go/gregor/storage"
    18  	grutils "github.com/keybase/client/go/gregor/utils"
    19  	"github.com/keybase/client/go/kbtest"
    20  	"github.com/keybase/client/go/libkb"
    21  	"github.com/keybase/client/go/logger"
    22  	"github.com/keybase/client/go/protocol/chat1"
    23  	"github.com/keybase/client/go/protocol/gregor1"
    24  	"github.com/keybase/client/go/protocol/keybase1"
    25  	"github.com/keybase/clockwork"
    26  	"github.com/stretchr/testify/require"
    27  )
    28  
    29  func broadcastMessageTesting(t *testing.T, h *gregorHandler, m gregor1.Message) error {
    30  	require.NoError(t, h.BroadcastMessage(context.TODO(), m))
    31  	select {
    32  	case err := <-h.testingEvents.broadcastSentCh:
    33  		return err
    34  	case <-time.After(20 * time.Second):
    35  		require.Fail(t, "broadcast didn't complete")
    36  	}
    37  	return nil
    38  }
    39  
    40  func setupGregorTest(t *testing.T) (libkb.TestContext, *globals.Context) {
    41  	tc := libkb.SetupTest(t, "gregor", 2)
    42  	g := globals.NewContext(tc.G, &globals.ChatContext{})
    43  	g.CtxFactory = chat.NewCtxFactory(g)
    44  	return tc, g
    45  }
    46  
    47  func TestGregorHandler(t *testing.T) {
    48  	tc, g := setupGregorTest(t)
    49  	defer tc.Cleanup()
    50  
    51  	tc.G.SetService()
    52  
    53  	listener := newNlistener(t)
    54  	tc.G.NotifyRouter.AddListener(listener)
    55  
    56  	user, err := kbtest.CreateAndSignupFakeUser("gregr", tc.G)
    57  	require.NoError(t, err)
    58  
    59  	h := newGregorHandler(g)
    60  	h.Init()
    61  	h.testingEvents = newTestingEvents()
    62  	_, err = h.resetGregorClient(context.TODO(), gregor1.UID(user.User.GetUID().ToBytes()), gregor1.DeviceID{})
    63  	require.NoError(t, err)
    64  	require.Equal(t, "gregor", h.HandlerName(), "wrong name")
    65  
    66  	kbUID := user.User.GetUID()
    67  	gUID := gregor1.UID(kbUID.ToBytes())
    68  
    69  	h.PushHandler(newKBFSFavoritesHandler(tc.G))
    70  
    71  	m := gregor1.Message{
    72  		Ibm_: &gregor1.InBandMessage{
    73  			StateUpdate_: &gregor1.StateUpdateMessage{
    74  				Md_: gregor1.Metadata{
    75  					Uid_:   gUID,
    76  					MsgID_: newMsgID(),
    77  				},
    78  				Creation_: &gregor1.Item{
    79  					Category_: "kbfs.favorites",
    80  					Body_:     gregor1.Body(`{"action": "delete", "tlf":"/private/t_alice,t_bob"}`),
    81  				},
    82  			},
    83  		},
    84  	}
    85  
    86  	err = broadcastMessageTesting(t, h, m)
    87  	require.NoError(t, err)
    88  	require.Equal(t, 1, len(listener.favoritesChanged), "num faves failure")
    89  	require.Equal(t, kbUID, listener.favoritesChanged[0], "wrong uid")
    90  }
    91  
    92  type nlistener struct {
    93  	libkb.NoopNotifyListener
    94  	t                *testing.T
    95  	favoritesChanged []keybase1.UID
    96  	badgeState       chan keybase1.BadgeState
    97  	threadStale      chan []chat1.ConversationStaleUpdate
    98  	testChanTimeout  time.Duration
    99  }
   100  
   101  var _ libkb.NotifyListener = (*nlistener)(nil)
   102  
   103  func newNlistener(t *testing.T) *nlistener {
   104  	return &nlistener{
   105  		t:               t,
   106  		badgeState:      make(chan keybase1.BadgeState, 1),
   107  		threadStale:     make(chan []chat1.ConversationStaleUpdate, 1),
   108  		testChanTimeout: 20 * time.Second,
   109  	}
   110  }
   111  
   112  func (n *nlistener) FavoritesChanged(uid keybase1.UID) {
   113  	n.favoritesChanged = append(n.favoritesChanged, uid)
   114  }
   115  func (n *nlistener) ChatThreadsStale(uid keybase1.UID, cids []chat1.ConversationStaleUpdate) {
   116  	select {
   117  	case n.threadStale <- cids:
   118  	case <-time.After(n.testChanTimeout):
   119  		require.Fail(n.t, "thread send timeout")
   120  	}
   121  }
   122  func (n *nlistener) BadgeState(badgeState keybase1.BadgeState) {
   123  	select {
   124  	case n.badgeState <- badgeState:
   125  	case <-time.After(n.testChanTimeout):
   126  		require.Fail(n.t, "badgestate not read")
   127  	}
   128  }
   129  
   130  func (n *nlistener) getBadgeState(t *testing.T) keybase1.BadgeState {
   131  	select {
   132  	case x := <-n.badgeState:
   133  		return x
   134  	case <-time.After(n.testChanTimeout):
   135  		require.Fail(t, "badgestate not received")
   136  		return keybase1.BadgeState{}
   137  	}
   138  }
   139  
   140  type showTrackerPopupIdentifyUI struct {
   141  	kbtest.FakeIdentifyUI
   142  	startCh   chan string
   143  	dismissCh chan string
   144  }
   145  
   146  func newShowTrackerPopupIdentifyUI() *showTrackerPopupIdentifyUI {
   147  	return &showTrackerPopupIdentifyUI{
   148  		startCh:   make(chan string, 1),
   149  		dismissCh: make(chan string, 1),
   150  	}
   151  }
   152  
   153  var _ libkb.IdentifyUI = (*showTrackerPopupIdentifyUI)(nil)
   154  
   155  func (ui *showTrackerPopupIdentifyUI) Start(_ libkb.MetaContext, name string, reason keybase1.IdentifyReason, force bool) error {
   156  	ui.startCh <- name
   157  	return nil
   158  }
   159  
   160  // Overriding the Dismiss method lets us test that it gets called.
   161  func (ui *showTrackerPopupIdentifyUI) Dismiss(_ libkb.MetaContext, username string, _ keybase1.DismissReason) error {
   162  	ui.dismissCh <- username
   163  	return nil
   164  }
   165  
   166  // Test that when we inject a gregor "show_tracker_popup" message containing a
   167  // given UID into a gregorHandler, the result is that a TrackEngine gets run
   168  // for that user.
   169  func TestShowTrackerPopupMessage(t *testing.T) {
   170  	tc, g := setupGregorTest(t)
   171  	defer tc.Cleanup()
   172  
   173  	tc.G.SetService()
   174  
   175  	identifyUI := newShowTrackerPopupIdentifyUI()
   176  	router := fakeUIRouter{
   177  		secretUI:   &libkb.TestSecretUI{},
   178  		identifyUI: identifyUI,
   179  	}
   180  	tc.G.SetUIRouter(&router)
   181  
   182  	idhandler := NewIdentifyUIHandler(tc.G, 0)
   183  	idhandler.toggleAlwaysAlive(true)
   184  
   185  	trackee, err := kbtest.CreateAndSignupFakeUser("gregr", tc.G)
   186  	require.NoError(t, err)
   187  
   188  	// Create another test user to actually perform the track, because we can't track ourselves.
   189  	tracker, err := kbtest.CreateAndSignupFakeUser("gregr", tc.G)
   190  	require.NoError(t, err)
   191  
   192  	h := newGregorHandler(g)
   193  	h.Init()
   194  	h.testingEvents = newTestingEvents()
   195  	_, err = h.resetGregorClient(context.TODO(), gregor1.UID(tracker.User.GetUID().ToBytes()), gregor1.DeviceID{})
   196  	require.NoError(t, err)
   197  
   198  	h.PushHandler(idhandler)
   199  
   200  	msgID := gregor1.MsgID("my_random_id")
   201  	m := gregor1.Message{
   202  		Ibm_: &gregor1.InBandMessage{
   203  			StateUpdate_: &gregor1.StateUpdateMessage{
   204  				Md_: gregor1.Metadata{
   205  					MsgID_: msgID,
   206  					Uid_:   gregor1.UID(tracker.User.GetUID().ToBytes()),
   207  				},
   208  				Creation_: &gregor1.Item{
   209  					Category_: gregor1.Category("show_tracker_popup"),
   210  					Body_:     gregor1.Body(fmt.Sprintf(`{"uid": "%s"}`, trackee.User.GetUID())),
   211  				},
   212  			},
   213  		},
   214  	}
   215  
   216  	err = broadcastMessageTesting(t, h, m)
   217  	require.NoError(t, err)
   218  	select {
   219  	case name := <-identifyUI.startCh:
   220  		require.Equal(t, trackee.Username, name, "wrong username")
   221  	case <-time.After(20 * time.Second):
   222  		require.Fail(t, "no start username")
   223  	}
   224  	select {
   225  	case <-identifyUI.dismissCh:
   226  		require.Fail(t, "no dismiss should have happened")
   227  	default:
   228  	}
   229  
   230  	msgIDDis := gregor1.MsgID("my_random_id_dis")
   231  	dismissal := gregor1.Message{
   232  		Ibm_: &gregor1.InBandMessage{
   233  			StateUpdate_: &gregor1.StateUpdateMessage{
   234  				Md_: gregor1.Metadata{
   235  					MsgID_: msgIDDis,
   236  					Uid_:   gregor1.UID(tracker.User.GetUID().ToBytes()),
   237  				},
   238  				Dismissal_: &gregor1.Dismissal{
   239  					MsgIDs_: []gregor1.MsgID{msgID},
   240  				},
   241  			},
   242  		},
   243  	}
   244  	err = broadcastMessageTesting(t, h, dismissal)
   245  	require.NoError(t, err)
   246  	select {
   247  	case name := <-identifyUI.dismissCh:
   248  		require.Equal(t, trackee.User.GetName(), name, "wrong dismiss")
   249  	case <-time.After(20 * time.Second):
   250  		require.Fail(t, "no dismiss username")
   251  	}
   252  }
   253  
   254  func newMsgID() gregor1.MsgID {
   255  	ret := make([]byte, 16)
   256  	_, _ = rand.Read(ret)
   257  	return ret
   258  }
   259  
   260  type mockGregord struct {
   261  	sm  gregor.StateMachine
   262  	fc  clockwork.FakeClock
   263  	log logger.Logger
   264  }
   265  
   266  func (m mockGregord) SyncAll(ctx context.Context, arg chat1.SyncAllArg) (res chat1.SyncAllResult, err error) {
   267  	sres, err := m.Sync(ctx, gregor1.SyncArg{
   268  		Uid:      arg.Uid,
   269  		Deviceid: arg.DeviceID,
   270  		Ctime:    arg.Ctime,
   271  	})
   272  	if err != nil {
   273  		return res, err
   274  	}
   275  
   276  	res.Notification = chat1.NewSyncAllNotificationResWithIncremental(sres)
   277  	return res, nil
   278  }
   279  
   280  func (m mockGregord) Sync(ctx context.Context, arg gregor1.SyncArg) (gregor1.SyncResult, error) {
   281  	var res gregor1.SyncResult
   282  	msgs, err := m.sm.InBandMessagesSince(ctx, arg.UID(), arg.DeviceID(), arg.CTime())
   283  	if err != nil {
   284  		return res, err
   285  	}
   286  	state, err := m.sm.State(ctx, arg.UID(), arg.DeviceID(), nil)
   287  	if err != nil {
   288  		return res, err
   289  	}
   290  	hash, err := state.Hash()
   291  	if err != nil {
   292  		return res, err
   293  	}
   294  	for _, msg := range msgs {
   295  		if ibm, ok := msg.(gregor1.InBandMessage); ok {
   296  			res.Msgs = append(res.Msgs, ibm)
   297  		} else {
   298  			m.log.Warning("Bad cast in serveSync (type=%T): %+v", msg)
   299  		}
   300  	}
   301  	res.Hash = hash
   302  	return res, nil
   303  }
   304  
   305  func (m mockGregord) ConsumeMessage(ctx context.Context, msg gregor1.Message) error {
   306  	m.log.Debug("mockGregord: ConsumeMessage: msgID: %s Ctime: %s", msg.ToInBandMessage().Metadata().MsgID(),
   307  		msg.ToInBandMessage().Metadata().CTime())
   308  	_, err := m.sm.ConsumeMessage(ctx, msg)
   309  	return err
   310  }
   311  
   312  func (m mockGregord) ConsumeMessageMulti(ctx context.Context, arg gregor1.ConsumeMessageMultiArg) error {
   313  	return errors.New("unimplemented")
   314  }
   315  
   316  func (m mockGregord) ConsumePublishMessage(_ context.Context, _ gregor1.Message) error {
   317  	return errors.New("unimplemented")
   318  }
   319  func (m mockGregord) Ping(_ context.Context) (string, error) {
   320  	return "", nil
   321  }
   322  func (m mockGregord) State(ctx context.Context, arg gregor1.StateArg) (gregor1.State, error) {
   323  	state, err := m.sm.State(ctx, arg.Uid, arg.Deviceid, arg.TimeOrOffset)
   324  	if err != nil {
   325  		return gregor1.State{}, err
   326  	}
   327  	return state.(gregor1.State), nil
   328  }
   329  func (m mockGregord) StateByCategoryPrefix(_ context.Context, _ gregor1.StateByCategoryPrefixArg) (gregor1.State, error) {
   330  	return gregor1.State{}, errors.New("unimplemented")
   331  }
   332  func (m mockGregord) Version(_ context.Context, _ gregor1.UID) (string, error) {
   333  	return "mock", nil
   334  }
   335  func (m mockGregord) DescribeConnectedUsers(ctx context.Context, arg []gregor1.UID) ([]gregor1.ConnectedUser, error) {
   336  	return nil, nil
   337  }
   338  func (m mockGregord) DescribeConnectedUsersInternal(ctx context.Context, arg []gregor1.UID) ([]gregor1.ConnectedUser, error) {
   339  	return nil, nil
   340  }
   341  
   342  func (m mockGregord) newIbm(uid gregor1.UID) gregor1.Message {
   343  	m.fc.Advance(time.Minute)
   344  	return gregor1.Message{
   345  		Ibm_: &gregor1.InBandMessage{
   346  			StateUpdate_: &gregor1.StateUpdateMessage{
   347  				Md_: gregor1.Metadata{
   348  					Uid_:   uid,
   349  					MsgID_: newMsgID(),
   350  					Ctime_: gregor1.ToTime(m.fc.Now()),
   351  				},
   352  				Creation_: &gregor1.Item{
   353  					Category_: "unknown!",
   354  					Body_:     gregor1.Body([]byte("HIHIHI")),
   355  				},
   356  			},
   357  		},
   358  	}
   359  }
   360  
   361  func (m mockGregord) newIbm2(uid gregor1.UID, category gregor1.Category, body gregor1.Body) gregor1.Message {
   362  	m.fc.Advance(time.Minute)
   363  	return gregor1.Message{
   364  		Ibm_: &gregor1.InBandMessage{
   365  			StateUpdate_: &gregor1.StateUpdateMessage{
   366  				Md_: gregor1.Metadata{
   367  					Uid_:   uid,
   368  					MsgID_: newMsgID(),
   369  					Ctime_: gregor1.ToTime(m.fc.Now()),
   370  				},
   371  				Creation_: &gregor1.Item{
   372  					Category_: category,
   373  					Body_:     body,
   374  				},
   375  			},
   376  		},
   377  	}
   378  }
   379  
   380  func (m mockGregord) newDismissal(uid gregor1.UID, msg gregor.Message) gregor.Message {
   381  	m.fc.Advance(time.Minute)
   382  	dismissalID := msg.ToInBandMessage().Metadata().MsgID().(gregor1.MsgID)
   383  	return gregor1.Message{
   384  		Ibm_: &gregor1.InBandMessage{
   385  			StateUpdate_: &gregor1.StateUpdateMessage{
   386  				Md_: gregor1.Metadata{
   387  					Uid_:   uid,
   388  					MsgID_: newMsgID(),
   389  					Ctime_: gregor1.ToTime(m.fc.Now()),
   390  				},
   391  				Dismissal_: &gregor1.Dismissal{
   392  					MsgIDs_: []gregor1.MsgID{dismissalID},
   393  				},
   394  			},
   395  		},
   396  	}
   397  }
   398  
   399  func newGregordMock(logger logger.Logger) mockGregord {
   400  	var of gregor1.ObjFactory
   401  	fc := clockwork.NewFakeClock()
   402  
   403  	sm := storage.NewMemEngine(of, fc, logger)
   404  
   405  	return mockGregord{sm: sm, fc: fc, log: logger}
   406  }
   407  
   408  func setupSyncTests(t *testing.T, g *globals.Context) (*gregorHandler, mockGregord, gregor1.UID) {
   409  	user, err := kbtest.CreateAndSignupFakeUser("gregr", g.ExternalG())
   410  	require.NoError(t, err)
   411  	uid := gregor1.UID(user.User.GetUID().ToBytes())
   412  	deviceID := gregor1.DeviceID{}
   413  
   414  	h := newGregorHandler(g)
   415  	h.Init()
   416  	h.testingEvents = newTestingEvents()
   417  	_, err = h.resetGregorClient(context.TODO(), uid, deviceID)
   418  	require.NoError(t, err)
   419  
   420  	server := newGregordMock(g.ExternalG().Log)
   421  
   422  	return h, server, uid
   423  }
   424  
   425  func checkMessages(t *testing.T, source string, msgs []gregor.InBandMessage,
   426  	refMsgs []gregor.InBandMessage) {
   427  	require.Len(t, msgs, len(refMsgs))
   428  	for index, refMsg := range refMsgs {
   429  		msg := msgs[index]
   430  		msgID := msg.Metadata().MsgID()
   431  		refMsgID := refMsg.Metadata().MsgID()
   432  		require.Equal(t, refMsgID.Bytes(), msgID.Bytes())
   433  	}
   434  }
   435  
   436  func doServerSync(t *testing.T, h *gregorHandler, srv mockGregord) ([]gregor.InBandMessage, []gregor.InBandMessage) {
   437  	_, token, _, _, _ := h.loggedIn(context.TODO())
   438  	pctime := h.gregorCli.StateMachineLatestCTime(context.TODO())
   439  	ctime := gregor1.Time(0)
   440  	if pctime != nil {
   441  		ctime = gregor1.ToTime(*pctime)
   442  	}
   443  	sres, err := srv.SyncAll(context.TODO(), chat1.SyncAllArg{
   444  		Uid:      h.gregorCli.User.(gregor1.UID),
   445  		DeviceID: h.gregorCli.Device.(gregor1.DeviceID),
   446  		Session:  gregor1.SessionToken(token),
   447  		Ctime:    ctime,
   448  	})
   449  	require.NoError(t, err)
   450  	c, err := h.serverSync(context.TODO(), srv, h.gregorCli, &sres.Notification)
   451  	require.NoError(t, err)
   452  	require.NotNil(t, h.testingEvents)
   453  	select {
   454  	case r := <-h.testingEvents.replayThreadCh:
   455  		require.NoError(t, r.err)
   456  		return r.replayed, c
   457  	case <-time.After(20 * time.Second):
   458  		require.Fail(t, "no replay event received")
   459  		return nil, nil
   460  	}
   461  }
   462  
   463  func TestSyncFresh(t *testing.T) {
   464  	tc, g := setupGregorTest(t)
   465  	defer tc.Cleanup()
   466  	tc.G.SetService()
   467  
   468  	// Set up client and server
   469  	h, server, uid := setupSyncTests(t, g)
   470  	defer h.Shutdown()
   471  
   472  	// Consume a bunch of messages to the server, and we'll sync them down
   473  	const numMsgs = 20
   474  	var refMsgs []gregor.InBandMessage
   475  	for i := 0; i < numMsgs; i++ {
   476  		msg := server.newIbm(uid)
   477  		refMsgs = append(refMsgs, msg.ToInBandMessage())
   478  		err := server.ConsumeMessage(context.TODO(), msg)
   479  		require.NoError(t, err)
   480  	}
   481  
   482  	// Sync messages down and see if we get 20
   483  	replayedMessages, consumedMessages := doServerSync(t, h, server)
   484  	checkMessages(t, "replayed messages", replayedMessages, refMsgs)
   485  	checkMessages(t, "consumed messages", consumedMessages, refMsgs)
   486  }
   487  
   488  func TestSyncNonFresh(t *testing.T) {
   489  	tc, g := setupGregorTest(t)
   490  	defer tc.Cleanup()
   491  	tc.G.SetService()
   492  
   493  	// Set up client and server
   494  	h, server, uid := setupSyncTests(t, g)
   495  	defer h.Shutdown()
   496  
   497  	// Consume a bunch of messages to the server, and we'll sync them down
   498  	const numMsgs = 6
   499  	const msgLimit = numMsgs / 2
   500  	var refMsgs []gregor.InBandMessage
   501  	for i := 0; i < numMsgs; i++ {
   502  		msg := server.newIbm(uid)
   503  		err := server.ConsumeMessage(context.TODO(), msg)
   504  		require.NoError(t, err)
   505  		if i < msgLimit {
   506  			err := broadcastMessageTesting(t, h, msg)
   507  			require.NoError(t, err)
   508  			// We end up picking up the last one in the sync, since its
   509  			// CTime is equal to when we start the sync, so just add it
   510  			if i == msgLimit-1 {
   511  				refMsgs = append(refMsgs, msg.ToInBandMessage())
   512  			}
   513  		} else {
   514  			refMsgs = append(refMsgs, msg.ToInBandMessage())
   515  		}
   516  	}
   517  
   518  	// Turn off fresh replay
   519  	h.firstConnect = false
   520  
   521  	// We should only get half of the messages on a non-fresh sync
   522  	replayedMessages, consumedMessages := doServerSync(t, h, server)
   523  	checkMessages(t, "replayed messages", replayedMessages, refMsgs)
   524  	checkMessages(t, "consumed messages", consumedMessages, refMsgs)
   525  }
   526  
   527  func TestSyncSaveRestoreFresh(t *testing.T) {
   528  	tc, g := setupGregorTest(t)
   529  	defer tc.Cleanup()
   530  	tc.G.SetService()
   531  
   532  	// Set up client and server
   533  	h, server, uid := setupSyncTests(t, g)
   534  	defer h.Shutdown()
   535  
   536  	// Consume a bunch of messages to the server, and we'll sync them down
   537  	const numMsgs = 6
   538  	const msgLimit = numMsgs / 2
   539  	var refReplayMsgs, refConsumeMsgs []gregor.InBandMessage
   540  	for i := 0; i < numMsgs; i++ {
   541  		msg := server.newIbm(uid)
   542  		err := server.ConsumeMessage(context.TODO(), msg)
   543  		require.NoError(t, err)
   544  		if i < msgLimit {
   545  			err := broadcastMessageTesting(t, h, msg)
   546  			require.NoError(t, err)
   547  			// We end up picking up the last one in the sync, since its
   548  			// CTime is equal to when we start the sync, so just add it
   549  			if i == msgLimit-1 {
   550  				refConsumeMsgs = append(refConsumeMsgs, msg.ToInBandMessage())
   551  			}
   552  		} else {
   553  			refConsumeMsgs = append(refConsumeMsgs, msg.ToInBandMessage())
   554  		}
   555  		refReplayMsgs = append(refReplayMsgs, msg.ToInBandMessage())
   556  	}
   557  
   558  	// Try saving
   559  	var err error
   560  	if err = h.gregorCli.Save(context.TODO()); err != nil {
   561  		t.Fatal(err)
   562  	}
   563  
   564  	// Create a new gregor handler, this will restore our saved state
   565  	h = newGregorHandler(g)
   566  	h.testingEvents = newTestingEvents()
   567  	h.Init()
   568  	_, err = h.resetGregorClient(context.TODO(), uid, gregor1.DeviceID{})
   569  	require.NoError(t, err)
   570  
   571  	// Sync from the server
   572  	replayedMessages, consumedMessages := doServerSync(t, h, server)
   573  	checkMessages(t, "replayed messages", replayedMessages, refReplayMsgs)
   574  	checkMessages(t, "consumed messages", consumedMessages, refConsumeMsgs)
   575  }
   576  
   577  func TestSyncSaveRestoreNonFresh(t *testing.T) {
   578  	tc, g := setupGregorTest(t)
   579  	defer tc.Cleanup()
   580  	tc.G.SetService()
   581  
   582  	// Set up client and server
   583  	h, server, uid := setupSyncTests(t, g)
   584  	defer h.Shutdown()
   585  
   586  	// Consume a bunch of messages to the server, and we'll sync them down
   587  	const numMsgs = 6
   588  	const msgLimit = numMsgs / 2
   589  	var refReplayMsgs, refConsumeMsgs []gregor.InBandMessage
   590  	for i := 0; i < numMsgs; i++ {
   591  		msg := server.newIbm(uid)
   592  		err := server.ConsumeMessage(context.TODO(), msg)
   593  		require.NoError(t, err)
   594  		if i < msgLimit {
   595  			err := broadcastMessageTesting(t, h, msg)
   596  			require.NoError(t, err)
   597  			// We end up picking up the last one in the sync, since its
   598  			// CTime is equal to when we start the sync, so just add it
   599  			if i == msgLimit-1 {
   600  				refConsumeMsgs = append(refConsumeMsgs, msg.ToInBandMessage())
   601  				refReplayMsgs = append(refReplayMsgs, msg.ToInBandMessage())
   602  			}
   603  		} else {
   604  			refConsumeMsgs = append(refConsumeMsgs, msg.ToInBandMessage())
   605  			refReplayMsgs = append(refReplayMsgs, msg.ToInBandMessage())
   606  		}
   607  	}
   608  
   609  	// Try saving
   610  	var err error
   611  	if err = h.gregorCli.Save(context.TODO()); err != nil {
   612  		t.Fatal(err)
   613  	}
   614  
   615  	// Create a new gregor handler, this will restore our saved state
   616  	h = newGregorHandler(g)
   617  	h.testingEvents = newTestingEvents()
   618  	h.Init()
   619  	_, err = h.resetGregorClient(context.TODO(), uid, gregor1.DeviceID{})
   620  	require.NoError(t, err)
   621  
   622  	// Turn off fresh replay
   623  	h.firstConnect = false
   624  
   625  	// Sync from the server
   626  	replayedMessages, consumedMessages := doServerSync(t, h, server)
   627  	checkMessages(t, "replayed messages", replayedMessages, refReplayMsgs)
   628  	checkMessages(t, "consumed messages", consumedMessages, refConsumeMsgs)
   629  }
   630  
   631  func TestSyncDismissal(t *testing.T) {
   632  	tc, g := setupGregorTest(t)
   633  	defer tc.Cleanup()
   634  	tc.G.SetService()
   635  
   636  	// Set up client and server
   637  	h, server, uid := setupSyncTests(t, g)
   638  	defer h.Shutdown()
   639  
   640  	// Consume msg
   641  	msg := server.newIbm(uid)
   642  	err := server.ConsumeMessage(context.TODO(), msg)
   643  	require.NoError(t, err)
   644  
   645  	// Dismiss message
   646  	dismissal := server.newDismissal(uid, msg)
   647  	err = server.ConsumeMessage(context.TODO(), dismissal.(gregor1.Message))
   648  	require.NoError(t, err)
   649  
   650  	// Sync from the server
   651  	replayedMessages, consumedMessages := doServerSync(t, h, server)
   652  	var refReplayMsgs, refConsumeMsgs []gregor.InBandMessage
   653  	checkMessages(t, "replayed messages", replayedMessages, refReplayMsgs)
   654  	checkMessages(t, "consumed messages", consumedMessages, refConsumeMsgs)
   655  }
   656  
   657  func TestMessagesAddedDuringProcessing(t *testing.T) {
   658  	tc, g := setupGregorTest(t)
   659  	defer tc.Cleanup()
   660  	tc.G.SetService()
   661  	// Set up client and server
   662  	h, server, uid := setupSyncTests(t, g)
   663  	defer h.Shutdown()
   664  
   665  	totalNumberOfMessages := 10
   666  	numberToDoAsync := 5
   667  	// create a bunch of messages to be processed
   668  	var msgs []gregor1.Message
   669  	for i := 1; i <= totalNumberOfMessages; i++ {
   670  		msg := server.newIbm(uid)
   671  		msgs = append(msgs, msg)
   672  	}
   673  
   674  	blockUntilDone := make(chan struct{})
   675  	// fire off some of them asynchronously
   676  	go func() {
   677  		for i := 0; i < numberToDoAsync; i++ {
   678  			err := server.ConsumeMessage(context.TODO(), msgs[i])
   679  			require.NoError(t, err)
   680  		}
   681  		blockUntilDone <- struct{}{}
   682  	}()
   683  	// do the rest synchronously
   684  	for i := numberToDoAsync; i < totalNumberOfMessages; i++ {
   685  		err := server.ConsumeMessage(context.TODO(), msgs[i])
   686  		require.NoError(t, err)
   687  	}
   688  
   689  	// block until everything has had a chance to get called
   690  	select {
   691  	case <-blockUntilDone:
   692  	case <-time.After(20 * time.Second):
   693  		require.Fail(t, "async messages not consumed")
   694  	}
   695  
   696  	// all of the messages should have been consumed
   697  	_, consumedMessages := doServerSync(t, h, server)
   698  	require.Equal(t, len(consumedMessages), totalNumberOfMessages)
   699  }
   700  
   701  type dummyRemoteClient struct {
   702  	chat1.RemoteClient
   703  }
   704  
   705  func (d dummyRemoteClient) GetUnreadUpdateFull(ctx context.Context, vers chat1.InboxVers) (chat1.UnreadUpdateFull, error) {
   706  	return chat1.UnreadUpdateFull{}, nil
   707  }
   708  
   709  func TestGregorBadgesIBM(t *testing.T) {
   710  	tc, g := setupGregorTest(t)
   711  	defer tc.Cleanup()
   712  	tc.G.SetService()
   713  	listener := newNlistener(t)
   714  	tc.G.NotifyRouter.AddListener(listener)
   715  
   716  	// Set up client and server
   717  	h, server, uid := setupSyncTests(t, g)
   718  	defer h.Shutdown()
   719  	h.badger = badges.NewBadger(tc.G)
   720  	t.Logf("client setup complete")
   721  
   722  	t.Logf("server message")
   723  	// One with type: created
   724  	msg := server.newIbm2(uid, gregor1.Category("tlf"), gregor1.Body([]byte(`{"type": "created"}`)))
   725  	require.NoError(t, server.ConsumeMessage(context.TODO(), msg))
   726  	// One with some other random type.
   727  	msg = server.newIbm2(uid, gregor1.Category("tlf"), gregor1.Body([]byte(`{"type": "bogusnogus"}`)))
   728  	require.NoError(t, server.ConsumeMessage(context.TODO(), msg))
   729  
   730  	// Sync from the server
   731  	t.Logf("client sync")
   732  	_, err := h.serverSync(context.TODO(), server, h.gregorCli, nil)
   733  	require.NoError(t, err)
   734  	t.Logf("client sync complete")
   735  
   736  	ri := func() chat1.RemoteInterface {
   737  		return dummyRemoteClient{RemoteClient: chat1.RemoteClient{Cli: h.cli}}
   738  	}
   739  	badgerResync(context.TODO(), t, h.badger, ri, h.gregorCli)
   740  
   741  	listener.getBadgeState(t) // skip one since resync sends 2
   742  	bs := listener.getBadgeState(t)
   743  	require.Equal(t, 1, bs.NewTlfs, "one new tlf")
   744  
   745  	t.Logf("server dismissal")
   746  	_ = server.newDismissal(uid, msg)
   747  	require.NoError(t, server.ConsumeMessage(context.TODO(), msg))
   748  
   749  	t.Logf("client sync")
   750  	_, err = h.serverSync(context.TODO(), server, h.gregorCli, nil)
   751  	require.NoError(t, err)
   752  	t.Logf("client sync complete")
   753  
   754  	badgerResync(context.TODO(), t, h.badger, ri, h.gregorCli)
   755  
   756  	bs = listener.getBadgeState(t)
   757  	require.Equal(t, 1, bs.NewTlfs, "no more badges")
   758  }
   759  
   760  func TestGregorTeamBadges(t *testing.T) {
   761  	tc, g := setupGregorTest(t)
   762  	defer tc.Cleanup()
   763  	tc.G.SetService()
   764  	listener := newNlistener(t)
   765  	tc.G.NotifyRouter.AddListener(listener)
   766  
   767  	// Set up client and server
   768  	h, server, uid := setupSyncTests(t, g)
   769  	defer h.Shutdown()
   770  	h.badger = badges.NewBadger(tc.G)
   771  	t.Logf("client setup complete")
   772  
   773  	t.Logf("server message")
   774  	teamID := keybase1.MakeTestTeamID(1, false)
   775  	fakeUID := keybase1.MakeTestUID(1)
   776  	msg := server.newIbm2(uid, gregor1.Category("team.newly_added_to_team"), gregor1.Body([]byte(`[{"id": "`+teamID+`","name": "teamname"}]`)))
   777  	require.NoError(t, server.ConsumeMessage(context.TODO(), msg))
   778  	msg = server.newIbm2(uid, gregor1.Category("team.request_access:"+teamID), gregor1.Body([]byte(`{"id": "`+teamID+`","username": "username"}`)))
   779  	require.NoError(t, server.ConsumeMessage(context.TODO(), msg))
   780  	msg = server.newIbm2(uid, gregor1.Category("team.member_out_from_reset"), gregor1.Body([]byte(`{"reset_user": {"uid":"`+fakeUID.String()+`","username":"alice"},"team_name": "teamname"}`)))
   781  	require.NoError(t, server.ConsumeMessage(context.TODO(), msg))
   782  
   783  	// Sync from the server
   784  	t.Logf("client sync")
   785  	_, err := h.serverSync(context.TODO(), server, h.gregorCli, nil)
   786  	require.NoError(t, err)
   787  	t.Logf("client sync complete")
   788  
   789  	ri := func() chat1.RemoteInterface {
   790  		return dummyRemoteClient{RemoteClient: chat1.RemoteClient{Cli: h.cli}}
   791  	}
   792  	badgerResync(context.TODO(), t, h.badger, ri, h.gregorCli)
   793  
   794  	listener.getBadgeState(t) // skip one since resync sends 2
   795  	bs := listener.getBadgeState(t)
   796  	require.Equal(t, 1, len(bs.NewTeams), "one new team name")
   797  	require.Equal(t, teamID, bs.NewTeams[0])
   798  	require.Equal(t, 1, bs.NewTeamAccessRequestCount, "one team access request")
   799  	require.Equal(t, 1, len(bs.TeamsWithResetUsers), "one team member out due to reset")
   800  	require.Equal(t, "teamname", bs.TeamsWithResetUsers[0].Teamname)
   801  	require.Equal(t, "alice", bs.TeamsWithResetUsers[0].Username)
   802  	require.Equal(t, msg.ToInBandMessage().Metadata().MsgID(), bs.TeamsWithResetUsers[0].Id)
   803  }
   804  
   805  // TestGregorBadgesOOBM doesn't actually use out of band messages.
   806  // Instead it feeds chat updates directly to badger. So it's a pretty weak test.
   807  func TestGregorBadgesOOBM(t *testing.T) {
   808  	tc, g := setupGregorTest(t)
   809  	defer tc.Cleanup()
   810  	tc.G.SetService()
   811  	listener := newNlistener(t)
   812  	tc.G.NotifyRouter.AddListener(listener)
   813  
   814  	// Set up client and server
   815  	h, _, _ := setupSyncTests(t, g)
   816  	defer h.Shutdown()
   817  	h.badger = badges.NewBadger(tc.G)
   818  	t.Logf("client setup complete")
   819  
   820  	t.Logf("sending first chat update")
   821  	h.badger.PushChatUpdate(context.TODO(), chat1.UnreadUpdate{
   822  		ConvID:         chat1.ConversationID(`a`),
   823  		UnreadMessages: 2,
   824  	}, 0)
   825  	_ = listener.getBadgeState(t)
   826  
   827  	t.Logf("sending second chat update")
   828  	h.badger.PushChatUpdate(context.TODO(), chat1.UnreadUpdate{
   829  		ConvID:         chat1.ConversationID(`b`),
   830  		UnreadMessages: 2,
   831  	}, 1)
   832  
   833  	bs := listener.getBadgeState(t)
   834  	require.Equal(t, 2, badgeStateStats(bs).UnreadChatConversations, "unread chat convs")
   835  	require.Equal(t, 4, badgeStateStats(bs).UnreadChatMessages, "unread chat messages")
   836  
   837  	t.Logf("resyncing")
   838  	// Instead of calling badger.Resync, reach in and twiddle the knobs.
   839  	h.badger.State().UpdateWithChatFull(context.TODO(), chat1.UnreadUpdateFull{
   840  		InboxVers: chat1.InboxVers(4),
   841  		Updates: []chat1.UnreadUpdate{
   842  			{ConvID: chat1.ConversationID(`b`), UnreadMessages: 0},
   843  			{ConvID: chat1.ConversationID(`c`), UnreadMessages: 3},
   844  		},
   845  		InboxSyncStatus: chat1.SyncInboxResType_CLEAR,
   846  	}, false)
   847  	err := h.badger.Send(context.TODO())
   848  	require.NoError(t, err)
   849  	bs = listener.getBadgeState(t)
   850  	require.Equal(t, 1, badgeStateStats(bs).UnreadChatConversations, "unread chat convs")
   851  	require.Equal(t, 3, badgeStateStats(bs).UnreadChatMessages, "unread chat messages")
   852  
   853  	t.Logf("clearing")
   854  	h.badger.Clear(context.TODO())
   855  	bs = listener.getBadgeState(t)
   856  	require.Equal(t, 0, badgeStateStats(bs).UnreadChatConversations, "unread chat convs")
   857  	require.Equal(t, 0, badgeStateStats(bs).UnreadChatMessages, "unread chat messages")
   858  }
   859  
   860  func TestSyncDismissalExistingState(t *testing.T) {
   861  	tc, g := setupGregorTest(t)
   862  	defer tc.Cleanup()
   863  	tc.G.SetService()
   864  
   865  	// Set up client and server
   866  	h, server, uid := setupSyncTests(t, g)
   867  	defer h.Shutdown()
   868  
   869  	var refReplayMsgs, refConsumeMsgs []gregor.InBandMessage
   870  
   871  	// Consume msg
   872  	msg := server.newIbm(uid)
   873  	err := server.ConsumeMessage(context.TODO(), msg)
   874  	require.NoError(t, err)
   875  
   876  	// Broadcast msg
   877  	err = broadcastMessageTesting(t, h, msg)
   878  	require.NoError(t, err)
   879  
   880  	// Consume another message but don't broadcast
   881  	msg2 := server.newIbm(uid)
   882  	err = server.ConsumeMessage(context.TODO(), msg2)
   883  	require.NoError(t, err)
   884  	refConsumeMsgs = append(refConsumeMsgs, msg2.ToInBandMessage())
   885  	refReplayMsgs = append(refReplayMsgs, msg2.ToInBandMessage())
   886  
   887  	// Dismiss message
   888  	dismissal := server.newDismissal(uid, msg)
   889  	err = server.ConsumeMessage(context.TODO(), dismissal.(gregor1.Message))
   890  	require.NoError(t, err)
   891  	refReplayMsgs = append(refReplayMsgs, dismissal.ToInBandMessage())
   892  	refConsumeMsgs = append(refConsumeMsgs, dismissal.ToInBandMessage())
   893  
   894  	// Sync from the server
   895  	h.firstConnect = false
   896  	replayedMessages, consumedMessages := doServerSync(t, h, server)
   897  	checkMessages(t, "replayed messages", replayedMessages, refReplayMsgs)
   898  	checkMessages(t, "consumed messages", consumedMessages, refConsumeMsgs)
   899  }
   900  
   901  func TestSyncFutureDismissals(t *testing.T) {
   902  	tc, g := setupGregorTest(t)
   903  	defer tc.Cleanup()
   904  	tc.G.SetService()
   905  
   906  	// Set up client and server
   907  	h, server, uid := setupSyncTests(t, g)
   908  	defer h.Shutdown()
   909  
   910  	var refReplayMsgs, refConsumeMsgs []gregor.InBandMessage
   911  
   912  	// Consume msg
   913  	msg := server.newIbm(uid)
   914  	err := server.ConsumeMessage(context.TODO(), msg)
   915  	require.NoError(t, err)
   916  	refConsumeMsgs = append(refConsumeMsgs, msg.ToInBandMessage())
   917  	refReplayMsgs = append(refReplayMsgs, msg.ToInBandMessage())
   918  
   919  	// Broadcast msg
   920  	err = broadcastMessageTesting(t, h, msg)
   921  	require.NoError(t, err)
   922  
   923  	// Consume another message but don't broadcast
   924  	msg2 := server.newIbm(uid)
   925  	err = server.ConsumeMessage(context.TODO(), msg2)
   926  	require.NoError(t, err)
   927  
   928  	// Dismiss message
   929  	dismissal := server.newDismissal(uid, msg2)
   930  	err = server.ConsumeMessage(context.TODO(), dismissal.(gregor1.Message))
   931  	require.NoError(t, err)
   932  
   933  	// Sync from the server
   934  	h.firstConnect = false
   935  	replayedMessages, consumedMessages := doServerSync(t, h, server)
   936  	checkMessages(t, "replayed messages", replayedMessages, refReplayMsgs)
   937  	checkMessages(t, "consumed messages", consumedMessages, refConsumeMsgs)
   938  }
   939  
   940  func TestBroadcastRepeat(t *testing.T) {
   941  	tc, g := setupGregorTest(t)
   942  	defer tc.Cleanup()
   943  
   944  	tc.G.SetService()
   945  
   946  	u, err := kbtest.CreateAndSignupFakeUser("gregr", tc.G)
   947  	if err != nil {
   948  		t.Fatal(err)
   949  	}
   950  	uid := gregor1.UID(u.GetUID().ToBytes())
   951  
   952  	h := newGregorHandler(g)
   953  	h.Init()
   954  	h.testingEvents = newTestingEvents()
   955  	_, err = h.resetGregorClient(context.TODO(), uid, gregor1.DeviceID{})
   956  	require.NoError(t, err)
   957  
   958  	m, err := grutils.TemplateMessage(uid)
   959  	if err != nil {
   960  		t.Fatal(err)
   961  	}
   962  	m.Ibm_.StateUpdate_.Creation_ = &gregor1.Item{
   963  		Category_: gregor1.Category("mike"),
   964  		Body_:     gregor1.Body([]byte("mike")),
   965  	}
   966  
   967  	m2, err := grutils.TemplateMessage(uid)
   968  	if err != nil {
   969  		t.Fatal(err)
   970  	}
   971  	m2.Ibm_.StateUpdate_.Creation_ = &gregor1.Item{
   972  		Category_: gregor1.Category("mike!!"),
   973  		Body_:     gregor1.Body([]byte("mike!!")),
   974  	}
   975  
   976  	err = broadcastMessageTesting(t, h, m)
   977  	require.NoError(t, err)
   978  	err = broadcastMessageTesting(t, h, m2)
   979  	require.NoError(t, err)
   980  	err = broadcastMessageTesting(t, h, m)
   981  	require.Error(t, err)
   982  	require.Equal(t, "ignored repeat message", err.Error())
   983  }
   984  
   985  type BadgeStateStats struct {
   986  	UnreadChatConversations int
   987  	UnreadChatMessages      int
   988  }
   989  
   990  func badgeStateStats(bs keybase1.BadgeState) (res BadgeStateStats) {
   991  	for _, c := range bs.Conversations {
   992  		res.UnreadChatMessages += c.UnreadMessages
   993  		if c.UnreadMessages > 0 {
   994  			res.UnreadChatConversations++
   995  		}
   996  	}
   997  	return
   998  }
   999  
  1000  func TestLocalDismissals(t *testing.T) {
  1001  	tc, g := setupGregorTest(t)
  1002  	defer tc.Cleanup()
  1003  	tc.G.SetService()
  1004  
  1005  	// Set up client and server
  1006  	h, server, uid := setupSyncTests(t, g)
  1007  	defer h.Shutdown()
  1008  
  1009  	var refReplayMsgs []gregor.InBandMessage
  1010  	var refConsumeMsgs []gregor.InBandMessage
  1011  	msg := server.newIbm(uid)
  1012  	require.NoError(t, server.ConsumeMessage(context.TODO(), msg))
  1013  	refConsumeMsgs = append(refConsumeMsgs, msg.ToInBandMessage())
  1014  	refReplayMsgs = append(refReplayMsgs, msg.ToInBandMessage())
  1015  
  1016  	lmsg := server.newIbm(uid)
  1017  	require.NoError(t, server.ConsumeMessage(context.TODO(), lmsg))
  1018  	refConsumeMsgs = append(refConsumeMsgs, lmsg.ToInBandMessage())
  1019  
  1020  	require.NoError(t, h.LocalDismissItem(context.TODO(), lmsg.ToInBandMessage().Metadata().MsgID()))
  1021  
  1022  	replayedMessages, consumedMessages := doServerSync(t, h, server)
  1023  	checkMessages(t, "replayed messages", replayedMessages, refReplayMsgs)
  1024  	checkMessages(t, "consumed messages", consumedMessages, refConsumeMsgs)
  1025  
  1026  	dis := server.newDismissal(uid, lmsg)
  1027  	require.NoError(t, server.ConsumeMessage(context.TODO(), dis.(gregor1.Message)))
  1028  	require.NoError(t, broadcastMessageTesting(t, h, dis.(gregor1.Message)))
  1029  
  1030  	gcli, err := h.getGregorCli()
  1031  	require.NoError(t, err)
  1032  	lds, err := gcli.Sm.LocalDismissals(context.TODO(), uid)
  1033  	require.NoError(t, err)
  1034  	require.Zero(t, len(lds))
  1035  }
  1036  
  1037  type flakeyIncomingClient struct {
  1038  	gregor1.IncomingInterface
  1039  
  1040  	offline bool
  1041  	client  func() gregor1.IncomingInterface
  1042  }
  1043  
  1044  func newFlakeyIncomingClient(client func() gregor1.IncomingInterface) flakeyIncomingClient {
  1045  	return flakeyIncomingClient{
  1046  		client: client,
  1047  	}
  1048  }
  1049  
  1050  func (f flakeyIncomingClient) ConsumeMessage(ctx context.Context, m gregor1.Message) error {
  1051  	if f.offline {
  1052  		return errors.New("offline")
  1053  	}
  1054  	return f.client().ConsumeMessage(ctx, m)
  1055  }
  1056  
  1057  func TestOfflineConsume(t *testing.T) {
  1058  	tc, g := setupGregorTest(t)
  1059  	defer tc.Cleanup()
  1060  	tc.G.SetService()
  1061  	h, server, uid := setupSyncTests(t, g)
  1062  	defer h.Shutdown()
  1063  
  1064  	fclient := newFlakeyIncomingClient(func() gregor1.IncomingInterface { return server })
  1065  	fc := clockwork.NewFakeClock()
  1066  	client := grclient.NewClient(uid, nil, func() gregor.StateMachine {
  1067  		return storage.NewMemEngine(gregor1.ObjFactory{}, clockwork.NewRealClock(), tc.G.GetLog())
  1068  	}, storage.NewLocalDB(tc.G), func() gregor1.IncomingInterface { return fclient }, tc.G.GetLog(), fc)
  1069  	tev := grclient.NewTestingEvents()
  1070  	client.TestingEvents = tev
  1071  	h.gregorCli = client
  1072  
  1073  	// Try to consume offline
  1074  	t.Logf("offline")
  1075  	fclient.offline = true
  1076  	msg := server.newIbm(uid)
  1077  	require.NoError(t, client.ConsumeMessage(context.TODO(), msg))
  1078  	serverState, err := server.State(context.TODO(), gregor1.StateArg{
  1079  		Uid: uid,
  1080  	})
  1081  	require.NoError(t, err)
  1082  	require.Zero(t, len(serverState.Items_))
  1083  	clientState, err := client.StateMachineState(context.TODO(), gregor1.TimeOrOffset{}, true)
  1084  	require.NoError(t, err)
  1085  	items, err := clientState.Items()
  1086  	require.NoError(t, err)
  1087  	require.Equal(t, 1, len(items))
  1088  	require.Equal(t, msg.ToInBandMessage().Metadata().MsgID().String(),
  1089  		items[0].Metadata().MsgID().String())
  1090  	select {
  1091  	case <-tev.OutboxSend:
  1092  		require.Fail(t, "should not have sent")
  1093  	default:
  1094  	}
  1095  
  1096  	// Come back online
  1097  	t.Logf("online")
  1098  	fclient.offline = false
  1099  	fc.Advance(10 * time.Minute)
  1100  	select {
  1101  	case msg := <-tev.OutboxSend:
  1102  		require.Equal(t, msg.ToInBandMessage().Metadata().MsgID().String(),
  1103  			items[0].Metadata().MsgID().String())
  1104  	case <-time.After(20 * time.Second):
  1105  		require.Fail(t, "no send")
  1106  	}
  1107  	serverState, err = server.State(context.TODO(), gregor1.StateArg{
  1108  		Uid: uid,
  1109  	})
  1110  	require.NoError(t, err)
  1111  	require.NoError(t, broadcastMessageTesting(t, h, msg))
  1112  	require.Equal(t, 1, len(serverState.Items_))
  1113  	require.Equal(t, msg.ToInBandMessage().Metadata().MsgID().String(),
  1114  		serverState.Items_[0].Metadata().MsgID().String())
  1115  	clientState, err = client.StateMachineState(context.TODO(), gregor1.TimeOrOffset{}, true)
  1116  	require.NoError(t, err)
  1117  	items, err = clientState.Items()
  1118  	require.NoError(t, err)
  1119  	require.Equal(t, 1, len(items))
  1120  	require.Equal(t, msg.ToInBandMessage().Metadata().MsgID().String(),
  1121  		items[0].Metadata().MsgID().String())
  1122  
  1123  }
  1124  
  1125  func badgerResync(ctx context.Context, t testing.TB, b *badges.Badger, chatRemote func() chat1.RemoteInterface,
  1126  	gcli *grclient.Client) {
  1127  	iboxVersion, err := b.GetInboxVersionForTest(ctx)
  1128  	require.NoError(t, err)
  1129  	b.G().Log.Debug("Badger: Resync(): using inbox version: %v", iboxVersion)
  1130  	update, err := chatRemote().GetUnreadUpdateFull(ctx, iboxVersion)
  1131  	require.NoError(t, err)
  1132  
  1133  	state, err := gcli.StateMachineState(ctx, nil, false)
  1134  	require.NoError(t, err)
  1135  
  1136  	b.PushChatFullUpdate(ctx, update)
  1137  	b.PushState(ctx, state)
  1138  }