~mterry/ubuntu-push/wake-screen

« back to all changes in this revision

Viewing changes to client/client_test.go

  • Committer: CI Train Bot
  • Author(s): Samuele Pedroni (Canonical Services Ltd.)
  • Date: 2015-04-03 13:27:41 UTC
  • mfrom: (143.1.2 vivid)
  • Revision ID: ci-train-bot@canonical.com-20150403132741-dzovofwogdhky960
[Roberto Alsina]
* click-hook: report failure if hooks_path doesn't exist. [client]

[Bret Barker]
* add a hacky busy sleep loop to workaround go's sleep not
  accounting for suspended time, more logging (lp:1435109). [client]

[John R. Lenton]
* Refactor code maintaining session (better fix for lp:1390663) [client]

[Samuele Pedroni]
* just delegate whether there's a update-worthy image to the
  system-settings helper and system-image. [client]
* stop waking up for polling if in flight-mode and wireless not
  enabled (lp:1437135). [client]
* don't hold a lock for a long time on handleErrConn, trigger
  autoRedial on Error more actively (lp:1435109). [client]
* disallow RC4 and SSLv3. [server]
Approved by: Roberto Alsina

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
        clickhelp "launchpad.net/ubuntu-push/click/testing"
44
44
        "launchpad.net/ubuntu-push/client/service"
45
45
        "launchpad.net/ubuntu-push/client/session"
46
 
        "launchpad.net/ubuntu-push/client/session/seenstate"
47
46
        "launchpad.net/ubuntu-push/config"
48
47
        "launchpad.net/ubuntu-push/identifier"
49
48
        idtesting "launchpad.net/ubuntu-push/identifier/testing"
186
185
                "poll_net_wait":    "1m",
187
186
                "poll_polld_wait":  "3m",
188
187
                "poll_done_wait":   "5s",
 
188
                "poll_busy_wait":   "0s",
189
189
        }
190
190
        for k, v := range overrides {
191
191
                cfgMap[k] = v
427
427
                AuthGetter:       func(string) string { return "" },
428
428
                AuthURL:          "xyzzy://",
429
429
                AddresseeChecker: cli,
 
430
                BroadcastCh:      make(chan *session.BroadcastNotification),
 
431
                NotificationsCh:  make(chan session.AddressedNotification),
430
432
        }
431
433
        // sanity check that we are looking at all fields
432
434
        vExpected := reflect.ValueOf(expected)
440
442
        conf := cli.deriveSessionConfig(info)
441
443
        // compare authGetter by string
442
444
        c.Check(fmt.Sprintf("%#v", conf.AuthGetter), Equals, fmt.Sprintf("%#v", cli.getAuthorization))
 
445
        // channels are ok as long as non-nil
 
446
        conf.BroadcastCh = nil
 
447
        conf.NotificationsCh = nil
 
448
        expected.BroadcastCh = nil
 
449
        expected.NotificationsCh = nil
443
450
        // and set it to nil
444
451
        conf.AuthGetter = nil
445
452
        expected.AuthGetter = nil
521
528
/*****************************************************************
522
529
    derivePollerSetup tests
523
530
******************************************************************/
 
531
type derivePollerSession struct{}
 
532
 
 
533
func (s *derivePollerSession) ResetCookie()                      {}
 
534
func (s *derivePollerSession) State() session.ClientSessionState { return session.Unknown }
 
535
func (s *derivePollerSession) HasConnectivity(bool)              {}
 
536
func (s *derivePollerSession) KeepConnection() error             { return nil }
 
537
func (s *derivePollerSession) StopKeepConnection()               {}
 
538
 
524
539
func (cs *clientSuite) TestDerivePollerSetup(c *C) {
525
540
        cs.writeTestConfig(map[string]interface{}{})
526
541
        cli := NewPushClient(cs.configPath, cs.leveldbPath)
527
 
        cli.session = new(session.ClientSession)
 
542
        cli.session = new(derivePollerSession)
528
543
        err := cli.configure()
529
544
        c.Assert(err, IsNil)
530
545
        expected := &poller.PollerSetup{
705
720
}
706
721
 
707
722
/*****************************************************************
708
 
    handleErr tests
709
 
******************************************************************/
710
 
 
711
 
func (cs *clientSuite) TestHandleErr(c *C) {
712
 
        cli := NewPushClient(cs.configPath, cs.leveldbPath)
713
 
        cli.log = cs.log
714
 
        cli.systemImageInfo = siInfoRes
715
 
        c.Assert(cli.initSessionAndPoller(), IsNil)
716
 
        cs.log.ResetCapture()
717
 
        cli.hasConnectivity = true
718
 
        defer cli.session.Close()
719
 
        cli.handleErr(errors.New("bananas"))
720
 
        c.Check(cs.log.Captured(), Matches, ".*session exited.*bananas\n")
721
 
}
722
 
 
723
 
/*****************************************************************
724
723
    seenStateFactory tests
725
724
******************************************************************/
726
725
 
741
740
}
742
741
 
743
742
/*****************************************************************
744
 
    handleConnState tests
745
 
******************************************************************/
746
 
 
747
 
func (cs *clientSuite) TestHandleConnStateD2C(c *C) {
748
 
        cli := NewPushClient(cs.configPath, cs.leveldbPath)
749
 
        cli.log = cs.log
750
 
        cli.systemImageInfo = siInfoRes
751
 
        c.Assert(cli.initSessionAndPoller(), IsNil)
752
 
 
753
 
        c.Assert(cli.hasConnectivity, Equals, false)
754
 
        defer cli.session.Close()
755
 
        cli.handleConnState(true)
756
 
        c.Check(cli.hasConnectivity, Equals, true)
757
 
        c.Assert(cli.session, NotNil)
758
 
}
759
 
 
760
 
func (cs *clientSuite) TestHandleConnStateSame(c *C) {
761
 
        cli := NewPushClient(cs.configPath, cs.leveldbPath)
762
 
        cli.log = cs.log
763
 
        // here we want to check that we don't do anything
764
 
        c.Assert(cli.session, IsNil)
765
 
        c.Assert(cli.hasConnectivity, Equals, false)
766
 
        cli.handleConnState(false)
767
 
        c.Check(cli.session, IsNil)
768
 
 
769
 
        cli.hasConnectivity = true
770
 
        cli.handleConnState(true)
771
 
        c.Check(cli.session, IsNil)
772
 
}
773
 
 
774
 
func (cs *clientSuite) TestHandleConnStateC2D(c *C) {
775
 
        cli := NewPushClient(cs.configPath, cs.leveldbPath)
776
 
        cli.log = cs.log
777
 
        cli.session, _ = session.NewSession(cli.config.Addr, cli.deriveSessionConfig(nil), cli.deviceId, seenstate.NewSeenState, cs.log)
778
 
        cli.session.Dial()
779
 
        cli.hasConnectivity = true
780
 
 
781
 
        // cli.session.State() will be "Error" here, for now at least
782
 
        c.Check(cli.session.State(), Not(Equals), session.Disconnected)
783
 
        cli.handleConnState(false)
784
 
        c.Check(cli.session.State(), Equals, session.Disconnected)
785
 
}
786
 
 
787
 
func (cs *clientSuite) TestHandleConnStateC2DPending(c *C) {
788
 
        cli := NewPushClient(cs.configPath, cs.leveldbPath)
789
 
        cli.log = cs.log
790
 
        cli.session, _ = session.NewSession(cli.config.Addr, cli.deriveSessionConfig(nil), cli.deviceId, seenstate.NewSeenState, cs.log)
791
 
        cli.hasConnectivity = true
792
 
 
793
 
        cli.handleConnState(false)
794
 
        c.Check(cli.session.State(), Equals, session.Disconnected)
795
 
}
796
 
 
797
 
/*****************************************************************
798
743
   filterBroadcastNotification tests
799
744
******************************************************************/
800
745
 
811
756
        // empty
812
757
        msg := &session.BroadcastNotification{}
813
758
        c.Check(cli.filterBroadcastNotification(msg), Equals, false)
814
 
        // same build number
815
 
        msg = &session.BroadcastNotification{
816
 
                Decoded: []map[string]interface{}{
817
 
                        map[string]interface{}{
818
 
                                "daily/mako": []interface{}{float64(102), "tubular"},
819
 
                        },
820
 
                },
821
 
        }
822
 
        c.Check(cli.filterBroadcastNotification(msg), Equals, false)
823
 
        // higher build number and pick last
824
 
        msg = &session.BroadcastNotification{
825
 
                Decoded: []map[string]interface{}{
826
 
                        map[string]interface{}{
827
 
                                "daily/mako": []interface{}{float64(102), "tubular"},
828
 
                        },
829
 
                        map[string]interface{}{
830
 
                                "daily/mako": []interface{}{float64(103), "tubular"},
831
 
                        },
832
 
                },
833
 
        }
834
 
        c.Check(cli.filterBroadcastNotification(msg), Equals, true)
835
 
        // going backward by a margin, assume switch of alias
836
 
        msg = &session.BroadcastNotification{
837
 
                Decoded: []map[string]interface{}{
838
 
                        map[string]interface{}{
839
 
                                "daily/mako": []interface{}{float64(102), "tubular"},
840
 
                        },
841
 
                        map[string]interface{}{
842
 
                                "daily/mako": []interface{}{float64(2), "urban"},
 
759
        // same build number, we let the helper deal
 
760
        msg = &session.BroadcastNotification{
 
761
                Decoded: []map[string]interface{}{
 
762
                        map[string]interface{}{
 
763
                                "daily/mako": []interface{}{float64(102), "tubular"},
843
764
                        },
844
765
                },
845
766
        }
888
809
        }
889
810
        negativeBroadcastNotification = &session.BroadcastNotification{
890
811
                Decoded: []map[string]interface{}{
891
 
                        map[string]interface{}{
892
 
                                "daily/mako": []interface{}{float64(102), "tubular"},
893
 
                        },
 
812
                        map[string]interface{}{},
894
813
                },
895
814
        }
896
815
)
1012
931
var nopConn = func(bool) {}
1013
932
var nopBcast = func(*session.BroadcastNotification) error { return nil }
1014
933
var nopUcast = func(session.AddressedNotification) error { return nil }
1015
 
var nopError = func(error) {}
1016
934
var nopUnregister = func(*click.AppId) {}
1017
935
var nopAcct = func() {}
1018
936
 
1025
943
        c.Assert(cli.initSessionAndPoller(), IsNil)
1026
944
 
1027
945
        ch := make(chan bool, 1)
1028
 
        go cli.doLoop(func(bool) { ch <- true }, nopBcast, nopUcast, nopError, nopUnregister, nopAcct)
 
946
        go cli.doLoop(func(bool) { ch <- true }, nopBcast, nopUcast, nopUnregister, nopAcct)
1029
947
        c.Check(takeNextBool(ch), Equals, true)
1030
948
}
1031
949
 
1034
952
        cli.log = cs.log
1035
953
        cli.systemImageInfo = siInfoRes
1036
954
        c.Assert(cli.initSessionAndPoller(), IsNil)
1037
 
        cli.session.BroadcastCh = make(chan *session.BroadcastNotification, 1)
1038
 
        cli.session.BroadcastCh <- &session.BroadcastNotification{}
 
955
        cli.broadcastCh = make(chan *session.BroadcastNotification, 1)
 
956
        cli.broadcastCh <- &session.BroadcastNotification{}
1039
957
 
1040
958
        ch := make(chan bool, 1)
1041
 
        go cli.doLoop(nopConn, func(_ *session.BroadcastNotification) error { ch <- true; return nil }, nopUcast, nopError, nopUnregister, nopAcct)
 
959
        go cli.doLoop(nopConn, func(_ *session.BroadcastNotification) error { ch <- true; return nil }, nopUcast, nopUnregister, nopAcct)
1042
960
        c.Check(takeNextBool(ch), Equals, true)
1043
961
}
1044
962
 
1047
965
        cli.log = cs.log
1048
966
        cli.systemImageInfo = siInfoRes
1049
967
        c.Assert(cli.initSessionAndPoller(), IsNil)
1050
 
        cli.session.NotificationsCh = make(chan session.AddressedNotification, 1)
1051
 
        cli.session.NotificationsCh <- session.AddressedNotification{}
1052
 
 
1053
 
        ch := make(chan bool, 1)
1054
 
        go cli.doLoop(nopConn, nopBcast, func(session.AddressedNotification) error { ch <- true; return nil }, nopError, nopUnregister, nopAcct)
1055
 
        c.Check(takeNextBool(ch), Equals, true)
1056
 
}
1057
 
 
1058
 
func (cs *clientSuite) TestDoLoopErr(c *C) {
1059
 
        cli := NewPushClient(cs.configPath, cs.leveldbPath)
1060
 
        cli.log = cs.log
1061
 
        cli.systemImageInfo = siInfoRes
1062
 
        c.Assert(cli.initSessionAndPoller(), IsNil)
1063
 
        cli.session.ErrCh = make(chan error, 1)
1064
 
        cli.session.ErrCh <- nil
1065
 
 
1066
 
        ch := make(chan bool, 1)
1067
 
        go cli.doLoop(nopConn, nopBcast, nopUcast, func(error) { ch <- true }, nopUnregister, nopAcct)
 
968
        cli.notificationsCh = make(chan session.AddressedNotification, 1)
 
969
        cli.notificationsCh <- session.AddressedNotification{}
 
970
 
 
971
        ch := make(chan bool, 1)
 
972
        go cli.doLoop(nopConn, nopBcast, func(session.AddressedNotification) error { ch <- true; return nil }, nopUnregister, nopAcct)
1068
973
        c.Check(takeNextBool(ch), Equals, true)
1069
974
}
1070
975
 
1077
982
        cli.unregisterCh <- app1
1078
983
 
1079
984
        ch := make(chan bool, 1)
1080
 
        go cli.doLoop(nopConn, nopBcast, nopUcast, nopError, func(app *click.AppId) { c.Check(app.Original(), Equals, appId1); ch <- true }, nopAcct)
 
985
        go cli.doLoop(nopConn, nopBcast, nopUcast, func(app *click.AppId) { c.Check(app.Original(), Equals, appId1); ch <- true }, nopAcct)
1081
986
        c.Check(takeNextBool(ch), Equals, true)
1082
987
}
1083
988
 
1091
996
        cli.accountsCh = acctCh
1092
997
 
1093
998
        ch := make(chan bool, 1)
1094
 
        go cli.doLoop(nopConn, nopBcast, nopUcast, nopError, nopUnregister, func() { ch <- true })
 
999
        go cli.doLoop(nopConn, nopBcast, nopUcast, nopUnregister, func() { ch <- true })
1095
1000
        c.Check(takeNextBool(ch), Equals, true)
1096
1001
}
1097
1002
 
1126
1031
    Loop() tests
1127
1032
******************************************************************/
1128
1033
 
 
1034
type loopSession struct{ hasConn bool }
 
1035
 
 
1036
func (s *loopSession) ResetCookie() {}
 
1037
func (s *loopSession) State() session.ClientSessionState {
 
1038
        if s.hasConn {
 
1039
                return session.Connected
 
1040
        } else {
 
1041
                return session.Disconnected
 
1042
        }
 
1043
}
 
1044
func (s *loopSession) HasConnectivity(hasConn bool) { s.hasConn = hasConn }
 
1045
func (s *loopSession) KeepConnection() error        { return nil }
 
1046
func (s *loopSession) StopKeepConnection()          {}
 
1047
 
1129
1048
func (cs *clientSuite) TestLoop(c *C) {
1130
1049
        cli := NewPushClient(cs.configPath, cs.leveldbPath)
1131
1050
        cli.connCh = make(chan bool)
1140
1059
 
1141
1060
        c.Assert(cli.initSessionAndPoller(), IsNil)
1142
1061
 
1143
 
        cli.session.BroadcastCh = make(chan *session.BroadcastNotification)
1144
 
        cli.session.ErrCh = make(chan error)
 
1062
        cli.broadcastCh = make(chan *session.BroadcastNotification)
1145
1063
 
1146
1064
        // we use tick() to make sure things have been through the
1147
1065
        // event loop at least once before looking at things;
1149
1067
        // at and the loop itself.
1150
1068
        tick := func() { cli.sessionConnectedCh <- 42 }
1151
1069
 
 
1070
        c.Assert(cli.session, NotNil)
 
1071
        cli.session.StopKeepConnection()
 
1072
        cli.session = &loopSession{}
 
1073
 
1152
1074
        go cli.Loop()
1153
1075
 
1154
1076
        // sessionConnectedCh to nothing in particular, but it'll help sync this test
1158
1080
 
1159
1081
        // loop() should have connected:
1160
1082
        //  * connCh to the connectivity checker
1161
 
        c.Check(cli.hasConnectivity, Equals, false)
 
1083
        c.Check(cli.session.State(), Equals, session.Disconnected)
1162
1084
        cli.connCh <- true
1163
1085
        tick()
1164
 
        c.Check(cli.hasConnectivity, Equals, true)
 
1086
        c.Check(cli.session.State(), Equals, session.Connected)
1165
1087
        cli.connCh <- false
1166
1088
        tick()
1167
 
        c.Check(cli.hasConnectivity, Equals, false)
 
1089
        c.Check(cli.session.State(), Equals, session.Disconnected)
1168
1090
 
1169
1091
        //  * session.BroadcastCh to the notifications handler
1170
1092
        c.Check(d.bcastCount, Equals, 0)
1171
 
        cli.session.BroadcastCh <- positiveBroadcastNotification
 
1093
        cli.broadcastCh <- positiveBroadcastNotification
1172
1094
        tick()
1173
1095
        c.Check(d.bcastCount, Equals, 1)
1174
 
 
1175
 
        //  * session.ErrCh to the error handler
1176
 
        cli.session.ErrCh <- nil
1177
 
        tick()
1178
 
        c.Check(cs.log.Captured(), Matches, "(?ms).*session exited.*")
1179
1096
}
1180
1097
 
1181
1098
/*****************************************************************