github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/list_tracking_test.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package engine 5 6 import ( 7 "errors" 8 "fmt" 9 "net/http" 10 "testing" 11 "time" 12 13 "github.com/keybase/client/go/libkb" 14 keybase1 "github.com/keybase/client/go/protocol/keybase1" 15 "github.com/keybase/clockwork" 16 jsonw "github.com/keybase/go-jsonw" 17 "github.com/stretchr/testify/require" 18 ) 19 20 func TestListTracking(t *testing.T) { 21 doWithSigChainVersions(func(sigVersion libkb.SigVersion) { 22 _testListTracking(t, sigVersion) 23 }) 24 } 25 26 func _verifyListTrackingEntries(entries []keybase1.UserSummary) error { 27 if len(entries) != 2 { 28 return fmt.Errorf("Num tracks: %d, exected 2.", len(entries)) 29 } 30 31 alice := entries[0] 32 if alice.Username != "t_alice" { 33 return fmt.Errorf("Username: %q, Expected t_alice.", alice.Username) 34 } 35 bob := entries[1] 36 if bob.Username != "t_bob" { 37 return fmt.Errorf("Username: %q, Expected t_bob.", bob.Username) 38 } 39 40 return nil 41 } 42 43 func _testListTracking(t *testing.T, sigVersion libkb.SigVersion) { 44 tc := SetupEngineTest(t, "track") 45 defer tc.Cleanup() 46 fu := CreateAndSignupFakeUser(tc, "track") 47 fu.LoginOrBust(tc) 48 49 trackAlice(tc, fu, sigVersion) 50 trackBob(tc, fu, sigVersion) 51 defer untrackAlice(tc, fu, sigVersion) 52 defer untrackBob(tc, fu, sigVersion) 53 54 // Perform a proof to make sure that the last item of the chain isn't a track 55 proveUI, _, err := proveRooter(tc.G, fu, sigVersion) 56 require.NoError(t, err) 57 require.False(t, proveUI.overwrite) 58 require.False(t, proveUI.warning) 59 require.False(t, proveUI.recheck) 60 require.True(t, proveUI.checked) 61 62 eng := NewListTrackingEngine(tc.G, &ListTrackingEngineArg{}) 63 if err := RunEngine2(NewMetaContextForTest(tc), eng); err != nil { 64 t.Fatal("Error in ListTrackingEngine:", err) 65 } 66 if err := _verifyListTrackingEntries(eng.TableResult().Users); err != nil { 67 t.Fatal("Error in tracking engine result entries verification:", err) 68 } 69 70 // We're running this again using a different, non-signed-in cache to test 71 // the manual stubbing override. 72 tc2 := SetupEngineTest(t, "track-anonymous") 73 defer tc2.Cleanup() 74 75 eng = NewListTrackingEngine(tc2.G, &ListTrackingEngineArg{ 76 Assertion: fu.Username, 77 }) 78 if err := RunEngine2(NewMetaContextForTest(tc2), eng); err != nil { 79 t.Fatal("Error in ListTrackingEngine:", err) 80 } 81 if err := _verifyListTrackingEntries(eng.TableResult().Users); err != nil { 82 t.Fatal("Error in tracking engine result entries verification:", err) 83 } 84 } 85 86 func TestListTrackingJSON(t *testing.T) { 87 tc := SetupEngineTest(t, "track") 88 defer tc.Cleanup() 89 sigVersion := libkb.GetDefaultSigVersion(tc.G) 90 fu := CreateAndSignupFakeUser(tc, "track") 91 fu.LoginOrBust(tc) 92 93 trackAlice(tc, fu, sigVersion) 94 defer untrackAlice(tc, fu, sigVersion) 95 96 arg := ListTrackingEngineArg{JSON: true, Verbose: true} 97 eng := NewListTrackingEngine(tc.G, &arg) 98 m := NewMetaContextForTest(tc) 99 err := RunEngine2(m, eng) 100 if err != nil { 101 t.Fatal("Error in ListTrackingEngine:", err) 102 } 103 104 _, err = jsonw.Unmarshal([]byte(eng.JSONResult())) 105 if err != nil { 106 t.Fatal(err) 107 } 108 } 109 110 func TestListTrackingLocal(t *testing.T) { 111 t.Skip("Skipping test for local tracks in list tracking (milestone 2)") 112 tc := SetupEngineTest(t, "track") 113 defer tc.Cleanup() 114 sigVersion := libkb.GetDefaultSigVersion(tc.G) 115 fu := CreateAndSignupFakeUser(tc, "track") 116 117 trackAlice(tc, fu, sigVersion) 118 defer untrackAlice(tc, fu, sigVersion) 119 120 sv := keybase1.SigVersion(sigVersion) 121 trackBobWithOptions(tc, fu, keybase1.TrackOptions{LocalOnly: true, SigVersion: &sv}, fu.NewSecretUI()) 122 defer untrackBob(tc, fu, sigVersion) 123 124 arg := ListTrackingEngineArg{} 125 eng := NewListTrackingEngine(tc.G, &arg) 126 m := NewMetaContextForTest(tc) 127 err := RunEngine2(m, eng) 128 if err != nil { 129 t.Fatal("Error in ListTrackingEngine:", err) 130 } 131 132 entries := eng.TableResult().Users 133 if len(entries) != 2 { 134 t.Errorf("Num tracks: %d, exected 2", len(entries)) 135 } 136 } 137 138 func TestListTrackingServerInterference(t *testing.T) { 139 atc := SetupEngineTest(t, "track") 140 defer atc.Cleanup() 141 btc := SetupEngineTest(t, "track") 142 defer btc.Cleanup() 143 ctc := SetupEngineTest(t, "track") 144 defer ctc.Cleanup() 145 sigVersion := libkb.GetDefaultSigVersion(atc.G) 146 147 alice := CreateAndSignupFakeUser(atc, "track") 148 bob := CreateAndSignupFakeUser(btc, "track") 149 charlie := CreateAndSignupFakeUser(ctc, "track") 150 alice.LoginOrBust(atc) 151 152 _, _, err := runTrack(atc, alice, bob.Username, sigVersion) 153 require.NoError(t, err) 154 155 eng := NewListTrackingEngine(atc.G, &ListTrackingEngineArg{}) 156 if err := RunEngine2(NewMetaContextForTest(atc), eng); err != nil { 157 t.Fatal("Error in ListTrackingEngine:", err) 158 } 159 found := false 160 for _, user := range eng.TableResult().Users { 161 if user.Username == bob.Username { 162 found = true 163 } 164 } 165 if !found { 166 t.Fatalf("expected to be following bob, but wasn't") 167 } 168 169 ResetAccount(btc, bob) 170 171 // (MD/TRIAGE-1837) Due to a server bug, it seems the follow version doesn't 172 // update immediately on resets, only on the next follow, so we're not 173 // going to get the proper filtration until we bump it e.g. by following 174 // another random user. 175 _, _, err = runTrack(atc, alice, charlie.Username, sigVersion) 176 require.NoError(t, err) 177 178 eng = NewListTrackingEngine(atc.G, &ListTrackingEngineArg{}) 179 if err := RunEngine2(NewMetaContextForTest(atc), eng); err != nil { 180 t.Fatal("Error in ListTrackingEngine:", err) 181 } 182 found = false 183 for _, user := range eng.TableResult().Users { 184 if user.Username == bob.Username { 185 found = true 186 } 187 } 188 if found { 189 t.Fatalf("expected server to filter out reset bob, but didn't; still following after reset") 190 } 191 192 eng = NewListTrackingEngine(atc.G, &ListTrackingEngineArg{}) 193 eng.disableTrackerSyncerForTest = true 194 if err := RunEngine2(NewMetaContextForTest(atc), eng); err != nil { 195 t.Fatal("Error in ListTrackingEngine:", err) 196 } 197 found = false 198 for _, user := range eng.TableResult().Users { 199 if user.Username == bob.Username { 200 found = true 201 } 202 } 203 if !found { 204 t.Fatalf("tracker syncer returned error; so we should still succeed but not filter") 205 } 206 } 207 208 type errorAPIMock struct { 209 *libkb.APIArgRecorder 210 callCount int 211 } 212 213 func (r *errorAPIMock) GetDecode(mctx libkb.MetaContext, arg libkb.APIArg, w libkb.APIResponseWrapper) error { 214 r.callCount++ 215 return errors.New("timeout or something") 216 } 217 218 func (r *errorAPIMock) GetResp(mctx libkb.MetaContext, arg libkb.APIArg) (*http.Response, func(), error) { 219 r.callCount++ 220 return nil, func() {}, errors.New("timeout or something") 221 } 222 223 func (r *errorAPIMock) Get(mctx libkb.MetaContext, arg libkb.APIArg) (*libkb.APIRes, error) { 224 r.callCount++ 225 return nil, errors.New("timeout or something") 226 } 227 228 func TestListTrackingOfflineBehavior(t *testing.T) { 229 atc := SetupEngineTest(t, "track") 230 defer atc.Cleanup() 231 btc := SetupEngineTest(t, "track") 232 defer btc.Cleanup() 233 ctc := SetupEngineTest(t, "track") 234 defer ctc.Cleanup() 235 sigVersion := libkb.GetDefaultSigVersion(atc.G) 236 237 alice := CreateAndSignupFakeUser(atc, "track") 238 bob := CreateAndSignupFakeUser(btc, "track") 239 charlie := CreateAndSignupFakeUser(ctc, "track") 240 alice.LoginOrBust(atc) 241 242 _, _, err := runTrack(atc, alice, bob.Username, sigVersion) 243 require.NoError(t, err) 244 245 // Prime UPAK and TrackerSyncer caches when online 246 eng := NewListTrackingEngine(atc.G, &ListTrackingEngineArg{}) 247 if err := RunEngine2(NewMetaContextForTest(atc), eng); err != nil { 248 t.Fatal("Error in ListTrackingEngine:", err) 249 } 250 res1 := eng.TableResult() 251 252 // realAPI := atc.G.API 253 fakeAPI := &errorAPIMock{} 254 atc.G.API = fakeAPI 255 256 // We're offline now 257 _, _, err = runTrack(atc, alice, charlie.Username, sigVersion) 258 require.Error(t, err) 259 require.Contains(t, err.Error(), "timeout or something") 260 261 c := clockwork.NewFakeClockAt(atc.G.Clock().Now()) 262 atc.G.SetClock(c) 263 264 t.Logf("Test CachedOnly") 265 // But ListTracking with CachedOnly=true should still work. 266 eng = NewListTrackingEngine(atc.G, &ListTrackingEngineArg{CachedOnly: true}) 267 err = RunEngine2(NewMetaContextForTest(atc), eng) 268 require.NoError(t, err) 269 res2 := eng.TableResult() 270 require.Equal(t, res1, res2, "got same results even when offline") 271 272 staleness := time.Hour * 24 * 7 273 t.Logf("Test offline 1 day later") 274 // Should work even if we're still offline 1 day later (longer than the 10 275 // minute UPAK staleness window), if CachedOnlyStalenessWindow passed. 276 stalenesseng := NewListTrackingEngine(atc.G, &ListTrackingEngineArg{CachedOnly: true, CachedOnlyStalenessWindow: &staleness}) 277 c.Advance(time.Hour * 24) 278 err = RunEngine2(NewMetaContextForTest(atc), stalenesseng) 279 require.NoError(t, err) 280 281 t.Logf("Should return an error past the staleness window") 282 c.Advance(time.Hour * 24 * 8) 283 err = RunEngine2(NewMetaContextForTest(atc), stalenesseng) 284 require.Error(t, err) 285 require.IsType(t, err, libkb.UserNotFoundError{}) 286 }