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 }