github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/systests/treeloader_test.go (about) 1 package systests 2 3 import ( 4 "fmt" 5 "math/rand" 6 "testing" 7 "time" 8 9 "golang.org/x/net/context" 10 11 "github.com/keybase/client/go/libkb" 12 "github.com/keybase/client/go/protocol/keybase1" 13 "github.com/keybase/client/go/teams" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func mustAppend(t *testing.T, a keybase1.TeamName, b string) keybase1.TeamName { 18 ret, err := a.Append(b) 19 require.NoError(t, err) 20 return ret 21 } 22 23 func mustCreateSubteam(t *testing.T, tc *libkb.TestContext, 24 name keybase1.TeamName) keybase1.TeamID { 25 parent, err := name.Parent() 26 require.NoError(t, err) 27 id, err := teams.CreateSubteam(context.TODO(), tc.G, name.LastPart().String(), 28 parent, keybase1.TeamRole_NONE) 29 require.NoError(t, err) 30 return *id 31 } 32 33 func loadTeamTree(t *testing.T, tmctx libkb.MetaContext, notifications *teamNotifyHandler, 34 teamID keybase1.TeamID, username string, failureTeamIDs []keybase1.TeamID, 35 teamFailures []string) ([]keybase1.TeamTreeMembership, error) { 36 var err error 37 38 guid := rand.Int() 39 40 l, err := teams.NewTreeloader(tmctx, username, teamID, guid, true /* includeAncestors */) 41 if err != nil { 42 return nil, err 43 } 44 if failureTeamIDs != nil { 45 l.Converter = newMockConverter(failureTeamIDs, l) 46 } 47 err = l.LoadAsync(tmctx) 48 if err != nil { 49 return nil, err 50 } 51 52 var results []keybase1.TeamTreeMembership 53 var expectedCount *int 54 got := 0 55 loop: 56 for { 57 select { 58 case res := <-notifications.teamTreeMembershipsDoneCh: 59 // We don't immediately break in this case because we are not guaranteed to receive this 60 // notification last by the RPC layer. So we wait until all of the messages are 61 // received. Even if there were errors, we should still get exactly this many 62 // notifications in teamTreeMembershipsPartialCh. 63 expectedCount = &res.ExpectedCount 64 require.Equal(t, guid, res.Guid) 65 case res := <-notifications.teamTreeMembershipsPartialCh: 66 got++ 67 results = append(results, res) 68 s, err := res.Result.S() 69 require.NoError(t, err, "should never happen") 70 switch s { 71 case keybase1.TeamTreeMembershipStatus_OK: 72 case keybase1.TeamTreeMembershipStatus_ERROR: 73 require.Contains(t, teamFailures, res.TeamName, 74 "unexpectedly got an error while loading team: %s", res.Result.Error().Message) 75 } 76 require.Equal(t, guid, res.Guid) 77 case <-time.After(10 * time.Second): 78 t.Fatalf("timed out waiting for team tree notifications") 79 } 80 if expectedCount != nil && *expectedCount == got { 81 break loop 82 } 83 } 84 return results, nil 85 } 86 87 func checkTeamTreeResults(t *testing.T, expected map[string]keybase1.TeamRole, 88 failureTeamNames []string, hiddenTeamNames []string, results []keybase1.TeamTreeMembership) { 89 require.Equal(t, len(expected)+len(failureTeamNames)+len(hiddenTeamNames), 90 len(results), "got right number of results back") 91 m := make(map[string]struct{}) 92 for _, result := range results { 93 _, alreadyExists := m[result.TeamName] 94 require.False(t, alreadyExists, "got a duplicate got %s", result.TeamName) 95 m[result.TeamName] = struct{}{} 96 s, err := result.Result.S() 97 require.NoError(t, err) 98 99 switch s { 100 case keybase1.TeamTreeMembershipStatus_OK: 101 r, ok := expected[result.TeamName] 102 require.True(t, ok, "should not have gotten a result for %s", result.TeamName) 103 val := result.Result.Ok() 104 require.Equal(t, r, val.Role, "expected role %v for team %s, but got role %v", 105 r, result.TeamName, val.Role) 106 if val.Role != keybase1.TeamRole_NONE { 107 require.NotNil(t, val.JoinTime) 108 } 109 case keybase1.TeamTreeMembershipStatus_ERROR: 110 require.Contains(t, failureTeamNames, result.TeamName) 111 case keybase1.TeamTreeMembershipStatus_HIDDEN: 112 require.Contains(t, hiddenTeamNames, result.TeamName) 113 default: 114 t.Errorf("got an unknown result status %s", s) 115 } 116 } 117 } 118 119 type mockConverter struct { 120 failureTeamIDs []keybase1.TeamID 121 loader *teams.Treeloader 122 } 123 124 func (m mockConverter) ProcessSigchainState(mctx libkb.MetaContext, 125 teamName keybase1.TeamName, s *keybase1.TeamSigChainState) keybase1.TeamTreeMembershipResult { 126 for _, failureTeamID := range m.failureTeamIDs { 127 if failureTeamID == s.Id { 128 return m.loader.NewErrorResult(fmt.Errorf("mock failure"), teamName) 129 } 130 } 131 return m.loader.ProcessSigchainState(mctx, teamName, s) 132 } 133 134 func newMockConverter(failureTeamIDs []keybase1.TeamID, loader *teams.Treeloader) mockConverter { 135 return mockConverter{ 136 failureTeamIDs: failureTeamIDs, 137 loader: loader, 138 } 139 } 140 141 func TestLoadTeamTreeMemberships(t *testing.T) { 142 tt := newTeamTester(t) 143 defer tt.cleanup() 144 145 t.Logf("Creating users") 146 // Create the folowing team tree: 147 // 148 // .___A_____. 149 // | | 150 // B .___C__. 151 // | | 152 // D .__E__. 153 // | | | | 154 // F G H I 155 // 156 // Teams are going to have the following members: 157 // 158 // A: zulu (adm) 159 // B: yank (adm) 160 // C: yank (adm), vict, tang 161 // D: xray (adm), unif 162 // E: tang (adm), vict 163 // F: yank (adm) 164 // G: yank, whis (adm), vict 165 // H: zulu, xray 166 // I: zulu, unif 167 // Below, we generate paperkeys to set up a environment for testing the GUI integration. 168 alfa := tt.addUserWithPaper("alfa") 169 t.Logf("Generated paperkey for %s: %s", alfa.username, alfa.backupKey.secret) 170 zulu := tt.addUserWithPaper("zulu") 171 t.Logf("Generated paperkey for %s: %s", zulu.username, zulu.backupKey.secret) 172 yank := tt.addUserWithPaper("yank") 173 t.Logf("Generated paperkey for %s: %s", yank.username, yank.backupKey.secret) 174 xray := tt.addUserWithPaper("xray") 175 t.Logf("Generated paperkey for %s: %s", xray.username, xray.backupKey.secret) 176 whis := tt.addUserWithPaper("whis") 177 t.Logf("Generated paperkey for %s: %s", whis.username, whis.backupKey.secret) 178 vict := tt.addUserWithPaper("vict") 179 t.Logf("Generated paperkey for %s: %s", vict.username, vict.backupKey.secret) 180 unif := tt.addUserWithPaper("unif") 181 t.Logf("UGenerated paperkey for %s: %s", unif.username, unif.backupKey.secret) 182 tang := tt.addUserWithPaper("tang") 183 t.Logf("Generated paperkey for %s: %s", tang.username, tang.backupKey.secret) 184 185 t.Logf("Creating teams") 186 aID, aName := alfa.createTeam2() 187 bName := mustAppend(t, aName, "bb") 188 cName := mustAppend(t, aName, "cc") 189 dName := mustAppend(t, cName, "dd") 190 eName := mustAppend(t, cName, "ee") 191 fName := mustAppend(t, dName, "ff") 192 gName := mustAppend(t, eName, "gg") 193 hName := mustAppend(t, eName, "hh") 194 iName := mustAppend(t, eName, "ii") 195 bID := mustCreateSubteam(t, alfa.tc, bName) 196 cID := mustCreateSubteam(t, alfa.tc, cName) 197 dID := mustCreateSubteam(t, alfa.tc, dName) 198 eID := mustCreateSubteam(t, alfa.tc, eName) 199 fID := mustCreateSubteam(t, alfa.tc, fName) 200 gID := mustCreateSubteam(t, alfa.tc, gName) 201 hID := mustCreateSubteam(t, alfa.tc, hName) 202 iID := mustCreateSubteam(t, alfa.tc, iName) 203 204 var err error 205 206 t.Logf("Populating teams with members") 207 _, _, err = teams.AddMembers(context.Background(), alfa.tc.G, aID, 208 []keybase1.UserRolePair{ 209 {Assertion: zulu.username, Role: keybase1.TeamRole_ADMIN}, 210 }, 211 nil, 212 ) 213 require.NoError(t, err) 214 _, _, err = teams.AddMembers(context.Background(), alfa.tc.G, bID, 215 []keybase1.UserRolePair{ 216 {Assertion: yank.username, Role: keybase1.TeamRole_ADMIN}, 217 }, 218 nil, 219 ) 220 require.NoError(t, err) 221 _, _, err = teams.AddMembers(context.Background(), alfa.tc.G, cID, 222 []keybase1.UserRolePair{ 223 {Assertion: yank.username, Role: keybase1.TeamRole_ADMIN}, 224 {Assertion: vict.username, Role: keybase1.TeamRole_WRITER}, 225 {Assertion: tang.username, Role: keybase1.TeamRole_WRITER}, 226 }, 227 nil, 228 ) 229 require.NoError(t, err) 230 _, _, err = teams.AddMembers(context.Background(), alfa.tc.G, dID, 231 []keybase1.UserRolePair{ 232 {Assertion: xray.username, Role: keybase1.TeamRole_ADMIN}, 233 {Assertion: unif.username, Role: keybase1.TeamRole_WRITER}, 234 }, 235 nil, 236 ) 237 require.NoError(t, err) 238 _, _, err = teams.AddMembers(context.Background(), alfa.tc.G, eID, 239 []keybase1.UserRolePair{ 240 {Assertion: tang.username, Role: keybase1.TeamRole_ADMIN}, 241 {Assertion: vict.username, Role: keybase1.TeamRole_WRITER}, 242 }, 243 nil, 244 ) 245 require.NoError(t, err) 246 _, _, err = teams.AddMembers(context.Background(), alfa.tc.G, fID, 247 []keybase1.UserRolePair{ 248 {Assertion: yank.username, Role: keybase1.TeamRole_ADMIN}, 249 }, 250 nil, 251 ) 252 require.NoError(t, err) 253 _, _, err = teams.AddMembers(context.Background(), alfa.tc.G, gID, 254 []keybase1.UserRolePair{ 255 {Assertion: yank.username, Role: keybase1.TeamRole_WRITER}, 256 {Assertion: whis.username, Role: keybase1.TeamRole_ADMIN}, 257 {Assertion: vict.username, Role: keybase1.TeamRole_WRITER}, 258 }, 259 nil, 260 ) 261 require.NoError(t, err) 262 _, _, err = teams.AddMembers(context.Background(), alfa.tc.G, hID, 263 []keybase1.UserRolePair{ 264 {Assertion: zulu.username, Role: keybase1.TeamRole_WRITER}, 265 {Assertion: xray.username, Role: keybase1.TeamRole_WRITER}, 266 }, 267 nil, 268 ) 269 require.NoError(t, err) 270 _, _, err = teams.AddMembers(context.Background(), alfa.tc.G, iID, 271 []keybase1.UserRolePair{ 272 {Assertion: zulu.username, Role: keybase1.TeamRole_WRITER}, 273 {Assertion: unif.username, Role: keybase1.TeamRole_WRITER}, 274 }, 275 nil, 276 ) 277 require.NoError(t, err) 278 279 t.Logf("Modifying teams") 280 tui := &teamsUI{} 281 err = teams.Delete(context.Background(), alfa.tc.G, tui, hID) 282 require.NoError(t, err) 283 tang.reset() 284 tang.loginAfterReset() 285 unif.delete() 286 287 t.Logf("happy-path table tests") 288 tsts := []struct { 289 teamID keybase1.TeamID 290 requester *userPlusDevice 291 target *userPlusDevice 292 hidden []string 293 expected map[string]keybase1.TeamRole 294 }{ 295 { 296 teamID: aID, 297 requester: zulu, 298 target: zulu, 299 expected: map[string]keybase1.TeamRole{ 300 aName.String(): keybase1.TeamRole_ADMIN, 301 bName.String(): keybase1.TeamRole_NONE, 302 cName.String(): keybase1.TeamRole_NONE, 303 dName.String(): keybase1.TeamRole_NONE, 304 eName.String(): keybase1.TeamRole_NONE, 305 fName.String(): keybase1.TeamRole_NONE, 306 gName.String(): keybase1.TeamRole_NONE, 307 iName.String(): keybase1.TeamRole_WRITER, 308 }, 309 hidden: []string{}, 310 }, 311 { 312 teamID: bID, 313 requester: zulu, 314 target: zulu, 315 expected: map[string]keybase1.TeamRole{ 316 aName.String(): keybase1.TeamRole_ADMIN, 317 bName.String(): keybase1.TeamRole_NONE, 318 }, 319 hidden: []string{}, 320 }, 321 { 322 teamID: bID, 323 requester: zulu, 324 target: yank, 325 expected: map[string]keybase1.TeamRole{ 326 aName.String(): keybase1.TeamRole_NONE, 327 bName.String(): keybase1.TeamRole_ADMIN, 328 }, 329 }, 330 { 331 teamID: bID, 332 requester: yank, 333 target: zulu, 334 expected: map[string]keybase1.TeamRole{ 335 bName.String(): keybase1.TeamRole_NONE, 336 }, 337 hidden: []string{aName.String()}, 338 }, 339 { 340 teamID: bID, 341 requester: yank, 342 target: yank, 343 expected: map[string]keybase1.TeamRole{ 344 bName.String(): keybase1.TeamRole_ADMIN, 345 }, 346 hidden: []string{aName.String()}, 347 }, 348 { 349 teamID: cID, 350 requester: zulu, 351 target: yank, 352 expected: map[string]keybase1.TeamRole{ 353 aName.String(): keybase1.TeamRole_NONE, 354 cName.String(): keybase1.TeamRole_ADMIN, 355 dName.String(): keybase1.TeamRole_NONE, 356 eName.String(): keybase1.TeamRole_NONE, 357 fName.String(): keybase1.TeamRole_ADMIN, 358 gName.String(): keybase1.TeamRole_WRITER, 359 iName.String(): keybase1.TeamRole_NONE, 360 }, 361 }, 362 { 363 teamID: cID, 364 requester: yank, 365 target: yank, 366 expected: map[string]keybase1.TeamRole{ 367 cName.String(): keybase1.TeamRole_ADMIN, 368 dName.String(): keybase1.TeamRole_NONE, 369 eName.String(): keybase1.TeamRole_NONE, 370 fName.String(): keybase1.TeamRole_ADMIN, 371 gName.String(): keybase1.TeamRole_WRITER, 372 iName.String(): keybase1.TeamRole_NONE, 373 }, 374 hidden: []string{aName.String()}, 375 }, 376 { 377 teamID: cID, 378 requester: zulu, 379 target: whis, 380 expected: map[string]keybase1.TeamRole{ 381 aName.String(): keybase1.TeamRole_NONE, 382 cName.String(): keybase1.TeamRole_NONE, 383 dName.String(): keybase1.TeamRole_NONE, 384 eName.String(): keybase1.TeamRole_NONE, 385 fName.String(): keybase1.TeamRole_NONE, 386 gName.String(): keybase1.TeamRole_ADMIN, 387 iName.String(): keybase1.TeamRole_NONE, 388 }, 389 }, 390 { 391 teamID: cID, 392 requester: yank, 393 target: whis, 394 expected: map[string]keybase1.TeamRole{ 395 cName.String(): keybase1.TeamRole_NONE, 396 dName.String(): keybase1.TeamRole_NONE, 397 eName.String(): keybase1.TeamRole_NONE, 398 fName.String(): keybase1.TeamRole_NONE, 399 gName.String(): keybase1.TeamRole_ADMIN, 400 iName.String(): keybase1.TeamRole_NONE, 401 }, 402 hidden: []string{aName.String()}, 403 }, 404 405 { 406 teamID: cID, 407 requester: zulu, 408 target: xray, 409 expected: map[string]keybase1.TeamRole{ 410 aName.String(): keybase1.TeamRole_NONE, 411 cName.String(): keybase1.TeamRole_NONE, 412 dName.String(): keybase1.TeamRole_ADMIN, 413 eName.String(): keybase1.TeamRole_NONE, 414 fName.String(): keybase1.TeamRole_NONE, 415 gName.String(): keybase1.TeamRole_NONE, 416 iName.String(): keybase1.TeamRole_NONE, 417 }, 418 }, 419 { 420 teamID: cID, 421 requester: yank, 422 target: xray, 423 expected: map[string]keybase1.TeamRole{ 424 cName.String(): keybase1.TeamRole_NONE, 425 dName.String(): keybase1.TeamRole_ADMIN, 426 eName.String(): keybase1.TeamRole_NONE, 427 fName.String(): keybase1.TeamRole_NONE, 428 gName.String(): keybase1.TeamRole_NONE, 429 iName.String(): keybase1.TeamRole_NONE, 430 }, 431 hidden: []string{aName.String()}, 432 }, 433 { 434 teamID: cID, 435 requester: yank, 436 target: tang, // in no teams after reset 437 expected: map[string]keybase1.TeamRole{ 438 cName.String(): keybase1.TeamRole_NONE, 439 dName.String(): keybase1.TeamRole_NONE, 440 eName.String(): keybase1.TeamRole_NONE, 441 fName.String(): keybase1.TeamRole_NONE, 442 gName.String(): keybase1.TeamRole_NONE, 443 iName.String(): keybase1.TeamRole_NONE, 444 }, 445 hidden: []string{aName.String()}, 446 }, 447 { 448 teamID: dID, 449 requester: zulu, 450 target: zulu, 451 expected: map[string]keybase1.TeamRole{ 452 aName.String(): keybase1.TeamRole_ADMIN, 453 dName.String(): keybase1.TeamRole_NONE, 454 fName.String(): keybase1.TeamRole_NONE, 455 }, 456 hidden: []string{cName.String()}, 457 }, 458 { 459 teamID: dID, 460 requester: yank, 461 target: zulu, 462 expected: map[string]keybase1.TeamRole{ 463 cName.String(): keybase1.TeamRole_NONE, 464 dName.String(): keybase1.TeamRole_NONE, 465 fName.String(): keybase1.TeamRole_NONE, 466 }, 467 hidden: []string{aName.String()}, 468 }, 469 { 470 teamID: dID, 471 requester: xray, 472 target: zulu, 473 expected: map[string]keybase1.TeamRole{ 474 dName.String(): keybase1.TeamRole_NONE, 475 fName.String(): keybase1.TeamRole_NONE, 476 }, 477 hidden: []string{aName.String(), cName.String()}, 478 }, 479 { 480 teamID: dID, 481 requester: zulu, 482 target: vict, 483 expected: map[string]keybase1.TeamRole{ 484 aName.String(): keybase1.TeamRole_NONE, 485 dName.String(): keybase1.TeamRole_NONE, 486 fName.String(): keybase1.TeamRole_NONE, 487 }, 488 hidden: []string{cName.String()}, 489 }, 490 { 491 teamID: dID, 492 requester: yank, 493 target: vict, 494 expected: map[string]keybase1.TeamRole{ 495 cName.String(): keybase1.TeamRole_WRITER, 496 dName.String(): keybase1.TeamRole_NONE, 497 fName.String(): keybase1.TeamRole_NONE, 498 }, 499 hidden: []string{aName.String()}, 500 }, 501 { 502 teamID: dID, 503 requester: xray, 504 target: vict, 505 expected: map[string]keybase1.TeamRole{ 506 dName.String(): keybase1.TeamRole_NONE, 507 fName.String(): keybase1.TeamRole_NONE, 508 }, 509 hidden: []string{aName.String(), cName.String()}, 510 }, 511 { 512 teamID: dID, 513 requester: zulu, 514 target: xray, 515 expected: map[string]keybase1.TeamRole{ 516 aName.String(): keybase1.TeamRole_NONE, 517 dName.String(): keybase1.TeamRole_ADMIN, 518 fName.String(): keybase1.TeamRole_NONE, 519 }, 520 hidden: []string{cName.String()}, 521 }, 522 { 523 teamID: dID, 524 requester: yank, 525 target: xray, 526 expected: map[string]keybase1.TeamRole{ 527 cName.String(): keybase1.TeamRole_NONE, 528 dName.String(): keybase1.TeamRole_ADMIN, 529 fName.String(): keybase1.TeamRole_NONE, 530 }, 531 hidden: []string{aName.String()}, 532 }, 533 { 534 teamID: dID, 535 requester: xray, 536 target: xray, 537 expected: map[string]keybase1.TeamRole{ 538 dName.String(): keybase1.TeamRole_ADMIN, 539 fName.String(): keybase1.TeamRole_NONE, 540 }, 541 hidden: []string{aName.String(), cName.String()}, 542 }, 543 { 544 teamID: eID, 545 requester: yank, 546 target: vict, 547 expected: map[string]keybase1.TeamRole{ 548 cName.String(): keybase1.TeamRole_WRITER, 549 eName.String(): keybase1.TeamRole_WRITER, 550 gName.String(): keybase1.TeamRole_WRITER, 551 iName.String(): keybase1.TeamRole_NONE, 552 }, 553 hidden: []string{aName.String()}, 554 }, 555 { 556 teamID: eID, 557 requester: yank, 558 target: xray, 559 expected: map[string]keybase1.TeamRole{ 560 cName.String(): keybase1.TeamRole_NONE, 561 eName.String(): keybase1.TeamRole_NONE, 562 gName.String(): keybase1.TeamRole_NONE, 563 iName.String(): keybase1.TeamRole_NONE, 564 }, 565 hidden: []string{aName.String()}, 566 }, 567 { 568 teamID: gID, 569 requester: whis, 570 target: whis, 571 expected: map[string]keybase1.TeamRole{ 572 gName.String(): keybase1.TeamRole_ADMIN, 573 }, 574 hidden: []string{aName.String(), cName.String(), eName.String()}, 575 }, 576 { 577 teamID: gID, 578 requester: yank, 579 target: whis, 580 expected: map[string]keybase1.TeamRole{ 581 cName.String(): keybase1.TeamRole_NONE, 582 gName.String(): keybase1.TeamRole_ADMIN, 583 }, 584 hidden: []string{aName.String(), eName.String()}, 585 }, 586 { 587 teamID: gID, 588 requester: zulu, 589 target: whis, 590 expected: map[string]keybase1.TeamRole{ 591 aName.String(): keybase1.TeamRole_NONE, 592 gName.String(): keybase1.TeamRole_ADMIN, 593 }, 594 hidden: []string{cName.String(), eName.String()}, 595 }, 596 } 597 for idx, tst := range tsts { 598 t.Logf("Testing testcase %d", idx) 599 name := fmt.Sprintf("happy/%d", idx) 600 t.Run(name, func(t *testing.T) { 601 mctx := libkb.NewMetaContextForTest(*tst.requester.tc) 602 results, err := loadTeamTree(t, mctx, tst.requester.notifications, 603 tst.teamID, tst.target.username, nil, nil) 604 require.NoError(t, err) 605 checkTeamTreeResults(t, tst.expected, nil, tst.hidden, results) 606 }) 607 } 608 609 t.Logf("error path table testing") 610 errorTsts := []struct { 611 teamID keybase1.TeamID 612 requester *userPlusDevice 613 target *userPlusDevice 614 failureTeamIDs []keybase1.TeamID 615 failureTeamNames []string 616 hidden []string 617 expectedSuccesses map[string]keybase1.TeamRole 618 }{ 619 { 620 teamID: cID, 621 requester: yank, 622 target: whis, 623 failureTeamIDs: []keybase1.TeamID{dID, gID}, 624 failureTeamNames: []string{dName.String(), gName.String()}, 625 expectedSuccesses: map[string]keybase1.TeamRole{ 626 cName.String(): keybase1.TeamRole_NONE, 627 eName.String(): keybase1.TeamRole_NONE, 628 iName.String(): keybase1.TeamRole_NONE, 629 }, 630 hidden: []string{aName.String()}, 631 }, 632 { 633 teamID: cID, 634 requester: yank, 635 target: whis, 636 failureTeamIDs: []keybase1.TeamID{iID}, 637 failureTeamNames: []string{iName.String()}, 638 expectedSuccesses: map[string]keybase1.TeamRole{ 639 cName.String(): keybase1.TeamRole_NONE, 640 dName.String(): keybase1.TeamRole_NONE, 641 eName.String(): keybase1.TeamRole_NONE, 642 fName.String(): keybase1.TeamRole_NONE, 643 gName.String(): keybase1.TeamRole_ADMIN, 644 }, 645 hidden: []string{aName.String()}, 646 }, 647 { 648 teamID: eID, 649 requester: yank, 650 target: whis, 651 failureTeamIDs: []keybase1.TeamID{cID}, 652 failureTeamNames: []string{cName.String()}, 653 expectedSuccesses: map[string]keybase1.TeamRole{ 654 eName.String(): keybase1.TeamRole_NONE, 655 gName.String(): keybase1.TeamRole_ADMIN, 656 iName.String(): keybase1.TeamRole_NONE, 657 }, 658 hidden: []string{}, 659 }, 660 { 661 teamID: eID, 662 requester: yank, 663 target: whis, 664 failureTeamIDs: []keybase1.TeamID{aID}, 665 failureTeamNames: []string{aName.String()}, 666 expectedSuccesses: map[string]keybase1.TeamRole{ 667 cName.String(): keybase1.TeamRole_NONE, 668 eName.String(): keybase1.TeamRole_NONE, 669 gName.String(): keybase1.TeamRole_ADMIN, 670 iName.String(): keybase1.TeamRole_NONE, 671 }, 672 hidden: []string{}, 673 }, 674 { 675 teamID: eID, 676 requester: yank, 677 target: whis, 678 failureTeamIDs: []keybase1.TeamID{aID, iID}, 679 failureTeamNames: []string{aName.String(), iName.String()}, 680 expectedSuccesses: map[string]keybase1.TeamRole{ 681 cName.String(): keybase1.TeamRole_NONE, 682 eName.String(): keybase1.TeamRole_NONE, 683 gName.String(): keybase1.TeamRole_ADMIN, 684 }, 685 hidden: []string{}, 686 }, 687 { 688 teamID: eID, 689 requester: yank, 690 target: whis, 691 failureTeamIDs: []keybase1.TeamID{eID}, 692 failureTeamNames: []string{eName.String()}, 693 expectedSuccesses: map[string]keybase1.TeamRole{}, 694 hidden: []string{}, 695 }, 696 } 697 for idx, tst := range errorTsts { 698 t.Logf("Testing testcase %d", idx) 699 name := fmt.Sprintf("error/%d", idx) 700 t.Run(name, func(t *testing.T) { 701 mctx := libkb.NewMetaContextForTest(*tst.requester.tc) 702 results, err := loadTeamTree(t, mctx, tst.requester.notifications, tst.teamID, 703 tst.target.username, tst.failureTeamIDs, tst.failureTeamNames) 704 require.NoError(t, err) 705 checkTeamTreeResults(t, tst.expectedSuccesses, tst.failureTeamNames, 706 tst.hidden, results) 707 }) 708 } 709 710 t.Logf("miscellaneous tests") 711 zuluMctx := libkb.NewMetaContextForTest(*zulu.tc) 712 victMctx := libkb.NewMetaContextForTest(*vict.tc) 713 714 _, err = loadTeamTree(t, zuluMctx, zulu.notifications, cID, unif.username, nil, nil) 715 require.IsType(t, libkb.NoKeyError{}, err, "cannot load a deleted user") 716 717 _, err = loadTeamTree(t, victMctx, vict.notifications, cID, yank.username, nil, nil) 718 require.IsType(t, teams.StubbedError{}, err, "can only load if you're an admin") 719 }