Merge lp:~chipaca/ubuntu-push/advanced-client-session into lp:ubuntu-push

Proposed by John Lenton
Status: Merged
Approved by: John Lenton
Approved revision: 40
Merged at revision: 36
Proposed branch: lp:~chipaca/ubuntu-push/advanced-client-session
Merge into: lp:ubuntu-push
Prerequisite: lp:~chipaca/ubuntu-push/client-session
Diff against target: 138 lines (+101/-0)
2 files modified
client/session/session.go (+8/-0)
client/session/session_test.go (+93/-0)
To merge this branch: bzr merge lp:~chipaca/ubuntu-push/advanced-client-session
Reviewer Review Type Date Requested Status
Samuele Pedroni Approve
Review via email: mp+204112@code.launchpad.net

Commit message

The handling of the ping.

Description of the change

Client session, volume 2: Advanced client session.

To post a comment you must log in.
36. By John Lenton

Merged client-session into advanced-client-session.

37. By John Lenton

Merged client-session into advanced-client-session.

Revision history for this message
Samuele Pedroni (pedronis) wrote :

protocol itself has a SetDeadline that should be used after you got a protocol and not a plain connection

review: Needs Fixing
38. By John Lenton

seriously bad protocol breakage spotted by pedronis; fixed

39. By John Lenton

Merged watchticker-goes-to-the-races into advanced-client-session.

40. By John Lenton

Assert instead of Check when checking the length of a chan you are about to read from

Revision history for this message
Samuele Pedroni (pedronis) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'client/session/session.go'
2--- client/session/session.go 2014-01-31 12:44:29 +0000
3+++ client/session/session.go 2014-01-31 14:15:56 +0000
4@@ -107,3 +107,11 @@
5 }
6 return nil
7 }
8+
9+// handle "ping" messages
10+func (sess *ClientSession) handlePing() error {
11+ sess.proto.SetDeadline(time.Now().Add(sess.ExchangeTimeout))
12+ err := sess.proto.WriteMessage(protocol.PingPongMsg{Type: "pong"})
13+ sess.Log.Debugf("Ping.")
14+ return err
15+}
16
17=== modified file 'client/session/session_test.go'
18--- client/session/session_test.go 2014-01-31 12:44:29 +0000
19+++ client/session/session_test.go 2014-01-31 14:15:56 +0000
20@@ -17,14 +17,18 @@
21 package session
22
23 import (
24+ "encoding/json"
25 "errors"
26+ "fmt"
27 "io/ioutil"
28 . "launchpad.net/gocheck"
29 "launchpad.net/ubuntu-push/logger"
30+ "launchpad.net/ubuntu-push/protocol"
31 helpers "launchpad.net/ubuntu-push/testing"
32 "launchpad.net/ubuntu-push/testing/condition"
33 "net"
34 "os"
35+ "reflect"
36 "testing"
37 "time"
38 )
39@@ -75,6 +79,52 @@
40 func (tc *testConn) Read(buf []byte) (n int, err error) { panic("Read not implemented.") }
41 func (tc *testConn) Write(buf []byte) (int, error) { panic("Write not implemented.") }
42
43+// test protocol (from session_test)
44+
45+type testProtocol struct {
46+ up chan interface{}
47+ down chan interface{}
48+}
49+
50+// takeNext takes a value from given channel with a 5s timeout
51+func takeNext(ch <-chan interface{}) interface{} {
52+ select {
53+ case <-time.After(5 * time.Second):
54+ panic("test protocol exchange stuck: too long waiting")
55+ case v := <-ch:
56+ return v
57+ }
58+ return nil
59+}
60+
61+func (c *testProtocol) SetDeadline(t time.Time) {
62+ deadAfter := t.Sub(time.Now())
63+ deadAfter = (deadAfter + time.Millisecond/2) / time.Millisecond * time.Millisecond
64+ c.down <- fmt.Sprintf("deadline %v", deadAfter)
65+}
66+
67+func (c *testProtocol) ReadMessage(dest interface{}) error {
68+ panic("ReadMessage not implemented.")
69+}
70+
71+func (c *testProtocol) WriteMessage(src interface{}) error {
72+ // make sure JSON.Marshal works with src
73+ _, err := json.Marshal(src)
74+ if err != nil {
75+ return err
76+ }
77+ val := reflect.ValueOf(src)
78+ if val.Kind() == reflect.Ptr {
79+ src = val.Elem().Interface()
80+ }
81+ c.down <- src
82+ switch v := takeNext(c.up).(type) {
83+ case error:
84+ return v
85+ }
86+ return nil
87+}
88+
89 /****************************************************************
90 NewSession() tests
91 ****************************************************************/
92@@ -197,3 +247,46 @@
93 sess.Connection = &testConn{}
94 c.Check(sess.checkRunnable(), IsNil)
95 }
96+
97+/****************************************************************
98+ handlePing() tests
99+****************************************************************/
100+
101+type msgSuite struct {
102+ sess *ClientSession
103+ upCh chan interface{}
104+ downCh chan interface{}
105+ errCh chan error
106+}
107+
108+var _ = Suite(&msgSuite{})
109+
110+func (s *msgSuite) SetUpTest(c *C) {
111+ var err error
112+ s.sess, err = NewSession("", nil, 0, "wah", debuglog)
113+ c.Assert(err, IsNil)
114+ s.sess.Connection = &testConn{Name: "TestRun* (small r)"}
115+ s.errCh = make(chan error, 1)
116+ s.upCh = make(chan interface{}, 5)
117+ s.downCh = make(chan interface{}, 5)
118+ s.sess.proto = &testProtocol{up: s.upCh, down: s.downCh}
119+}
120+
121+func (s *msgSuite) TestHandlePingWorks(c *C) {
122+ s.upCh <- nil // no error
123+ s.sess.ExchangeTimeout = time.Millisecond
124+ c.Check(s.sess.handlePing(), IsNil)
125+ c.Assert(len(s.downCh), Equals, 2)
126+ c.Check(<-s.downCh, Equals, "deadline 1ms")
127+ c.Check(<-s.downCh, Equals, protocol.PingPongMsg{Type: "pong"})
128+}
129+
130+func (s *msgSuite) TestHandlePingHandlesPongWriteError(c *C) {
131+ failure := errors.New("Pong")
132+ s.upCh <- failure
133+
134+ c.Check(s.sess.handlePing(), Equals, failure)
135+ c.Assert(len(s.downCh), Equals, 2)
136+ c.Check(<-s.downCh, Equals, "deadline 0")
137+ c.Check(<-s.downCh, Equals, protocol.PingPongMsg{Type: "pong"})
138+}

Subscribers

People subscribed via source and target branches