You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: inbox_test.go
    path of file: ./repos/client/go/chat/storage
    
    the code of the file until where you have to start completion: package storage

import (
	"context"
	"sort"
	"testing"
	"time"

	"encoding/hex"

	"github.com/keybase/client/go/chat/types"
	"github.com/keybase/client/go/chat/utils"
	"github.com/keybase/client/go/kbtest"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/chat1"
	"github.com/keybase/client/go/protocol/gregor1"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/stretchr/testify/require"
)

func setupInboxTest(t testing.TB, name string) (kbtest.ChatTestContext, *Inbox, gregor1.UID) {
	ctc := setupCommonTest(t, name)

	u, err := kbtest.CreateAndSignupFakeUser("ib", ctc.TestContext.G)
	require.NoError(t, err)
	uid := gregor1.UID(u.User.GetUID().ToBytes())
	return ctc, NewInbox(ctc.Context()), uid
}

func makeTlfID() chat1.TLFID {
	return randBytes(8)
}

func makeConvo(mtime gregor1.Time, rmsg chat1.MessageID, mmsg chat1.MessageID) types.RemoteConversation {
	conv := chat1.Conversation{
		Metadata: chat1.ConversationMetadata{
			ConversationID: randBytes(8),
			IdTriple: chat1.ConversationIDTriple{
				Tlfid:     makeTlfI
    
func TestInboxSync(t *testing.T) {
	tc, inbox, uid := setupInboxTest(t, "basic")
	defer tc.Cleanup()

	// Create an inbox with a bunch of convos, merge it and read it back out
	numConvs := 10
	var convs []types.RemoteConversation
	for i := numConvs - 1; i >= 0; i-- {
		convs = append(convs, makeConvo(gregor1.Time(i), 1, 1))
	}

	require.NoError(t, inbox.Merge(context.TODO(), uid, 1, utils.PluckConvs(convs), nil))
	_, res, err := inbox.Read(context.TODO(), uid, nil)
	require.NoError(t, err)

	var syncConvs []chat1.Conversation
	convs[0].Conv.Metadata.Status = chat1.ConversationStatus_MUTED
	convs[6].Conv.Metadata.Status = chat1.ConversationStatus_MUTED
	syncConvs = append(syncConvs, convs[0].Conv)
	syncConvs = append(syncConvs, convs[6].Conv)
	newConv := makeConvo(gregor1.Time(60), 1, 1)
	syncConvs = append(syncConvs, newConv.Conv)

	vers, err := inbox.Version(context.TODO(), uid)
	require.NoError(t, err)
	syncRes, err := inbox.Sync(context.TODO(), uid, vers+1, syncConvs)
	require.NoError(t, err)
	newVers, newRes, err := inbox.Read(context.TODO(), uid, nil)
	require.NoError(t, err)
	sort.Sort(ByDatabaseOrder(newRes))
	require.Equal(t, vers+1, newVers)
	require.Equal(t, len(res)+1, len(newRes))
	require.Equal(t, newConv.GetConvID(), newRes[0].GetConvID())
	require.Equal(t, chat1.ConversationStatus_MUTED, newRes[1].Conv.Metadata.Status)
	require.Equal(t, chat1.ConversationStatus_MUTED, newRes[7].Conv.Metadata.Status)
	require.Equal(t, chat1.ConversationStatus_UNFILED, newRes[4].Conv.Metadata.Status)
	require.False(t, syncRes.TeamTypeChanged)
	require.Len(t, syncRes.Expunges, 0)

	syncConvs = nil
	vers, err = inbox.Version(context.TODO(), uid)
	require.NoError(t, err)
	convs[8].Conv.Metadata.TeamType = chat1.TeamType_COMPLEX
	syncConvs = append(syncConvs, convs[8].Conv)
	convs[9].Conv.Expunge = chat1.Expunge{Upto: 3}
	syncConvs = append(syncConvs, convs[9].Conv)
	syncRes, err = inbox.Sync(context.TODO(), uid, vers+1, syncConvs)
	require.NoError(t, err)
	newVers, newRes, err = inbox.Read(context.TODO(), uid, nil)
	require.NoError(t, err)
	sort.Sort(ByDatabaseOrder(newRes))
	require.Equal(t, vers+1, newVers)
	require.Equal(t, chat1.TeamType_COMPLEX, newRes[9].Conv.Metadata.TeamType)
	require.True(t, syncRes.TeamTypeChanged)
	require.Len(t, syncRes.Expunges, 1)
	require.True(t, convs[9].Conv.GetConvID().Eq(syncRes.Expunges[0].ConvID))
	require.Equal(t, convs[9].Conv.Expunge, syncRes.Expunges[0].Expunge)
}