1// Copyright 2015 Keybase, Inc. All rights reserved. Use of 2// this source code is governed by the included BSD license. 3 4package systests 5 6import ( 7 "fmt" 8 "os" 9 "path/filepath" 10 "testing" 11 "time" 12 13 "net/http" 14 _ "net/http/pprof" 15 16 "github.com/keybase/client/go/externalstest" 17 "github.com/keybase/client/go/libkb" 18 keybase1 "github.com/keybase/client/go/protocol/keybase1" 19 "github.com/keybase/clockwork" 20 "github.com/stretchr/testify/require" 21 context "golang.org/x/net/context" 22) 23 24func TestMain(m *testing.M) { 25 if os.Getenv("KEYBASE_SYSTESTS_DEBUG") != "" { 26 go func() { 27 _ = http.ListenAndServe("localhost:8080", nil) 28 }() 29 } 30 os.Exit(m.Run()) 31} 32 33func setupTest(t libkb.TestingTB, nm string) *libkb.TestContext { 34 tc := externalstest.SetupTest(t, nm, 2) 35 installInsecureTriplesec(tc.G) 36 tc.SetRuntimeDir(filepath.Join(tc.Tp.Home, "run")) 37 if err := tc.G.ConfigureSocketInfo(); err != nil { 38 t.Fatal(err) 39 } 40 return &tc 41} 42 43func cloneContext(prev *libkb.TestContext) *libkb.TestContext { 44 ret := prev.Clone() 45 ret.SetRuntimeDir(filepath.Join(ret.Tp.Home, "run")) 46 if err := ret.G.ConfigureSocketInfo(); err != nil { 47 ret.T.Fatal(err) 48 } 49 return &ret 50} 51 52type baseNullUI struct { 53 g *libkb.GlobalContext 54} 55 56type dumbUI struct{} 57 58func (d dumbUI) Printf(format string, args ...interface{}) (int, error) { 59 return 0, nil 60} 61func (d dumbUI) PrintfStderr(format string, args ...interface{}) (int, error) { 62 return 0, nil 63} 64func (d dumbUI) PrintfUnescaped(format string, args ...interface{}) (int, error) { 65 return 0, nil 66} 67 68func (n *baseNullUI) GetDumbOutputUI() libkb.DumbOutputUI { return dumbUI{} } 69func (n *baseNullUI) GetIdentifyUI() libkb.IdentifyUI { return nil } 70func (n *baseNullUI) GetIdentifySelfUI() libkb.IdentifyUI { return nil } 71func (n *baseNullUI) GetIdentifyTrackUI() libkb.IdentifyUI { return nil } 72func (n *baseNullUI) GetLoginUI() libkb.LoginUI { return nil } 73func (n *baseNullUI) GetTerminalUI() libkb.TerminalUI { return nil } 74func (n *baseNullUI) GetSecretUI() libkb.SecretUI { return nil } 75func (n *baseNullUI) GetProveUI() libkb.ProveUI { return nil } 76func (n *baseNullUI) GetGPGUI() libkb.GPGUI { return nil } 77func (n *baseNullUI) GetLogUI() libkb.LogUI { return n.g.Log } 78func (n *baseNullUI) GetPgpUI() libkb.PgpUI { return nil } 79func (n *baseNullUI) GetProvisionUI(libkb.KexRole) libkb.ProvisionUI { return nil } 80 81func (n *baseNullUI) Configure() error { return nil } 82func (n *baseNullUI) Shutdown() error { return nil } 83 84type genericUI struct { 85 g *libkb.GlobalContext 86 DumbOutputUI libkb.DumbOutputUI 87 IdentifyUI libkb.IdentifyUI 88 IdentifySelfUI libkb.IdentifyUI 89 IdentifyTrackUI libkb.IdentifyUI 90 LoginUI libkb.LoginUI 91 TerminalUI libkb.TerminalUI 92 SecretUI libkb.SecretUI 93 ProveUI libkb.ProveUI 94 GPGUI libkb.GPGUI 95 LogUI libkb.LogUI 96 PgpUI libkb.PgpUI 97 ProvisionUI libkb.ProvisionUI 98} 99 100func (n *genericUI) GetDumbOutputUI() libkb.DumbOutputUI { 101 if n.DumbOutputUI == nil { 102 return dumbUI{} 103 } 104 return n.DumbOutputUI 105} 106func (n *genericUI) GetIdentifyUI() libkb.IdentifyUI { return n.IdentifyUI } 107func (n *genericUI) GetIdentifySelfUI() libkb.IdentifyUI { return n.IdentifyUI } 108func (n *genericUI) GetIdentifyTrackUI() libkb.IdentifyUI { return n.IdentifyUI } 109func (n *genericUI) GetLoginUI() libkb.LoginUI { return n.LoginUI } 110func (n *genericUI) GetTerminalUI() libkb.TerminalUI { return n.TerminalUI } 111func (n *genericUI) GetSecretUI() libkb.SecretUI { return n.SecretUI } 112func (n *genericUI) GetProveUI() libkb.ProveUI { return n.ProveUI } 113func (n *genericUI) GetGPGUI() libkb.GPGUI { return n.GPGUI } 114func (n *genericUI) GetLogUI() libkb.LogUI { 115 if n.LogUI == nil { 116 return n.g.Log 117 } 118 return n.LogUI 119} 120func (n *genericUI) GetPgpUI() libkb.PgpUI { return n.PgpUI } 121func (n *genericUI) GetProvisionUI(libkb.KexRole) libkb.ProvisionUI { return n.ProvisionUI } 122 123func (n *genericUI) Configure() error { return nil } 124func (n *genericUI) Shutdown() error { return nil } 125 126type nullProvisionUI struct { 127 deviceName string 128} 129 130func (n nullProvisionUI) ChooseProvisioningMethod(context.Context, keybase1.ChooseProvisioningMethodArg) (ret keybase1.ProvisionMethod, err error) { 131 return ret, nil 132} 133func (n nullProvisionUI) ChooseGPGMethod(context.Context, keybase1.ChooseGPGMethodArg) (ret keybase1.GPGMethod, err error) { 134 return ret, nil 135} 136func (n nullProvisionUI) SwitchToGPGSignOK(context.Context, keybase1.SwitchToGPGSignOKArg) (bool, error) { 137 return false, nil 138} 139func (n nullProvisionUI) ChooseDevice(context.Context, keybase1.ChooseDeviceArg) (ret keybase1.DeviceID, err error) { 140 return ret, nil 141} 142func (n nullProvisionUI) ChooseDeviceType(context.Context, keybase1.ChooseDeviceTypeArg) (ret keybase1.DeviceType, err error) { 143 return ret, nil 144} 145func (n nullProvisionUI) DisplayAndPromptSecret(context.Context, keybase1.DisplayAndPromptSecretArg) (ret keybase1.SecretResponse, err error) { 146 return ret, nil 147} 148func (n nullProvisionUI) DisplaySecretExchanged(context.Context, int) error { return nil } 149func (n nullProvisionUI) PromptNewDeviceName(context.Context, keybase1.PromptNewDeviceNameArg) (string, error) { 150 return n.deviceName, nil 151} 152func (n nullProvisionUI) ProvisioneeSuccess(context.Context, keybase1.ProvisioneeSuccessArg) error { 153 return nil 154} 155func (n nullProvisionUI) ProvisionerSuccess(context.Context, keybase1.ProvisionerSuccessArg) error { 156 return nil 157} 158 159func getActiveDevicesAndKeys(tc *libkb.TestContext, username string) ([]*libkb.Device, []libkb.GenericKey) { 160 arg := libkb.NewLoadUserByNameArg(tc.G, username).WithPublicKeyOptional() 161 user, err := libkb.LoadUser(arg) 162 if err != nil { 163 tc.T.Fatal(err) 164 } 165 sibkeys := user.GetComputedKeyFamily().GetAllActiveSibkeys() 166 subkeys := user.GetComputedKeyFamily().GetAllActiveSubkeys() 167 168 activeDevices := []*libkb.Device{} 169 for _, device := range user.GetComputedKeyFamily().GetAllDevices() { 170 if device.Status != nil && *device.Status == libkb.DeviceStatusActive { 171 activeDevices = append(activeDevices, device.Device) 172 } 173 } 174 return activeDevices, append(sibkeys, subkeys...) 175} 176 177func pollFor(t *testing.T, label string, totalTime time.Duration, g *libkb.GlobalContext, poller func(i int) bool) { 178 t.Logf("pollFor '%s'", label) 179 totalTime *= libkb.CITimeMultiplier(g) 180 clock := clockwork.NewRealClock() 181 start := clock.Now() 182 endCh := clock.After(totalTime) 183 wait := 10 * time.Millisecond 184 var i int 185 for { 186 satisfied := poller(i) 187 since := clock.Since(start) 188 t.Logf("pollFor '%s' round:%v -> %v running:%v", label, i, satisfied, since) 189 if satisfied { 190 t.Logf("pollFor '%s' succeeded after %v attempts over %v", label, i, since) 191 return 192 } 193 if since > totalTime { 194 // Game over 195 msg := fmt.Sprintf("pollFor '%s' timed out after %v attempts over %v", label, i, since) 196 t.Logf(msg) 197 require.Fail(t, msg) 198 require.FailNow(t, msg) 199 return 200 } 201 t.Logf("pollFor '%s' wait:%v", label, wait) 202 select { 203 case <-endCh: 204 case <-clock.After(wait): 205 } 206 wait *= 2 207 i++ 208 } 209} 210