github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libkbfs/favorites_test.go (about)

     1  // Copyright 2016 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package libkbfs
     6  
     7  import (
     8  	"reflect"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/golang/mock/gomock"
    13  	"github.com/keybase/client/go/kbfs/favorites"
    14  	"github.com/keybase/client/go/kbfs/idutil"
    15  	"github.com/keybase/client/go/kbfs/kbfsedits"
    16  	"github.com/keybase/client/go/kbfs/tlf"
    17  	kbname "github.com/keybase/client/go/kbun"
    18  	"github.com/keybase/client/go/protocol/keybase1"
    19  	"github.com/stretchr/testify/require"
    20  	"golang.org/x/net/context"
    21  )
    22  
    23  func favToAddToKBFolder(toAdd favorites.ToAdd) keybase1.Folder {
    24  	handle := toAdd.ToKBFolderHandle()
    25  	return keybase1.Folder{
    26  		Private:    handle.FolderType != keybase1.FolderType_PUBLIC,
    27  		Name:       handle.Name,
    28  		FolderType: handle.FolderType,
    29  		Created:    handle.Created,
    30  	}
    31  }
    32  
    33  func favTestInit(t *testing.T, testingDiskCache bool) (
    34  	mockCtrl *gomock.Controller, config *ConfigMock, ctx context.Context) {
    35  	ctr := NewSafeTestReporter(t)
    36  	mockCtrl = gomock.NewController(ctr)
    37  	config = NewConfigMock(mockCtrl, ctr)
    38  	if !testingDiskCache {
    39  		config.mockKbpki.EXPECT().GetCurrentSession(gomock.
    40  			Any()).AnyTimes().
    41  			Return(idutil.SessionInfo{
    42  				Name: kbname.NormalizedUsername("tester"),
    43  				UID:  keybase1.MakeTestUID(16),
    44  			}, nil)
    45  	}
    46  	config.mockClock.EXPECT().Now().Return(time.Unix(0, 0)).AnyTimes()
    47  	config.mockRep.EXPECT().
    48  		NotifyFavoritesChanged(gomock.Any()).Return().AnyTimes()
    49  
    50  	return mockCtrl, config, context.Background()
    51  }
    52  
    53  func favTestShutdown(t *testing.T, mockCtrl *gomock.Controller,
    54  	config *ConfigMock, f *Favorites) {
    55  	if err := f.Shutdown(); err != nil {
    56  		t.Errorf("Couldn't shut down favorites: %v", err)
    57  	}
    58  	config.ctr.CheckForFailures()
    59  	mockCtrl.Finish()
    60  }
    61  
    62  func TestFavoritesAddTwice(t *testing.T) {
    63  	mockCtrl, config, ctx := favTestInit(t, false)
    64  	f := NewFavorites(config)
    65  	f.InitForTest()
    66  	defer favTestShutdown(t, mockCtrl, config, f)
    67  
    68  	// Call Add twice in a row, but only get one Add KBPKI call
    69  	fav1 := favorites.ToAdd{
    70  		Folder: favorites.Folder{
    71  			Name: "test",
    72  			Type: tlf.Public,
    73  		},
    74  		Data:    favorites.Data{},
    75  		Created: false,
    76  	}
    77  	config.mockKbpki.EXPECT().FavoriteAdd(gomock.Any(), fav1.ToKBFolderHandle()).
    78  		Return(nil)
    79  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).
    80  		Return(keybase1.FavoritesResult{
    81  			FavoriteFolders: []keybase1.Folder{favToAddToKBFolder(fav1)},
    82  		}, nil)
    83  	if err := f.Add(ctx, fav1); err != nil {
    84  		t.Fatalf("Couldn't add favorite: %v", err)
    85  	}
    86  
    87  	// A second add shouldn't result in a KBPKI call
    88  	if err := f.Add(ctx, fav1); err != nil {
    89  		t.Fatalf("Couldn't re-add same favorite: %v", err)
    90  	}
    91  }
    92  
    93  func TestFavoriteAddCreatedAlwaysGoThrough(t *testing.T) {
    94  	mockCtrl, config, ctx := favTestInit(t, false)
    95  	f := NewFavorites(config)
    96  	f.InitForTest()
    97  	defer favTestShutdown(t, mockCtrl, config, f)
    98  
    99  	fav1 := favorites.ToAdd{
   100  		Folder: favorites.Folder{
   101  			Name: "test",
   102  			Type: tlf.Public,
   103  		},
   104  		Data:    favorites.Data{},
   105  		Created: false,
   106  	}
   107  	expected1 := keybase1.FolderHandle{
   108  		Name:       "test",
   109  		FolderType: keybase1.FolderType_PUBLIC,
   110  		Created:    false,
   111  	}
   112  	config.mockKbpki.EXPECT().FavoriteAdd(gomock.Any(), expected1).Return(nil)
   113  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).Return(keybase1.FavoritesResult{
   114  		FavoriteFolders: []keybase1.Folder{favToAddToKBFolder(fav1)},
   115  	}, nil)
   116  	if err := f.Add(ctx, fav1); err != nil {
   117  		t.Fatalf("Couldn't add favorite: %v", err)
   118  	}
   119  
   120  	fav2 := favorites.ToAdd{
   121  		Folder: favorites.Folder{
   122  			Name: "test",
   123  			Type: tlf.Public,
   124  		},
   125  		Data:    favorites.Data{},
   126  		Created: true,
   127  	}
   128  	expected2 := keybase1.FolderHandle{
   129  		Name:       "test",
   130  		FolderType: keybase1.FolderType_PUBLIC,
   131  		Created:    true,
   132  	}
   133  	config.mockKbpki.EXPECT().FavoriteAdd(gomock.Any(), expected2).Return(nil)
   134  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).Return(keybase1.FavoritesResult{
   135  		FavoriteFolders: []keybase1.Folder{favToAddToKBFolder(fav2)},
   136  	}, nil)
   137  	if err := f.Add(ctx, fav2); err != nil {
   138  		t.Fatalf("Couldn't add favorite: %v", err)
   139  	}
   140  }
   141  
   142  func TestFavoritesAddCreated(t *testing.T) {
   143  	mockCtrl, config, ctx := favTestInit(t, false)
   144  	f := NewFavorites(config)
   145  	f.InitForTest()
   146  	defer favTestShutdown(t, mockCtrl, config, f)
   147  
   148  	// Call Add with created = true
   149  	fav1 := favorites.ToAdd{
   150  		Folder: favorites.Folder{
   151  			Name: "test",
   152  			Type: tlf.Public,
   153  		},
   154  		Data:    favorites.Data{},
   155  		Created: true,
   156  	}
   157  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).Return(keybase1.FavoritesResult{}, nil)
   158  	expected := keybase1.FolderHandle{
   159  		Name:       "test",
   160  		FolderType: keybase1.FolderType_PUBLIC,
   161  		Created:    true,
   162  	}
   163  	config.mockKbpki.EXPECT().FavoriteAdd(gomock.Any(), expected).
   164  		Return(nil)
   165  	if err := f.Add(ctx, fav1); err != nil {
   166  		t.Fatalf("Couldn't add favorite: %v", err)
   167  	}
   168  }
   169  
   170  func TestFavoritesAddRemoveAdd(t *testing.T) {
   171  	mockCtrl, config, ctx := favTestInit(t, false)
   172  	f := NewFavorites(config)
   173  	f.InitForTest()
   174  	defer favTestShutdown(t, mockCtrl, config, f)
   175  
   176  	fav1 := favorites.ToAdd{
   177  		Folder: favorites.Folder{
   178  			Name: "test",
   179  			Type: tlf.Public,
   180  		},
   181  		Data:    favorites.Data{},
   182  		Created: false,
   183  	}
   184  
   185  	config.mockKbpki.EXPECT().FavoriteAdd(gomock.Any(), fav1.ToKBFolderHandle()).
   186  		Return(nil)
   187  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).Return(keybase1.FavoritesResult{
   188  		FavoriteFolders: []keybase1.Folder{favToAddToKBFolder(fav1)},
   189  	}, nil)
   190  	if err := f.Add(ctx, fav1); err != nil {
   191  		t.Fatalf("Couldn't add favorite: %v", err)
   192  	}
   193  
   194  	config.mockKbpki.EXPECT().FavoriteDelete(gomock.Any(), fav1.ToKBFolderHandle()).
   195  		Return(nil)
   196  	if err := f.Delete(ctx, fav1.Folder); err != nil {
   197  		t.Fatalf("Couldn't delete favorite: %v", err)
   198  	}
   199  
   200  	config.mockKbpki.EXPECT().FavoriteAdd(gomock.Any(), fav1.ToKBFolderHandle()).
   201  		Return(nil)
   202  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).Return(keybase1.FavoritesResult{
   203  		FavoriteFolders: []keybase1.Folder{favToAddToKBFolder(fav1)},
   204  	}, nil)
   205  	config.mockKbfs.EXPECT().RefreshEditHistory(gomock.Any()).Return()
   206  	if err := f.Add(ctx, fav1); err != nil {
   207  		t.Fatalf("Couldn't re-add same favorite: %v", err)
   208  	}
   209  }
   210  
   211  func TestFavoritesAddAsync(t *testing.T) {
   212  	mockCtrl, config, ctx := favTestInit(t, false)
   213  	// Only one task at a time
   214  	f := newFavoritesWithChan(config, make(chan *favReq, 1))
   215  	f.InitForTest()
   216  	defer favTestShutdown(t, mockCtrl, config, f)
   217  
   218  	// Call Add twice in a row, but only get one Add KBPKI call
   219  	fav1 := favorites.ToAdd{
   220  		Folder: favorites.Folder{
   221  			Name: "test",
   222  			Type: tlf.Public,
   223  		},
   224  		Data:    favorites.Data{},
   225  		Created: false,
   226  	}
   227  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).Return(keybase1.FavoritesResult{}, nil)
   228  
   229  	c := make(chan struct{})
   230  	// Block until there are multiple outstanding calls
   231  	config.mockKbpki.EXPECT().FavoriteAdd(gomock.Any(), fav1.ToKBFolderHandle()).
   232  		Do(func(_ context.Context, _ keybase1.FolderHandle) {
   233  			<-c
   234  		}).Return(nil)
   235  
   236  	// There should only be one FavoriteAdd call for all of these, and
   237  	// none of them should block.
   238  	f.AddAsync(ctx, fav1)
   239  	f.AddAsync(ctx, fav1)
   240  	f.AddAsync(ctx, fav1)
   241  	f.AddAsync(ctx, fav1)
   242  	f.AddAsync(ctx, fav1)
   243  	c <- struct{}{}
   244  }
   245  
   246  func TestFavoritesListFailsDuringAddAsync(t *testing.T) {
   247  	mockCtrl, config, ctx := favTestInit(t, false)
   248  	// Only one task at a time
   249  	f := newFavoritesWithChan(config, make(chan *favReq, 1))
   250  	f.InitForTest()
   251  	defer favTestShutdown(t, mockCtrl, config, f)
   252  
   253  	// Call Add twice in a row, but only get one Add KBPKI call
   254  	fav1 := favorites.ToAdd{
   255  		Folder: favorites.Folder{
   256  			Name: "test",
   257  			Type: tlf.Public,
   258  		},
   259  		Data:    favorites.Data{},
   260  		Created: false,
   261  	}
   262  
   263  	config.mockKbpki.EXPECT().FavoriteAdd(gomock.Any(), fav1.ToKBFolderHandle()).Return(nil)
   264  	// Cancel the first list request
   265  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).Return(keybase1.
   266  		FavoritesResult{}, context.Canceled)
   267  
   268  	f.AddAsync(ctx, fav1) // this will fail
   269  	// Wait so the next one doesn't get batched together with this one
   270  	if err := f.wg.Wait(context.Background()); err != nil {
   271  		t.Fatalf("Couldn't wait on favorites: %v", err)
   272  	}
   273  
   274  	// Now make sure the second time around, the favorites get listed
   275  	// and one gets added, even if its context gets added
   276  	c := make(chan struct{})
   277  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).Return(keybase1.FavoritesResult{}, nil)
   278  	config.mockKbpki.EXPECT().FavoriteAdd(gomock.Any(), fav1.ToKBFolderHandle()).
   279  		Do(func(_ context.Context, _ keybase1.FolderHandle) {
   280  			c <- struct{}{}
   281  		}).Return(nil)
   282  
   283  	f.AddAsync(ctx, fav1) // should work
   284  	<-c
   285  }
   286  
   287  func TestFavoritesControlUserHistory(t *testing.T) {
   288  	mockCtrl, config, ctx := favTestInit(t, false)
   289  	f := NewFavorites(config)
   290  	f.Initialize(ctx)
   291  	defer favTestShutdown(t, mockCtrl, config, f)
   292  
   293  	config.mockKbpki.EXPECT().FavoriteAdd(gomock.Any(), gomock.Any()).
   294  		Return(nil)
   295  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).
   296  		Return(keybase1.FavoritesResult{}, nil)
   297  	config.mockKbs.EXPECT().EncryptFavorites(gomock.Any(),
   298  		gomock.Any()).Return(nil, nil)
   299  	config.mockCodec.EXPECT().Encode(gomock.Any()).Return(nil, nil).Times(2)
   300  	config.mockKbpki.EXPECT().FavoriteDelete(gomock.Any(), gomock.Any()).
   301  		Return(nil)
   302  
   303  	username := "bob"
   304  	tlfName := "alice,bob"
   305  	tlfType := tlf.Private
   306  
   307  	// Add a favorite.
   308  	err := f.Add(ctx, favorites.ToAdd{
   309  		Folder: favorites.Folder{
   310  			Name: tlfName,
   311  			Type: tlfType,
   312  		},
   313  		Created: true})
   314  	require.NoError(t, err)
   315  
   316  	// Put a thing in user history.
   317  	history := kbfsedits.NewTlfHistory()
   318  	_, err = history.AddNotifications(username, []string{"hello"})
   319  	require.NoError(t, err)
   320  	config.UserHistory().UpdateHistory(tlf.CanonicalName(tlfName), tlfType,
   321  		history, username)
   322  
   323  	// Delete the favorite.
   324  	err = f.Delete(ctx, favorites.Folder{Name: tlfName, Type: tlfType})
   325  	require.NoError(t, err)
   326  
   327  	// Verify that the user history is now empty.
   328  	userHistory := config.UserHistory().Get(username)
   329  	require.Empty(t, userHistory)
   330  }
   331  
   332  func TestFavoritesGetAll(t *testing.T) {
   333  	mockCtrl, config, ctx := favTestInit(t, false)
   334  	f := NewFavorites(config)
   335  	f.Initialize(ctx)
   336  	defer favTestShutdown(t, mockCtrl, config, f)
   337  
   338  	// Prep
   339  	teamID := keybase1.MakeTestTeamID(0xdeadbeef, false)
   340  	fol := keybase1.Folder{
   341  		Name:       "fake folder",
   342  		Private:    true,
   343  		Created:    false,
   344  		FolderType: keybase1.FolderType_TEAM,
   345  		TeamID:     &teamID,
   346  	}
   347  	teamID2 := keybase1.MakeTestTeamID(0xabcdef, true)
   348  	fol2 := keybase1.Folder{
   349  		Name:       "another folder",
   350  		Private:    false,
   351  		Created:    false,
   352  		FolderType: keybase1.FolderType_PUBLIC,
   353  		TeamID:     &teamID2,
   354  	}
   355  	teamID3 := keybase1.MakeTestTeamID(0x87654321, false)
   356  	fol3 := keybase1.Folder{
   357  		Name:       "folder three",
   358  		Private:    true,
   359  		Created:    false,
   360  		FolderType: keybase1.FolderType_PRIVATE,
   361  		TeamID:     &teamID3,
   362  	}
   363  	res := keybase1.FavoritesResult{
   364  		IgnoredFolders:  []keybase1.Folder{fol},
   365  		FavoriteFolders: []keybase1.Folder{fol2},
   366  		NewFolders:      []keybase1.Folder{fol3},
   367  	}
   368  	// Mock out the API server.
   369  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).Return(res, nil)
   370  	config.mockCodec.EXPECT().Encode(gomock.Any()).Return(nil, nil).Times(2)
   371  	config.mockKbs.EXPECT().EncryptFavorites(gomock.Any(),
   372  		gomock.Any()).Return(nil, nil)
   373  
   374  	// Require that we correctly return the data inserted into the cache by
   375  	// the server.
   376  	res2, err := f.GetAll(ctx)
   377  	require.NoError(t, err)
   378  	require.Equal(t, res.IgnoredFolders, res2.IgnoredFolders)
   379  	require.Equal(t, res.NewFolders, res2.NewFolders)
   380  
   381  	// Favorites will have 2 extra: the home TLFs
   382  	require.Len(t, res2.FavoriteFolders, len(res.FavoriteFolders)+2)
   383  	for _, folder := range res.FavoriteFolders {
   384  		found := false
   385  		for _, fav := range res2.FavoriteFolders {
   386  			if reflect.DeepEqual(fav, folder) {
   387  				found = true
   388  			}
   389  		}
   390  		require.True(t, found, "Folder: %v", folder)
   391  	}
   392  }
   393  
   394  func TestFavoritesDiskCache(t *testing.T) {
   395  	mockCtrl, config, ctx := favTestInit(t, true)
   396  
   397  	// EXPECT this manually so that we can manually edit the leveldb later
   398  	config.mockKbpki.EXPECT().GetCurrentSession(gomock.
   399  		Any()).Times(3).
   400  		Return(idutil.SessionInfo{
   401  			Name: kbname.NormalizedUsername("tester"),
   402  			UID:  keybase1.MakeTestUID(16),
   403  		}, nil)
   404  
   405  	f := NewFavorites(config)
   406  
   407  	f.Initialize(ctx)
   408  
   409  	// Add a favorite. Expect that it will be encoded to disk.
   410  	fav1 := favorites.Folder{Name: "test", Type: tlf.Public}
   411  	fav1Add := favorites.ToAdd{
   412  		Folder:  fav1,
   413  		Data:    favorites.Data{},
   414  		Created: false,
   415  	}
   416  
   417  	var decodedData favoritesCacheForDisk
   418  	var decodedDataFromDisk favoritesCacheEncryptedForDisk
   419  	encodedData := []byte("encoded data")
   420  	encryptedData := []byte("encrypted data")
   421  	diskData := []byte("disk data")
   422  	config.mockKbpki.EXPECT().FavoriteAdd(gomock.Any(), gomock.Any()).Return(nil)
   423  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).Return(keybase1.FavoritesResult{
   424  		FavoriteFolders: []keybase1.Folder{favToAddToKBFolder(fav1Add)},
   425  	}, nil)
   426  	config.mockCodec.EXPECT().Encode(gomock.Any()).Do(func(
   427  		f favoritesCacheForDisk) {
   428  		decodedData = f
   429  	}).Return(
   430  		encodedData,
   431  		nil)
   432  	config.mockKbs.EXPECT().EncryptFavorites(gomock.Any(),
   433  		encodedData).Return(encryptedData, nil)
   434  	config.mockCodec.EXPECT().Encode(gomock.Any()).Do(func(
   435  		f favoritesCacheEncryptedForDisk) {
   436  		decodedDataFromDisk = f
   437  	}).Return(
   438  		diskData,
   439  		nil)
   440  
   441  	err := f.Add(ctx, fav1Add)
   442  	require.NoError(t, err)
   443  
   444  	key := []byte(string(keybase1.MakeTestUID(16)))
   445  	dataInLeveldb, err := f.diskCache.Get(key, nil)
   446  	require.NoError(t, err)
   447  
   448  	// Shut down the favorites cache to remove the favorites from memory.
   449  	err = f.Shutdown()
   450  	require.NoError(t, err)
   451  
   452  	// EXPECT this manually so that we can manually edit the leveldb
   453  	config.mockKbpki.EXPECT().GetCurrentSession(gomock.
   454  		Any()).Times(1).
   455  		Return(idutil.SessionInfo{
   456  			Name: kbname.NormalizedUsername("tester"),
   457  			UID:  keybase1.MakeTestUID(16),
   458  		}, nil).Do(func(_ context.Context) {
   459  		err := f.diskCache.Put(key, dataInLeveldb, nil)
   460  		require.NoError(t, err)
   461  	})
   462  
   463  	// Make a new favorites cache.
   464  	f = NewFavorites(config)
   465  
   466  	// Initialize it from the data we just wrote to disk.
   467  	config.mockCodec.EXPECT().Decode(diskData,
   468  		gomock.Any()).Do(func(_ []byte, disk *favoritesCacheEncryptedForDisk) {
   469  		*disk = decodedDataFromDisk
   470  	}).Return(nil)
   471  	config.mockKbs.EXPECT().DecryptFavorites(gomock.Any(),
   472  		encryptedData).Return(encodedData, nil)
   473  	config.mockCodec.EXPECT().Decode(encodedData,
   474  		gomock.Any()).Do(func(_ []byte, disk *favoritesCacheForDisk) {
   475  		*disk = decodedData
   476  	}).Return(nil)
   477  
   478  	// Pretend we are offline and cannot retrieve favorites right now.
   479  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).Return(keybase1.
   480  		FavoritesResult{}, errDisconnected{})
   481  	f.Initialize(ctx)
   482  
   483  	// Ensure that the favorite we added before is still present.
   484  	// There should be three favorites total, including the home TLFs.
   485  	faves, err := f.Get(ctx)
   486  	require.NoError(t, err)
   487  	require.Equal(t, len(faves), 3)
   488  	require.Contains(t, faves, fav1)
   489  
   490  	// This line not deferred because we need to swap out Favorites instances
   491  	// above.
   492  	favTestShutdown(t, mockCtrl, config, f)
   493  }
   494  
   495  func TestFavoritesRefreshCacheWhenMtimeChanged(t *testing.T) {
   496  	mockCtrl, config, ctx := favTestInit(t, false)
   497  	f := NewFavorites(config)
   498  	f.bufferedInterval = 1 * time.Millisecond
   499  	f.InitForTest()
   500  	defer favTestShutdown(t, mockCtrl, config, f)
   501  
   502  	fav1 := favorites.ToAdd{
   503  		Folder: favorites.Folder{
   504  			Name: "test",
   505  			Type: tlf.Public,
   506  		},
   507  		Data:    favorites.Data{},
   508  		Created: false,
   509  	}
   510  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).
   511  		Return(keybase1.FavoritesResult{
   512  			FavoriteFolders: []keybase1.Folder{favToAddToKBFolder(fav1)},
   513  		}, nil)
   514  
   515  	t.Log("Refresh first time")
   516  	id := tlf.FakeID(1, fav1.Folder.Type)
   517  	f.RefreshCacheWhenMTimeChanged(ctx, id)
   518  	err := f.bufferedWg.Wait(ctx)
   519  	require.NoError(t, err)
   520  
   521  	t.Log("Refresh second time, no API call")
   522  	f.RefreshCacheWhenMTimeChanged(ctx, id)
   523  	err = f.bufferedWg.Wait(ctx)
   524  	require.NoError(t, err)
   525  
   526  	t.Log("A regular refresh should clear the state")
   527  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).
   528  		Return(keybase1.FavoritesResult{
   529  			FavoriteFolders: []keybase1.Folder{favToAddToKBFolder(fav1)},
   530  		}, nil)
   531  	f.RefreshCache(ctx, FavoritesRefreshModeBlocking)
   532  	err = f.wg.Wait(ctx)
   533  	require.NoError(t, err)
   534  
   535  	t.Log("Refresh third time, which should cause an API call again")
   536  	config.mockKbpki.EXPECT().FavoriteList(gomock.Any()).
   537  		Return(keybase1.FavoritesResult{
   538  			FavoriteFolders: []keybase1.Folder{favToAddToKBFolder(fav1)},
   539  		}, nil)
   540  	f.RefreshCacheWhenMTimeChanged(ctx, id)
   541  	err = f.bufferedWg.Wait(ctx)
   542  	require.NoError(t, err)
   543  }