mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 13:05:46 +00:00
ipn/ipnlocal: some state_test cleanups.
This doesn't change the actual functionality. Just some additional comments and fine tuning. Signed-off-by: Avery Pennarun <apenwarr@tailscale.com>
This commit is contained in:
parent
ac9cd48c80
commit
b0382ca167
@ -18,6 +18,8 @@
|
|||||||
"tailscale.com/types/empty"
|
"tailscale.com/types/empty"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/types/netmap"
|
"tailscale.com/types/netmap"
|
||||||
|
"tailscale.com/types/persist"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
"tailscale.com/wgengine"
|
"tailscale.com/wgengine"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -89,6 +91,8 @@ type mockControl struct {
|
|||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
calls []string
|
calls []string
|
||||||
authBlocked bool
|
authBlocked bool
|
||||||
|
persist persist.Persist
|
||||||
|
machineKey wgkey.Private
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMockControl() *mockControl {
|
func newMockControl() *mockControl {
|
||||||
@ -102,13 +106,30 @@ func (cc *mockControl) SetStatusFunc(fn func(controlclient.Status)) {
|
|||||||
cc.statusFunc = fn
|
cc.statusFunc = fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cc *mockControl) populateKeys() {
|
||||||
|
cc.mu.Lock()
|
||||||
|
defer cc.mu.Unlock()
|
||||||
|
|
||||||
|
if cc.machineKey.IsZero() {
|
||||||
|
cc.logf("Copying machineKey.")
|
||||||
|
cc.machineKey, _ = cc.opts.GetMachinePrivateKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
if cc.persist.PrivateNodeKey.IsZero() {
|
||||||
|
cc.logf("Generating a new nodekey.")
|
||||||
|
cc.persist.OldPrivateNodeKey = cc.persist.PrivateNodeKey
|
||||||
|
cc.persist.PrivateNodeKey, _ = wgkey.NewPrivate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// send publishes a controlclient.Status notification upstream.
|
// send publishes a controlclient.Status notification upstream.
|
||||||
// (In our tests here, upstream is the ipnlocal.Local instance.)
|
// (In our tests here, upstream is the ipnlocal.Local instance.)
|
||||||
func (cc *mockControl) send(err error, url string, loginFinished bool, nm *netmap.NetworkMap) {
|
func (cc *mockControl) send(err error, url string, loginFinished bool, nm *netmap.NetworkMap) {
|
||||||
if cc.statusFunc != nil {
|
if cc.statusFunc != nil {
|
||||||
s := controlclient.Status{
|
s := controlclient.Status{
|
||||||
URL: url,
|
URL: url,
|
||||||
NetMap: nm,
|
NetMap: nm,
|
||||||
|
Persist: &cc.persist,
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Err = err.Error()
|
s.Err = err.Error()
|
||||||
@ -170,6 +191,7 @@ func (cc *mockControl) Shutdown() {
|
|||||||
func (cc *mockControl) Login(t *tailcfg.Oauth2Token, flags controlclient.LoginFlags) {
|
func (cc *mockControl) Login(t *tailcfg.Oauth2Token, flags controlclient.LoginFlags) {
|
||||||
cc.logf("Login token=%v flags=%v", t, flags)
|
cc.logf("Login token=%v flags=%v", t, flags)
|
||||||
cc.called("Login")
|
cc.called("Login")
|
||||||
|
cc.populateKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *mockControl) StartLogout() {
|
func (cc *mockControl) StartLogout() {
|
||||||
@ -285,6 +307,7 @@ func TestStateMachine(t *testing.T) {
|
|||||||
// Start the state machine.
|
// Start the state machine.
|
||||||
// Since !WantRunning by default, it'll create a controlclient,
|
// Since !WantRunning by default, it'll create a controlclient,
|
||||||
// but not ask it to do anything yet.
|
// but not ask it to do anything yet.
|
||||||
|
t.Logf("\n\nStart")
|
||||||
notifies.expect(2)
|
notifies.expect(2)
|
||||||
assert.Nil(b.Start(ipn.Options{
|
assert.Nil(b.Start(ipn.Options{
|
||||||
StateKey: ipn.GlobalDaemonStateKey,
|
StateKey: ipn.GlobalDaemonStateKey,
|
||||||
@ -299,7 +322,6 @@ func TestStateMachine(t *testing.T) {
|
|||||||
assert.NotNil(nn[1].State)
|
assert.NotNil(nn[1].State)
|
||||||
prefs := *nn[0].Prefs
|
prefs := *nn[0].Prefs
|
||||||
assert.Equal(false, prefs.WantRunning)
|
assert.Equal(false, prefs.WantRunning)
|
||||||
// BUG: there should be a NoState first, to tell the GUI to show "Loading..."
|
|
||||||
assert.Equal(ipn.NeedsLogin, *nn[1].State)
|
assert.Equal(ipn.NeedsLogin, *nn[1].State)
|
||||||
assert.Equal(ipn.NeedsLogin, b.State())
|
assert.Equal(ipn.NeedsLogin, b.State())
|
||||||
}
|
}
|
||||||
@ -321,9 +343,7 @@ func TestStateMachine(t *testing.T) {
|
|||||||
assert.Equal([]string{}, cc.getCalls())
|
assert.Equal([]string{}, cc.getCalls())
|
||||||
assert.NotNil(nn[0].Prefs)
|
assert.NotNil(nn[0].Prefs)
|
||||||
assert.NotNil(nn[1].State)
|
assert.NotNil(nn[1].State)
|
||||||
prefs := *nn[0].Prefs
|
assert.Equal(false, nn[0].Prefs.WantRunning)
|
||||||
assert.Equal(false, prefs.WantRunning)
|
|
||||||
// BUG: there should be a NoState first, to tell the GUI to show "Loading..."
|
|
||||||
assert.Equal(ipn.NeedsLogin, *nn[1].State)
|
assert.Equal(ipn.NeedsLogin, *nn[1].State)
|
||||||
assert.Equal(ipn.NeedsLogin, b.State())
|
assert.Equal(ipn.NeedsLogin, b.State())
|
||||||
}
|
}
|
||||||
@ -361,7 +381,7 @@ func TestStateMachine(t *testing.T) {
|
|||||||
nn := notifies.drain(1)
|
nn := notifies.drain(1)
|
||||||
|
|
||||||
// Trying to log in automatically sets WantRunning.
|
// Trying to log in automatically sets WantRunning.
|
||||||
// BUG: this should have happened right after Login().
|
// BUG: that should have happened right after Login().
|
||||||
assert.NotNil(nn[0].Prefs)
|
assert.NotNil(nn[0].Prefs)
|
||||||
assert.Equal(true, nn[0].Prefs.WantRunning)
|
assert.Equal(true, nn[0].Prefs.WantRunning)
|
||||||
}
|
}
|
||||||
@ -510,6 +530,8 @@ func TestStateMachine(t *testing.T) {
|
|||||||
// Test the fast-path frontend reconnection.
|
// Test the fast-path frontend reconnection.
|
||||||
// This one is very finicky, so we have to force State==Running.
|
// This one is very finicky, so we have to force State==Running.
|
||||||
// TODO: actually get to State==Running, rather than cheating.
|
// TODO: actually get to State==Running, rather than cheating.
|
||||||
|
// That'll require spinning up a fake DERP server and putting it in
|
||||||
|
// the netmap.
|
||||||
t.Logf("\n\nFastpath Start()")
|
t.Logf("\n\nFastpath Start()")
|
||||||
notifies.expect(1)
|
notifies.expect(1)
|
||||||
b.state = ipn.Running
|
b.state = ipn.Running
|
||||||
@ -546,6 +568,7 @@ func TestStateMachine(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Let's make the logout succeed.
|
// Let's make the logout succeed.
|
||||||
|
t.Logf("\n\nLogout (async) - succeed")
|
||||||
notifies.expect(1)
|
notifies.expect(1)
|
||||||
cc.setAuthBlocked(true)
|
cc.setAuthBlocked(true)
|
||||||
cc.send(nil, "", false, nil)
|
cc.send(nil, "", false, nil)
|
||||||
@ -566,9 +589,11 @@ func TestStateMachine(t *testing.T) {
|
|||||||
// BUG: the backend has already called StartLogout, and we're
|
// BUG: the backend has already called StartLogout, and we're
|
||||||
// still logged out. So it shouldn't call it again.
|
// still logged out. So it shouldn't call it again.
|
||||||
assert.Equal([]string{"StartLogout"}, cc.getCalls())
|
assert.Equal([]string{"StartLogout"}, cc.getCalls())
|
||||||
|
assert.Equal(ipn.NeedsLogin, b.State())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's acknowledge the second logout too.
|
// Let's acknowledge the second logout too.
|
||||||
|
t.Logf("\n\nLogout2 (async) - succeed")
|
||||||
notifies.expect(1)
|
notifies.expect(1)
|
||||||
cc.setAuthBlocked(true)
|
cc.setAuthBlocked(true)
|
||||||
cc.send(nil, "", false, nil)
|
cc.send(nil, "", false, nil)
|
||||||
@ -578,6 +603,7 @@ func TestStateMachine(t *testing.T) {
|
|||||||
assert.NotNil(nn[0].Prefs)
|
assert.NotNil(nn[0].Prefs)
|
||||||
// BUG: second logout shouldn't cause WantRunning->true !!
|
// BUG: second logout shouldn't cause WantRunning->true !!
|
||||||
assert.Equal(true, nn[0].Prefs.WantRunning)
|
assert.Equal(true, nn[0].Prefs.WantRunning)
|
||||||
|
assert.Equal(ipn.NeedsLogin, b.State())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try the synchronous logout feature.
|
// Try the synchronous logout feature.
|
||||||
@ -591,9 +617,11 @@ func TestStateMachine(t *testing.T) {
|
|||||||
assert.Equal([]string{"Logout"}, cc.getCalls())
|
assert.Equal([]string{"Logout"}, cc.getCalls())
|
||||||
assert.NotNil(nn[0].Prefs)
|
assert.NotNil(nn[0].Prefs)
|
||||||
assert.Equal(false, nn[0].Prefs.WantRunning)
|
assert.Equal(false, nn[0].Prefs.WantRunning)
|
||||||
|
assert.Equal(ipn.NeedsLogin, b.State())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the third logout event.
|
// Generate the third logout event.
|
||||||
|
t.Logf("\n\nLogout3 (sync) - succeed")
|
||||||
notifies.expect(1)
|
notifies.expect(1)
|
||||||
cc.setAuthBlocked(true)
|
cc.setAuthBlocked(true)
|
||||||
cc.send(nil, "", false, nil)
|
cc.send(nil, "", false, nil)
|
||||||
@ -603,6 +631,7 @@ func TestStateMachine(t *testing.T) {
|
|||||||
assert.NotNil(nn[0].Prefs)
|
assert.NotNil(nn[0].Prefs)
|
||||||
// BUG: third logout shouldn't cause WantRunning->true !!
|
// BUG: third logout shouldn't cause WantRunning->true !!
|
||||||
assert.Equal(true, nn[0].Prefs.WantRunning)
|
assert.Equal(true, nn[0].Prefs.WantRunning)
|
||||||
|
assert.Equal(ipn.NeedsLogin, b.State())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shut down the backend.
|
// Shut down the backend.
|
||||||
@ -620,7 +649,7 @@ func TestStateMachine(t *testing.T) {
|
|||||||
// Note that it's explicitly okay to call b.Start() over and over
|
// Note that it's explicitly okay to call b.Start() over and over
|
||||||
// again, every time the frontend reconnects.
|
// again, every time the frontend reconnects.
|
||||||
//
|
//
|
||||||
// BUG: WantRunning should be true here (because of the bug above).
|
// BUG: WantRunning is true here (because of the bug above).
|
||||||
// We'll have to adjust the following test's expectations if we
|
// We'll have to adjust the following test's expectations if we
|
||||||
// fix that.
|
// fix that.
|
||||||
|
|
||||||
@ -645,9 +674,7 @@ func TestStateMachine(t *testing.T) {
|
|||||||
assert.Equal([]string{}, cc.getCalls())
|
assert.Equal([]string{}, cc.getCalls())
|
||||||
assert.NotNil(nn[0].Prefs)
|
assert.NotNil(nn[0].Prefs)
|
||||||
assert.NotNil(nn[1].State)
|
assert.NotNil(nn[1].State)
|
||||||
prefs := *nn[0].Prefs
|
assert.Equal(true, nn[0].Prefs.WantRunning)
|
||||||
assert.Equal(true, prefs.WantRunning)
|
|
||||||
// BUG: there should be a NoState first, to tell the GUI to show "Loading..."
|
|
||||||
assert.Equal(ipn.NeedsLogin, *nn[1].State)
|
assert.Equal(ipn.NeedsLogin, *nn[1].State)
|
||||||
assert.Equal(ipn.NeedsLogin, b.State())
|
assert.Equal(ipn.NeedsLogin, b.State())
|
||||||
}
|
}
|
||||||
@ -703,7 +730,6 @@ func TestStateMachine(t *testing.T) {
|
|||||||
assert.NotNil(nn[1].State)
|
assert.NotNil(nn[1].State)
|
||||||
prefs := *nn[0].Prefs
|
prefs := *nn[0].Prefs
|
||||||
assert.Equal(false, prefs.WantRunning)
|
assert.Equal(false, prefs.WantRunning)
|
||||||
// BUG: there should be a NoState first, to tell the GUI to show "Loading..."
|
|
||||||
// BUG: NeedsLogin is incorrect. We are already logged in.
|
// BUG: NeedsLogin is incorrect. We are already logged in.
|
||||||
// This is the cause of bug tailscale/corp#1660.
|
// This is the cause of bug tailscale/corp#1660.
|
||||||
// (Whenever we enter the NeedsLogin state, the UI will
|
// (Whenever we enter the NeedsLogin state, the UI will
|
||||||
|
Loading…
Reference in New Issue
Block a user