github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libkbfs/test_common.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  	"fmt"
     9  	"net"
    10  	"os"
    11  	"time"
    12  
    13  	"github.com/keybase/client/go/externals"
    14  	"github.com/keybase/client/go/kbfs/data"
    15  	"github.com/keybase/client/go/kbfs/env"
    16  	"github.com/keybase/client/go/kbfs/idutil"
    17  	"github.com/keybase/client/go/kbfs/kbfscrypto"
    18  	"github.com/keybase/client/go/kbfs/kbfsmd"
    19  	"github.com/keybase/client/go/kbfs/libkey"
    20  	"github.com/keybase/client/go/kbfs/tlf"
    21  	"github.com/keybase/client/go/kbfs/tlfhandle"
    22  	kbname "github.com/keybase/client/go/kbun"
    23  	"github.com/keybase/client/go/libkb"
    24  	"github.com/keybase/client/go/logger"
    25  	"github.com/keybase/client/go/protocol/keybase1"
    26  	"github.com/keybase/go-framed-msgpack-rpc/rpc"
    27  	"github.com/pkg/errors"
    28  	"github.com/stretchr/testify/assert"
    29  	"golang.org/x/net/context"
    30  )
    31  
    32  const (
    33  	// EnvTestMDServerAddr is the environment variable name for an
    34  	// mdserver address.
    35  	EnvTestMDServerAddr = "KEYBASE_TEST_MDSERVER_ADDR"
    36  	// EnvTestBServerAddr is the environment variable name for a block
    37  	// server address.
    38  	EnvTestBServerAddr = "KEYBASE_TEST_BSERVER_ADDR"
    39  	// TempdirServerAddr is the special value of the
    40  	// EnvTest{B,MD}ServerAddr environment value to signify that
    41  	// an on-disk implementation of the {b,md}server should be
    42  	// used with a temporary directory.
    43  	TempdirServerAddr = "tempdir"
    44  )
    45  
    46  // newConfigForTest returns a ConfigLocal object suitable for use by
    47  // MakeTestConfigOrBust or ConfigAsUser.
    48  //
    49  // TODO: Move more common code here.
    50  func newConfigForTest(modeType InitModeType, loggerFn func(module string) logger.Logger) *ConfigLocal {
    51  	mode := modeTest{NewInitModeFromType(modeType)}
    52  	g := &libkb.GlobalContext{
    53  		// Env is needed by simplefs.
    54  		Env: libkb.NewEnv(nil, nil, func() logger.Logger {
    55  			return loggerFn("G")
    56  		}),
    57  	}
    58  	g.MobileAppState = libkb.NewMobileAppState(g)
    59  	config := NewConfigLocal(mode, loggerFn, "", DiskCacheModeOff, env.NewContextFromGlobalContext(g))
    60  	config.SetVLogLevel(libkb.VLog1String)
    61  
    62  	bops := NewBlockOpsStandard(
    63  		config, testBlockRetrievalWorkerQueueSize, testPrefetchWorkerQueueSize,
    64  		0, env.EmptyAppStateUpdater{})
    65  	config.SetBlockOps(bops)
    66  
    67  	bsplit, err := data.NewBlockSplitterSimpleExact(
    68  		64*1024, 64*1024/int(data.BPSize), 8*1024)
    69  	if err != nil {
    70  		panic(err)
    71  	}
    72  	err = bsplit.SetMaxDirEntriesByBlockSize(config.Codec())
    73  	if err != nil {
    74  		panic(err)
    75  	}
    76  	config.SetBlockSplitter(bsplit)
    77  
    78  	return config
    79  }
    80  
    81  // MakeTestBlockServerOrBust makes a block server from the given
    82  // arguments and environment variables.
    83  func MakeTestBlockServerOrBust(t logger.TestLogBackend, c *ConfigLocal,
    84  	config blockServerRemoteConfig,
    85  	rpcLogFactory rpc.LogFactory) BlockServer {
    86  	// see if a local remote server is specified
    87  	bserverAddr := os.Getenv(EnvTestBServerAddr)
    88  	switch {
    89  	case bserverAddr == TempdirServerAddr:
    90  		var err error
    91  		blockServer, err := NewBlockServerTempDir(config.Codec(), config.MakeLogger(""))
    92  		if err != nil {
    93  			t.Fatal(err)
    94  		}
    95  		return blockServer
    96  
    97  	case len(bserverAddr) != 0:
    98  		remote, err := rpc.ParsePrioritizedRoundRobinRemote(bserverAddr)
    99  		if err != nil {
   100  			t.Fatal(err)
   101  		}
   102  		return NewBlockServerRemote(c.kbCtx, config, remote, rpcLogFactory)
   103  
   104  	default:
   105  		return NewBlockServerMemory(config.MakeLogger(""))
   106  	}
   107  }
   108  
   109  // TODO: Put the below code (also duplicated in kbfs-server) somewhere
   110  // in rpc and use that instead.
   111  
   112  type testLogger interface {
   113  	Logf(format string, args ...interface{})
   114  }
   115  
   116  type testLogOutput struct {
   117  	t testLogger
   118  }
   119  
   120  func (t testLogOutput) log(ch string, fmts string, args []interface{}) {
   121  	fmts = fmt.Sprintf("[%s] %s", ch, fmts)
   122  	t.t.Logf(fmts, args...)
   123  }
   124  
   125  func (t testLogOutput) Info(fmt string, args ...interface{})    { t.log("I", fmt, args) }
   126  func (t testLogOutput) Error(fmt string, args ...interface{})   { t.log("E", fmt, args) }
   127  func (t testLogOutput) Debug(fmt string, args ...interface{})   { t.log("D", fmt, args) }
   128  func (t testLogOutput) Warning(fmt string, args ...interface{}) { t.log("W", fmt, args) }
   129  func (t testLogOutput) Profile(fmt string, args ...interface{}) { t.log("P", fmt, args) }
   130  
   131  func newTestRPCLogFactory(t testLogger) rpc.LogFactory {
   132  	return rpc.NewSimpleLogFactory(testLogOutput{t}, nil)
   133  }
   134  
   135  // MakeTestConfigOrBustLoggedInWithMode creates and returns a config
   136  // suitable for unit-testing with the given mode and list of
   137  // users. loggedInIndex specifies the index (in the list) of the user
   138  // being logged in.
   139  func MakeTestConfigOrBustLoggedInWithMode(
   140  	t logger.TestLogBackend, loggedInIndex int,
   141  	mode InitModeType, users ...kbname.NormalizedUsername) *ConfigLocal {
   142  	log := logger.NewTestLogger(t)
   143  	config := newConfigForTest(mode, func(m string) logger.Logger {
   144  		return log
   145  	})
   146  
   147  	initDoneCh := make(chan struct{})
   148  	kbfsOps := NewKBFSOpsStandard(
   149  		env.EmptyAppStateUpdater{}, config, initDoneCh)
   150  	defer close(initDoneCh)
   151  	config.SetKBFSOps(kbfsOps)
   152  	config.SetNotifier(kbfsOps)
   153  
   154  	config.SetKeyManager(NewKeyManagerStandard(config))
   155  	config.SetMDOps(NewMDOpsStandard(config))
   156  
   157  	localUsers := idutil.MakeLocalUsers(users)
   158  	loggedInUser := localUsers[loggedInIndex]
   159  
   160  	daemon := NewKeybaseDaemonMemory(loggedInUser.UID, localUsers, nil,
   161  		config.Codec())
   162  	config.SetKeybaseService(daemon)
   163  	config.SetChat(newChatLocal(config))
   164  
   165  	kbpki := NewKBPKIClient(config, config.MakeLogger(""))
   166  	config.SetKBPKI(kbpki)
   167  
   168  	kbfsOps.favs.Initialize(context.TODO())
   169  
   170  	signingKey := idutil.MakeLocalUserSigningKeyOrBust(loggedInUser.Name)
   171  	cryptPrivateKey := idutil.MakeLocalUserCryptPrivateKeyOrBust(
   172  		loggedInUser.Name)
   173  	crypto := NewCryptoLocal(
   174  		config.Codec(), signingKey, cryptPrivateKey, config)
   175  	config.SetCrypto(crypto)
   176  
   177  	blockServer := MakeTestBlockServerOrBust(
   178  		t, config, config, newTestRPCLogFactory(t))
   179  	config.SetBlockServer(blockServer)
   180  
   181  	// see if a local remote server is specified
   182  	mdServerAddr := os.Getenv(EnvTestMDServerAddr)
   183  	var mdServer MDServer
   184  	var keyServer libkey.KeyServer
   185  	switch {
   186  	case mdServerAddr == TempdirServerAddr:
   187  		var err error
   188  		mdServer, err = NewMDServerTempDir(
   189  			mdServerLocalConfigAdapter{config})
   190  		if err != nil {
   191  			t.Fatal(err)
   192  		}
   193  		keyServer, err = libkey.NewKeyServerTempDir(
   194  			keyOpsConfigWrapper{config}, log)
   195  		if err != nil {
   196  			t.Fatal(err)
   197  		}
   198  
   199  	case len(mdServerAddr) != 0:
   200  		remote, err := rpc.ParsePrioritizedRoundRobinRemote(mdServerAddr)
   201  		if err != nil {
   202  			t.Fatal(err)
   203  		}
   204  		// connect to server
   205  		mdServer = NewMDServerRemote(config.kbCtx, config, remote, newTestRPCLogFactory(t))
   206  		// for now the MD server acts as the key server in production
   207  		keyServer = mdServer.(*MDServerRemote)
   208  
   209  	default:
   210  		var err error
   211  		// create in-memory server shim
   212  		mdServer, err = NewMDServerMemory(
   213  			mdServerLocalConfigAdapter{config})
   214  		if err != nil {
   215  			t.Fatal(err)
   216  		}
   217  		// shim for the key server too
   218  		keyServer, err = libkey.NewKeyServerMemory(
   219  			keyOpsConfigWrapper{config}, log)
   220  		if err != nil {
   221  			t.Fatal(err)
   222  		}
   223  	}
   224  	config.SetMDServer(mdServer)
   225  	config.SetKeyServer(keyServer)
   226  
   227  	// turn off background flushing by default during tests
   228  	config.noBGFlush = true
   229  
   230  	configs := []Config{config}
   231  	config.allKnownConfigsForTesting = &configs
   232  
   233  	return config
   234  }
   235  
   236  // MakeTestConfigOrBustLoggedIn creates and returns a config suitable for
   237  // unit-testing with the given list of users. loggedInIndex specifies the
   238  // index (in the list) of the user being logged in.
   239  func MakeTestConfigOrBustLoggedIn(t logger.TestLogBackend, loggedInIndex int,
   240  	users ...kbname.NormalizedUsername) *ConfigLocal {
   241  	return MakeTestConfigOrBustLoggedInWithMode(
   242  		t, loggedInIndex, InitDefault, users...)
   243  }
   244  
   245  // MakeTestConfigOrBust creates and returns a config suitable for
   246  // unit-testing with the given list of users.
   247  func MakeTestConfigOrBust(t logger.TestLogBackend,
   248  	users ...kbname.NormalizedUsername) *ConfigLocal {
   249  	return MakeTestConfigOrBustLoggedIn(t, 0, users...)
   250  }
   251  
   252  // ConfigAsUserWithMode clones a test configuration in the given mode,
   253  // setting another user as the logged in user.  Journaling will not be
   254  // enabled in the returned Config, regardless of the journal status in
   255  // `config`.
   256  func ConfigAsUserWithMode(config *ConfigLocal,
   257  	loggedInUser kbname.NormalizedUsername, mode InitModeType) *ConfigLocal {
   258  	c := newConfigForTest(mode, config.loggerFn)
   259  	c.SetMetadataVersion(config.MetadataVersion())
   260  	c.SetRekeyWithPromptWaitTime(config.RekeyWithPromptWaitTime())
   261  
   262  	initDoneCh := make(chan struct{})
   263  	kbfsOps := NewKBFSOpsStandard(env.EmptyAppStateUpdater{}, c, initDoneCh)
   264  	defer close(initDoneCh)
   265  	c.SetKBFSOps(kbfsOps)
   266  	c.SetNotifier(kbfsOps)
   267  
   268  	c.SetKeyManager(NewKeyManagerStandard(c))
   269  	c.SetMDOps(NewMDOpsStandard(c))
   270  	c.SetClock(config.Clock())
   271  
   272  	if chatLocal, ok := config.Chat().(*chatLocal); ok {
   273  		c.SetChat(chatLocal.copy(c))
   274  	} else {
   275  		c.SetChat(config.Chat())
   276  	}
   277  
   278  	daemon := config.KeybaseService().(*KeybaseDaemonLocal)
   279  	loggedInUID, ok := daemon.GetIDForAssertion(string(loggedInUser))
   280  	if !ok {
   281  		panic("bad test: unknown user: " + loggedInUser)
   282  	}
   283  
   284  	localUsers := daemon.GetLocalUsers()
   285  	newDaemon := NewKeybaseDaemonMemory(
   286  		loggedInUID.AsUserOrBust(), localUsers, nil, c.Codec())
   287  	c.SetKeybaseService(newDaemon)
   288  	c.SetKBPKI(NewKBPKIClient(c, c.MakeLogger("")))
   289  	kbfsOps.favs.InitForTest()
   290  
   291  	signingKey := idutil.MakeLocalUserSigningKeyOrBust(loggedInUser)
   292  	cryptPrivateKey := idutil.MakeLocalUserCryptPrivateKeyOrBust(loggedInUser)
   293  	crypto := NewCryptoLocal(
   294  		config.Codec(), signingKey, cryptPrivateKey, config)
   295  	c.SetCrypto(crypto)
   296  	c.noBGFlush = config.noBGFlush
   297  
   298  	if s, ok := config.BlockServer().(*BlockServerRemote); ok {
   299  		remote, err := rpc.ParsePrioritizedRoundRobinRemote(s.RemoteAddress())
   300  		if err != nil {
   301  			panic(err)
   302  		}
   303  		blockServer := NewBlockServerRemote(c.kbCtx, c, remote, s.putConn.rpcLogFactory)
   304  		c.SetBlockServer(blockServer)
   305  	} else {
   306  		c.SetBlockServer(config.BlockServer())
   307  	}
   308  
   309  	// If journaling was on in `config`, disable it in `c`.
   310  	jManager, err := GetJournalManager(config)
   311  	if err == nil {
   312  		c.SetBlockServer(jManager.delegateBlockServer)
   313  	}
   314  
   315  	var mdServer MDServer
   316  	var keyServer libkey.KeyServer
   317  	if s, ok := config.MDServer().(*MDServerRemote); ok {
   318  		remote, err := rpc.ParsePrioritizedRoundRobinRemote(s.RemoteAddress())
   319  		if err != nil {
   320  			panic(err)
   321  		}
   322  		// connect to server
   323  		mdServer = NewMDServerRemote(c.kbCtx, c, remote, s.rpcLogFactory)
   324  		// for now the MD server also acts as the key server.
   325  		keyServer = mdServer.(*MDServerRemote)
   326  	} else {
   327  		// copy the existing mdServer but update the config
   328  		// this way the current device key is paired with
   329  		// the proper user yet the DB state is all shared.
   330  		mdServerToCopy := config.MDServer().(mdServerLocal)
   331  		mdServer = mdServerToCopy.copy(mdServerLocalConfigAdapter{c})
   332  
   333  		// use the same db but swap configs
   334  		keyServerToCopy := config.KeyServer().(*libkey.KeyServerLocal)
   335  		keyServer = keyServerToCopy.CopyWithConfigAndLogger(
   336  			keyOpsConfigWrapper{c}, c.MakeLogger(""))
   337  	}
   338  	c.SetMDServer(mdServer)
   339  	c.SetKeyServer(keyServer)
   340  
   341  	// Keep track of all the other configs in a shared slice.
   342  	c.allKnownConfigsForTesting = config.allKnownConfigsForTesting
   343  	*c.allKnownConfigsForTesting = append(*c.allKnownConfigsForTesting, c)
   344  
   345  	return c
   346  }
   347  
   348  // ConfigAsUser clones a test configuration in default init mode,
   349  // setting another user as the logged in user.  Journaling will not be
   350  // enabled in the returned Config, regardless of the journal status in
   351  // `config`.
   352  func ConfigAsUser(config *ConfigLocal,
   353  	loggedInUser kbname.NormalizedUsername) *ConfigLocal {
   354  	c := ConfigAsUserWithMode(config, loggedInUser, config.Mode().Type())
   355  	c.SetMode(config.mode) // preserve any unusual test mode wrappers
   356  	return c
   357  }
   358  
   359  // NewEmptyTLFWriterKeyBundle creates a new empty kbfsmd.TLFWriterKeyBundleV2
   360  func NewEmptyTLFWriterKeyBundle() kbfsmd.TLFWriterKeyBundleV2 {
   361  	return kbfsmd.TLFWriterKeyBundleV2{
   362  		WKeys: make(kbfsmd.UserDeviceKeyInfoMapV2),
   363  	}
   364  }
   365  
   366  // NewEmptyTLFReaderKeyBundle creates a new empty kbfsmd.TLFReaderKeyBundleV2
   367  func NewEmptyTLFReaderKeyBundle() kbfsmd.TLFReaderKeyBundleV2 {
   368  	return kbfsmd.TLFReaderKeyBundleV2{
   369  		RKeys: make(kbfsmd.UserDeviceKeyInfoMapV2),
   370  	}
   371  }
   372  
   373  func keySaltForUserDevice(name kbname.NormalizedUsername,
   374  	index int) kbname.NormalizedUsername {
   375  	if index > 0 {
   376  		// We can't include the device index when it's 0, because we
   377  		// have to match what's done in MakeLocalUsers.
   378  		return kbname.NormalizedUsername(string(name) + " " + fmt.Sprint(index))
   379  	}
   380  	return name
   381  }
   382  
   383  func makeFakeKeys(name kbname.NormalizedUsername, index int) (
   384  	kbfscrypto.CryptPublicKey, kbfscrypto.VerifyingKey) {
   385  	keySalt := keySaltForUserDevice(name, index)
   386  	newCryptPublicKey := idutil.MakeLocalUserCryptPublicKeyOrBust(keySalt)
   387  	newVerifyingKey := idutil.MakeLocalUserVerifyingKeyOrBust(keySalt)
   388  	return newCryptPublicKey, newVerifyingKey
   389  }
   390  
   391  // AddDeviceForLocalUserOrBust creates a new device for a user and
   392  // returns the index for that device.
   393  func AddDeviceForLocalUserOrBust(t logger.TestLogBackend, config Config,
   394  	uid keybase1.UID) int {
   395  	kbd, ok := config.KeybaseService().(*KeybaseDaemonLocal)
   396  	if !ok {
   397  		t.Fatal("Bad keybase daemon")
   398  	}
   399  
   400  	index, err := kbd.addDeviceForTesting(uid, makeFakeKeys)
   401  	if err != nil {
   402  		t.Fatal(err.Error())
   403  	}
   404  	return index
   405  }
   406  
   407  // RevokeDeviceForLocalUserOrBust revokes a device for a user in the
   408  // given index.
   409  func RevokeDeviceForLocalUserOrBust(t logger.TestLogBackend, config Config,
   410  	uid keybase1.UID, index int) {
   411  	kbd, ok := config.KeybaseService().(*KeybaseDaemonLocal)
   412  	if !ok {
   413  		t.Fatal("Bad keybase daemon")
   414  	}
   415  
   416  	if err := kbd.revokeDeviceForTesting(
   417  		config.Clock(), uid, index); err != nil {
   418  		t.Fatal(err.Error())
   419  	}
   420  }
   421  
   422  // SwitchDeviceForLocalUserOrBust switches the current user's current device
   423  func SwitchDeviceForLocalUserOrBust(t logger.TestLogBackend, config Config, index int) {
   424  	session, err := config.KBPKI().GetCurrentSession(context.Background())
   425  	if err != nil {
   426  		t.Fatalf("Couldn't get UID: %+v", err)
   427  	}
   428  
   429  	kbd, ok := config.KeybaseService().(*KeybaseDaemonLocal)
   430  	if !ok {
   431  		t.Fatal("Bad keybase daemon")
   432  	}
   433  
   434  	if err := kbd.switchDeviceForTesting(session.UID, index); err != nil {
   435  		t.Fatal(err.Error())
   436  	}
   437  
   438  	if _, ok := config.Crypto().(*CryptoLocal); !ok {
   439  		t.Fatal("Bad crypto")
   440  	}
   441  
   442  	keySalt := keySaltForUserDevice(session.Name, index)
   443  	signingKey := idutil.MakeLocalUserSigningKeyOrBust(keySalt)
   444  	cryptPrivateKey := idutil.MakeLocalUserCryptPrivateKeyOrBust(keySalt)
   445  	config.SetCrypto(
   446  		NewCryptoLocal(config.Codec(), signingKey, cryptPrivateKey, config))
   447  }
   448  
   449  // AddNewAssertionForTest makes newAssertion, which should be a single
   450  // assertion that doesn't already resolve to anything, resolve to the
   451  // same UID as oldAssertion, which should be an arbitrary assertion
   452  // that does already resolve to something.  It only applies to the
   453  // given config.
   454  func AddNewAssertionForTest(
   455  	config Config, oldAssertion, newAssertion string) error {
   456  	kbd, ok := config.KeybaseService().(*KeybaseDaemonLocal)
   457  	if !ok {
   458  		return errors.New("Bad keybase daemon")
   459  	}
   460  
   461  	uid, err := kbd.AddNewAssertionForTest(oldAssertion, newAssertion)
   462  	if err != nil {
   463  		return err
   464  	}
   465  
   466  	// Let the mdserver know about the name change
   467  	md, ok := config.MDServer().(mdServerLocal)
   468  	if !ok {
   469  		return errors.New("Bad md server")
   470  	}
   471  	// If this function is called multiple times for different
   472  	// configs, it may end up invoking the following call more than
   473  	// once on the shared md databases.  That's ok though, it's an
   474  	// idempotent call.
   475  	newSocialAssertion, ok := externals.NormalizeSocialAssertionStatic(context.Background(), newAssertion)
   476  	if !ok {
   477  		return errors.Errorf("%s couldn't be parsed as a social assertion", newAssertion)
   478  	}
   479  	if err := md.addNewAssertionForTest(uid, newSocialAssertion); err != nil {
   480  		return errors.Errorf("Couldn't update md server: %+v", err)
   481  	}
   482  	return nil
   483  }
   484  
   485  // AddNewAssertionForTestOrBust is like AddNewAssertionForTest, but
   486  // dies if there's an error.
   487  func AddNewAssertionForTestOrBust(t logger.TestLogBackend, config Config,
   488  	oldAssertion, newAssertion string) {
   489  	err := AddNewAssertionForTest(config, oldAssertion, newAssertion)
   490  	if err != nil {
   491  		t.Fatal(err)
   492  	}
   493  }
   494  
   495  // AddTeamWriterForTest makes the given user a team writer.
   496  func AddTeamWriterForTest(
   497  	config Config, tid keybase1.TeamID, uid keybase1.UID) error {
   498  	kbd, ok := config.KeybaseService().(*KeybaseDaemonLocal)
   499  	if !ok {
   500  		return errors.New("Bad keybase daemon")
   501  	}
   502  
   503  	return kbd.addTeamWriterForTest(tid, uid)
   504  }
   505  
   506  // AddTeamWriterForTestOrBust is like AddTeamWriterForTest, but
   507  // dies if there's an error.
   508  func AddTeamWriterForTestOrBust(t logger.TestLogBackend, config Config,
   509  	tid keybase1.TeamID, uid keybase1.UID) {
   510  	err := AddTeamWriterForTest(config, tid, uid)
   511  	if err != nil {
   512  		t.Fatal(err)
   513  	}
   514  }
   515  
   516  // RemoveTeamWriterForTest removes the given user from a team.
   517  func RemoveTeamWriterForTest(
   518  	config Config, tid keybase1.TeamID, uid keybase1.UID) error {
   519  	kbd, ok := config.KeybaseService().(*KeybaseDaemonLocal)
   520  	if !ok {
   521  		return errors.New("Bad keybase daemon")
   522  	}
   523  
   524  	return kbd.removeTeamWriterForTest(tid, uid)
   525  }
   526  
   527  // RemoveTeamWriterForTestOrBust is like RemoveTeamWriterForTest, but
   528  // dies if there's an error.
   529  func RemoveTeamWriterForTestOrBust(t logger.TestLogBackend, config Config,
   530  	tid keybase1.TeamID, uid keybase1.UID) {
   531  	err := RemoveTeamWriterForTest(config, tid, uid)
   532  	if err != nil {
   533  		t.Fatal(err)
   534  	}
   535  }
   536  
   537  // AddTeamReaderForTest makes the given user a team reader.
   538  func AddTeamReaderForTest(
   539  	config Config, tid keybase1.TeamID, uid keybase1.UID) error {
   540  	kbd, ok := config.KeybaseService().(*KeybaseDaemonLocal)
   541  	if !ok {
   542  		return errors.New("Bad keybase daemon")
   543  	}
   544  
   545  	return kbd.addTeamReaderForTest(tid, uid)
   546  }
   547  
   548  // AddTeamReaderForTestOrBust is like AddTeamWriterForTest, but
   549  // dies if there's an error.
   550  func AddTeamReaderForTestOrBust(t logger.TestLogBackend, config Config,
   551  	tid keybase1.TeamID, uid keybase1.UID) {
   552  	err := AddTeamReaderForTest(config, tid, uid)
   553  	if err != nil {
   554  		t.Fatal(err)
   555  	}
   556  }
   557  
   558  // AddTeamKeyForTest adds a new key for the given team.
   559  func AddTeamKeyForTest(config Config, tid keybase1.TeamID) error {
   560  	kbd, ok := config.KeybaseService().(*KeybaseDaemonLocal)
   561  	if !ok {
   562  		return errors.New("Bad keybase daemon")
   563  	}
   564  
   565  	ti, err := kbd.LoadTeamPlusKeys(
   566  		context.Background(), tid, tlf.Unknown, kbfsmd.UnspecifiedKeyGen,
   567  		keybase1.UserVersion{}, kbfscrypto.VerifyingKey{},
   568  		keybase1.TeamRole_NONE, keybase1.OfflineAvailability_NONE)
   569  	if err != nil {
   570  		return err
   571  	}
   572  	newKeyGen := ti.LatestKeyGen + 1
   573  	newKey := idutil.MakeLocalTLFCryptKeyOrBust(
   574  		tlf.SingleTeam.String()+"/"+string(ti.Name),
   575  		newKeyGen)
   576  	return kbd.AddTeamKeyForTest(tid, newKeyGen, newKey)
   577  }
   578  
   579  // AddTeamKeyForTestOrBust is like AddTeamKeyForTest, but
   580  // dies if there's an error.
   581  func AddTeamKeyForTestOrBust(t logger.TestLogBackend, config Config,
   582  	tid keybase1.TeamID) {
   583  	err := AddTeamKeyForTest(config, tid)
   584  	if err != nil {
   585  		t.Fatal(err)
   586  	}
   587  }
   588  
   589  // AddEmptyTeamsForTest creates teams for the given names with empty
   590  // membership lists.
   591  func AddEmptyTeamsForTest(
   592  	config Config, teams ...kbname.NormalizedUsername) ([]idutil.TeamInfo, error) {
   593  	teamInfos := idutil.MakeLocalTeams(teams)
   594  
   595  	kbd, ok := config.KeybaseService().(*KeybaseDaemonLocal)
   596  	if !ok {
   597  		return nil, errors.New("Bad keybase daemon")
   598  	}
   599  
   600  	kbd.addTeamsForTest(teamInfos)
   601  	return teamInfos, nil
   602  }
   603  
   604  // AddEmptyTeamsForTestOrBust is like AddEmptyTeamsForTest, but dies
   605  // if there's an error.
   606  func AddEmptyTeamsForTestOrBust(t logger.TestLogBackend,
   607  	config Config, teams ...kbname.NormalizedUsername) []idutil.TeamInfo {
   608  	teamInfos, err := AddEmptyTeamsForTest(config, teams...)
   609  	if err != nil {
   610  		t.Fatal(err)
   611  	}
   612  	return teamInfos
   613  }
   614  
   615  // AddImplicitTeamForTest adds an implicit team with a TLF ID.
   616  func AddImplicitTeamForTest(
   617  	config Config, name, suffix string, teamNumber byte, ty tlf.Type) (
   618  	keybase1.TeamID, error) {
   619  	iteamInfo, err := config.KeybaseService().ResolveIdentifyImplicitTeam(
   620  		context.Background(), name, suffix, ty, true, "",
   621  		keybase1.OfflineAvailability_NONE)
   622  	if err != nil {
   623  		return "", err
   624  	}
   625  	return iteamInfo.TID, nil
   626  }
   627  
   628  // AddImplicitTeamForTestOrBust is like AddImplicitTeamForTest, but
   629  // dies if there's an error.
   630  func AddImplicitTeamForTestOrBust(t logger.TestLogBackend,
   631  	config Config, name, suffix string, teamNumber byte,
   632  	ty tlf.Type) keybase1.TeamID {
   633  	teamID, err := AddImplicitTeamForTest(config, name, suffix, teamNumber, ty)
   634  	if err != nil {
   635  		t.Fatal(err)
   636  	}
   637  	return teamID
   638  }
   639  
   640  // ChangeTeamNameForTest renames a team.
   641  func ChangeTeamNameForTest(
   642  	config Config, oldName, newName string) error {
   643  	kbd, ok := config.KeybaseService().(*KeybaseDaemonLocal)
   644  	if !ok {
   645  		return errors.New("Bad keybase daemon")
   646  	}
   647  
   648  	tid, err := kbd.ChangeTeamNameForTest(oldName, newName)
   649  	if err != nil {
   650  		return err
   651  	}
   652  
   653  	config.KBFSOps().TeamNameChanged(context.Background(), tid)
   654  	return nil
   655  }
   656  
   657  // ChangeTeamNameForTestOrBust is like ChangeTeamNameForTest, but dies
   658  // if there's an error.
   659  func ChangeTeamNameForTestOrBust(t logger.TestLogBackend, config Config,
   660  	oldName, newName string) {
   661  	err := ChangeTeamNameForTest(config, oldName, newName)
   662  	if err != nil {
   663  		t.Fatal(err)
   664  	}
   665  }
   666  
   667  // SetGlobalMerkleRootForTest sets the global Merkle root and time.
   668  func SetGlobalMerkleRootForTest(
   669  	config Config, root keybase1.MerkleRootV2, rootTime time.Time) error {
   670  	kbd, ok := config.KeybaseService().(*KeybaseDaemonLocal)
   671  	if !ok {
   672  		return errors.New("Bad keybase daemon")
   673  	}
   674  
   675  	kbd.SetCurrentMerkleRoot(root, rootTime)
   676  	return nil
   677  }
   678  
   679  // SetGlobalMerkleRootForTestOrBust is like
   680  // SetGlobalMerkleRootForTest, but dies if there's an error.
   681  func SetGlobalMerkleRootForTestOrBust(
   682  	t logger.TestLogBackend, config Config, root keybase1.MerkleRootV2,
   683  	rootTime time.Time) {
   684  	err := SetGlobalMerkleRootForTest(config, root, rootTime)
   685  	if err != nil {
   686  		t.Fatal(err)
   687  	}
   688  }
   689  
   690  // SetKbfsMerkleRootForTest sets a Merkle root for the given KBFS tree ID.
   691  func SetKbfsMerkleRootForTest(
   692  	config Config, treeID keybase1.MerkleTreeID,
   693  	root *kbfsmd.MerkleRoot) error {
   694  	md, ok := config.MDServer().(mdServerLocal)
   695  	if !ok {
   696  		return errors.New("Bad md server")
   697  	}
   698  	md.setKbfsMerkleRoot(treeID, root)
   699  	return nil
   700  }
   701  
   702  // SetKbfsMerkleRootForTestOrBust is like SetKbfsMerkleRootForTest,
   703  // but dies if there's an error.
   704  func SetKbfsMerkleRootForTestOrBust(
   705  	t logger.TestLogBackend, config Config, treeID keybase1.MerkleTreeID,
   706  	root *kbfsmd.MerkleRoot) {
   707  	err := SetKbfsMerkleRootForTest(config, treeID, root)
   708  	if err != nil {
   709  		t.Fatal(err)
   710  	}
   711  }
   712  
   713  // EnableImplicitTeamsForTest causes the mdserver to stop returning
   714  // random TLF IDs for new TLFs.
   715  func EnableImplicitTeamsForTest(config Config) error {
   716  	md, ok := config.MDServer().(mdServerLocal)
   717  	if !ok {
   718  		return errors.New("Bad md server")
   719  	}
   720  	md.enableImplicitTeams()
   721  	return nil
   722  }
   723  
   724  func testRPCWithCanceledContext(t logger.TestLogBackend,
   725  	serverConn net.Conn, fn func(context.Context) error) {
   726  	ctx, cancel := context.WithCancel(context.Background())
   727  	go func() {
   728  		// Wait for RPC in fn to make progress.
   729  		n, err := serverConn.Read([]byte{1})
   730  		assert.Equal(t, n, 1)
   731  		assert.NoError(t, err)
   732  		cancel()
   733  	}()
   734  
   735  	err := fn(ctx)
   736  	if errors.Cause(err) != context.Canceled {
   737  		t.Fatalf("Function did not return a canceled error: %+v", err)
   738  	}
   739  }
   740  
   741  // DisableUpdatesForTesting stops the given folder from acting on new
   742  // updates.  Send a struct{}{} down the returned channel to restart
   743  // notifications
   744  func DisableUpdatesForTesting(config Config, folderBranch data.FolderBranch) (
   745  	chan<- struct{}, error) {
   746  	kbfsOps, ok := config.KBFSOps().(*KBFSOpsStandard)
   747  	if !ok {
   748  		return nil, errors.New("Unexpected KBFSOps type")
   749  	}
   750  
   751  	ops := kbfsOps.getOpsNoAdd(context.TODO(), folderBranch)
   752  	c := make(chan struct{})
   753  	ops.updatePauseChan <- c
   754  	return c, nil
   755  }
   756  
   757  // DisableCRForTesting stops conflict resolution for the given folder.
   758  // RestartCRForTesting should be called to restart it.
   759  func DisableCRForTesting(config Config, folderBranch data.FolderBranch) error {
   760  	kbfsOps, ok := config.KBFSOps().(*KBFSOpsStandard)
   761  	if !ok {
   762  		return errors.New("Unexpected KBFSOps type")
   763  	}
   764  
   765  	ops := kbfsOps.getOpsNoAdd(context.TODO(), folderBranch)
   766  	ops.cr.Pause()
   767  	return nil
   768  }
   769  
   770  // RestartCRForTesting re-enables conflict resolution for the given
   771  // folder.  baseCtx must have a cancellation delayer.
   772  func RestartCRForTesting(baseCtx context.Context, config Config,
   773  	folderBranch data.FolderBranch) error {
   774  	kbfsOps, ok := config.KBFSOps().(*KBFSOpsStandard)
   775  	if !ok {
   776  		return errors.New("Unexpected KBFSOps type")
   777  	}
   778  
   779  	ops := kbfsOps.getOpsNoAdd(baseCtx, folderBranch)
   780  	ops.cr.Restart(baseCtx)
   781  
   782  	// Start a resolution for anything we've missed.
   783  	lState := makeFBOLockState()
   784  	if ops.isUnmerged(lState) {
   785  		ops.cr.Resolve(baseCtx, ops.getCurrMDRevision(lState),
   786  			kbfsmd.RevisionUninitialized)
   787  	}
   788  	return nil
   789  }
   790  
   791  // SetCRFailureForTesting sets whether CR should always fail on the folder
   792  // branch.
   793  func SetCRFailureForTesting(ctx context.Context, config Config,
   794  	folderBranch data.FolderBranch, fail failModeForTesting) error {
   795  	kbfsOps, ok := config.KBFSOps().(*KBFSOpsStandard)
   796  	if !ok {
   797  		return errors.New("Unexpected KBFSOps type")
   798  	}
   799  
   800  	ops := kbfsOps.getOpsNoAdd(ctx, folderBranch)
   801  	ops.cr.setFailModeForTesting(fail)
   802  	return nil
   803  }
   804  
   805  // ForceQuotaReclamationForTesting kicks off quota reclamation under
   806  // the given config, for the given folder-branch.
   807  func ForceQuotaReclamationForTesting(config Config,
   808  	folderBranch data.FolderBranch) error {
   809  	kbfsOps, ok := config.KBFSOps().(*KBFSOpsStandard)
   810  	if !ok {
   811  		return errors.New("Unexpected KBFSOps type")
   812  	}
   813  
   814  	ops := kbfsOps.getOpsNoAdd(context.TODO(), folderBranch)
   815  	ops.fbm.forceQuotaReclamation()
   816  	return nil
   817  }
   818  
   819  // CheckConfigAndShutdown shuts down the given config, but fails the
   820  // test if there's an error.
   821  func CheckConfigAndShutdown(
   822  	ctx context.Context, t logger.TestLogBackend, config Config) {
   823  	err := config.Shutdown(ctx)
   824  	switch errors.Cause(err).(type) {
   825  	case data.ShutdownHappenedError:
   826  	case nil:
   827  	default:
   828  		t.Errorf("err=%+v", err)
   829  	}
   830  }
   831  
   832  // GetRootNodeForTest gets the root node for the given TLF name, which
   833  // must be canonical, creating it if necessary.
   834  func GetRootNodeForTest(
   835  	ctx context.Context, config Config, name string,
   836  	t tlf.Type) (Node, error) {
   837  	h, err := tlfhandle.ParseHandle(
   838  		ctx, config.KBPKI(), config.MDOps(), config, name, t)
   839  	if err != nil {
   840  		return nil, err
   841  	}
   842  
   843  	n, _, err := config.KBFSOps().GetOrCreateRootNode(ctx, h, data.MasterBranch)
   844  	if err != nil {
   845  		return nil, err
   846  	}
   847  
   848  	return n, nil
   849  }
   850  
   851  // GetRootNodeOrBust gets the root node for the given TLF name, which
   852  // must be canonical, creating it if necessary, and failing if there's
   853  // an error.
   854  func GetRootNodeOrBust(
   855  	ctx context.Context, t logger.TestLogBackend,
   856  	config Config, name string, ty tlf.Type) Node {
   857  	n, err := GetRootNodeForTest(ctx, config, name, ty)
   858  	if err != nil {
   859  		t.Fatalf("Couldn't get root node for %s (type=%s): %+v",
   860  			name, ty, err)
   861  	}
   862  	return n
   863  }