Merge lp:~chipaca/ubuntu-push/elements-of-client-session-toponomy into lp:ubuntu-push

Proposed by John Lenton
Status: Merged
Approved by: John Lenton
Approved revision: 52
Merged at revision: 40
Proposed branch: lp:~chipaca/ubuntu-push/elements-of-client-session-toponomy
Merge into: lp:ubuntu-push
Prerequisite: lp:~chipaca/ubuntu-push/introduction-to-quantum-client-sessions
Diff against target: 286 lines (+209/-10)
2 files modified
client/session/session.go (+43/-1)
client/session/session_test.go (+166/-9)
To merge this branch: bzr merge lp:~chipaca/ubuntu-push/elements-of-client-session-toponomy
Reviewer Review Type Date Requested Status
Samuele Pedroni Approve
Review via email: mp+204129@code.launchpad.net

Commit message

Starting to take shape.

Description of the change

Client session, volume 5: elements of client session toponomy.

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

Merged introduction-to-quantum-client-sessions into elements-of-client-session-toponomy.

42. By John Lenton

Merged introduction-to-quantum-client-sessions into elements-of-client-session-toponomy.

43. By John Lenton

Merged introduction-to-quantum-client-sessions into elements-of-client-session-toponomy.

44. By John Lenton

Merged introduction-to-quantum-client-sessions into elements-of-client-session-toponomy.

45. By John Lenton

Merged introduction-to-quantum-client-sessions into elements-of-client-session-toponomy.

46. By John Lenton

Merged introduction-to-quantum-client-sessions into elements-of-client-session-toponomy.

47. By John Lenton

Merged introduction-to-quantum-client-sessions into elements-of-client-session-toponomy.

48. By John Lenton

brought back testConn.SetDeadline; added a proto.SetDeadline before sending the connect msg; fixed the tests appropriately; added a check on the type of the Connn^Cssages in TestStart*.

49. By John Lenton

Merged introduction-to-quantum-client-sessions into elements-of-client-session-toponomy.

50. By John Lenton

Merged introduction-to-quantum-client-sessions into elements-of-client-session-toponomy.

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

42 + err = proto.ReadMessage(&connAck)

around here there should be a sanity check that connAck.Type is "connack"

114 + c.Check(err.Error(), Matches, ".*deadline.*")

gocheck has c.Check(err, ErrorMatches, ...)

I just noticed that upCh downCh are still from the point of view of the server, I suppose we need to live with that if we want to share later unless we can invent neutral names

51. By John Lenton

sanity check to connack; used ErrorMatches in tests

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

there are still some:

client/session/session_test.go:396: c.Check(err.Error(), Equals, "Read")
client/session/session_test.go:446: c.Check(err.Error(), Matches, ".*deadline.*")
client/session/session_test.go:456: c.Check(err.Error(), Matches, ".*write.*")
client/session/session_test.go:482: c.Check(err.Error(), Matches, "Overflow.*null")
client/session/session_test.go:506: c.Check(err.Error(), Matches, ".*EOF.*")

review: Approve
52. By John Lenton

more ErrorMatches

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 17:40:56 +0000
3+++ client/session/session.go 2014-01-31 19:56:23 +0000
4@@ -22,6 +22,7 @@
5 "crypto/tls"
6 "crypto/x509"
7 "errors"
8+ "fmt"
9 "launchpad.net/ubuntu-push/client/session/levelmap"
10 "launchpad.net/ubuntu-push/logger"
11 "launchpad.net/ubuntu-push/protocol"
12@@ -138,7 +139,7 @@
13 sess.Levels.Set(bcast.ChanId, bcast.TopLevel)
14 sess.MsgCh <- &Notification{}
15 } else {
16- sess.Log.Debugf("what is this weird channel, %s?", bcast.ChanId)
17+ sess.Log.Debugf("what is this weird channel, %#v?", bcast.ChanId)
18 }
19 return nil
20 }
21@@ -165,3 +166,44 @@
22 }
23 }
24 }
25+
26+// Call this when you've connected and are ready to start running.
27+func (sess *ClientSession) start() error {
28+ conn := sess.Connection
29+ err := conn.SetDeadline(time.Now().Add(sess.ExchangeTimeout))
30+ if err != nil {
31+ return err
32+ }
33+ _, err = conn.Write(wireVersionBytes)
34+ // The Writer docs: Write must return a non-nil error if it returns
35+ // n < len(p). So, no need to check number of bytes written, hooray.
36+ if err != nil {
37+ return err
38+ }
39+ proto := sess.Protocolator(conn)
40+ proto.SetDeadline(time.Now().Add(sess.ExchangeTimeout))
41+ err = proto.WriteMessage(protocol.ConnectMsg{
42+ Type: "connect",
43+ DeviceId: sess.DeviceId,
44+ Levels: sess.Levels.GetAll(),
45+ })
46+ if err != nil {
47+ return err
48+ }
49+ var connAck protocol.ConnAckMsg
50+ err = proto.ReadMessage(&connAck)
51+ if err != nil {
52+ return err
53+ }
54+ if connAck.Type != "connack" {
55+ return fmt.Errorf("expecting CONNACK, got %#v", connAck.Type)
56+ }
57+ pingInterval, err := time.ParseDuration(connAck.Params.PingInterval)
58+ if err != nil {
59+ return err
60+ }
61+ sess.proto = proto
62+ sess.pingInterval = pingInterval
63+ sess.Log.Debugf("Connected %v.", conn.LocalAddr())
64+ return nil
65+}
66
67=== modified file 'client/session/session_test.go'
68--- client/session/session_test.go 2014-01-31 17:40:56 +0000
69+++ client/session/session_test.go 2014-01-31 19:56:23 +0000
70@@ -20,6 +20,7 @@
71 "encoding/json"
72 "errors"
73 "fmt"
74+ "io"
75 "io/ioutil"
76 . "launchpad.net/gocheck"
77 "launchpad.net/ubuntu-push/logger"
78@@ -73,11 +74,29 @@
79 }
80 }
81
82-func (tc *testConn) SetDeadline(t time.Time) error { panic("SetDeadline not implemented.") }
83+func (tc *testConn) SetDeadline(t time.Time) error {
84+ tc.Deadlines = append(tc.Deadlines, t.Sub(time.Now()))
85+ if tc.DeadlineCondition == nil || tc.DeadlineCondition.OK() {
86+ return nil
87+ } else {
88+ return errors.New("deadliner on fire")
89+ }
90+}
91+
92 func (tc *testConn) SetReadDeadline(t time.Time) error { panic("SetReadDeadline not implemented.") }
93 func (tc *testConn) SetWriteDeadline(t time.Time) error { panic("SetWriteDeadline not implemented.") }
94 func (tc *testConn) Read(buf []byte) (n int, err error) { panic("Read not implemented.") }
95-func (tc *testConn) Write(buf []byte) (int, error) { panic("Write not implemented.") }
96+
97+func (tc *testConn) Write(buf []byte) (int, error) {
98+ store := make([]byte, len(buf))
99+ copy(store, buf)
100+ tc.Writes = append(tc.Writes, store)
101+ if tc.WriteCondition == nil || tc.WriteCondition.OK() {
102+ return len(store), nil
103+ } else {
104+ return -1, errors.New("writer on fire")
105+ }
106+}
107
108 // test protocol (from session_test)
109
110@@ -174,8 +193,7 @@
111 sess, err := NewSession("", nil, 0, "wah", debuglog)
112 c.Assert(err, IsNil)
113 err = sess.Dial()
114- c.Assert(err, NotNil)
115- c.Check(err.Error(), Matches, ".*dial.*address.*")
116+ c.Check(err, ErrorMatches, ".*dial.*address.*")
117 }
118
119 func (cs *clientSessionSuite) TestDialConnects(c *C) {
120@@ -196,9 +214,7 @@
121 srv.Close()
122 c.Assert(err, IsNil)
123 err = sess.Dial()
124- c.Check(sess.Connection, IsNil)
125- c.Assert(err, NotNil)
126- c.Check(err.Error(), Matches, ".*connection refused")
127+ c.Check(err, ErrorMatches, ".*connection refused")
128 }
129
130 /****************************************************************
131@@ -376,8 +392,7 @@
132 func (s *runSuite) TestRunReadError(c *C) {
133 s.upCh <- errors.New("Read")
134 err := <-s.errCh
135- c.Assert(err, NotNil)
136- c.Check(err.Error(), Equals, "Read")
137+ c.Check(err, ErrorMatches, "Read")
138 }
139
140 func (s *runSuite) TestRunPing(c *C) {
141@@ -416,3 +431,145 @@
142 s.upCh <- failure
143 c.Check(<-s.errCh, Equals, failure)
144 }
145+
146+/****************************************************************
147+ start() tests
148+****************************************************************/
149+func (cs *clientSessionSuite) TestStartFailsIfSetDeadlineFails(c *C) {
150+ sess, err := NewSession("", nil, 0, "wah", debuglog)
151+ c.Assert(err, IsNil)
152+ sess.Connection = &testConn{Name: "TestStartFailsIfSetDeadlineFails",
153+ DeadlineCondition: condition.Work(false)} // setdeadline will fail
154+ err = sess.start()
155+ c.Check(err, ErrorMatches, ".*deadline.*")
156+}
157+
158+func (cs *clientSessionSuite) TestStartFailsIfWriteFails(c *C) {
159+ sess, err := NewSession("", nil, 0, "wah", debuglog)
160+ c.Assert(err, IsNil)
161+ sess.Connection = &testConn{Name: "TestStartFailsIfWriteFails",
162+ WriteCondition: condition.Work(false)} // write will fail
163+ err = sess.start()
164+ c.Check(err, ErrorMatches, ".*write.*")
165+}
166+
167+func (cs *clientSessionSuite) TestStartConnectMessageFails(c *C) {
168+ sess, err := NewSession("", nil, 0, "wah", debuglog)
169+ c.Assert(err, IsNil)
170+ sess.Connection = &testConn{Name: "TestStartConnectMessageFails"}
171+ errCh := make(chan error, 1)
172+ upCh := make(chan interface{}, 5)
173+ downCh := make(chan interface{}, 5)
174+ proto := &testProtocol{up: upCh, down: downCh}
175+ sess.Protocolator = func(_ net.Conn) protocol.Protocol { return proto }
176+
177+ go func() {
178+ errCh <- sess.start()
179+ }()
180+
181+ c.Check(takeNext(downCh), Equals, "deadline 0")
182+ c.Check(takeNext(downCh), DeepEquals, protocol.ConnectMsg{
183+ Type: "connect",
184+ DeviceId: sess.DeviceId,
185+ Levels: map[string]int64{},
186+ })
187+ upCh <- errors.New("Overflow error in /dev/null")
188+ err = <-errCh
189+ c.Check(err, ErrorMatches, "Overflow.*null")
190+}
191+
192+func (cs *clientSessionSuite) TestStartConnackReadError(c *C) {
193+ sess, err := NewSession("", nil, 0, "wah", debuglog)
194+ c.Assert(err, IsNil)
195+ sess.Connection = &testConn{Name: "TestStartConnackReadError"}
196+ errCh := make(chan error, 1)
197+ upCh := make(chan interface{}, 5)
198+ downCh := make(chan interface{}, 5)
199+ proto := &testProtocol{up: upCh, down: downCh}
200+ sess.Protocolator = func(_ net.Conn) protocol.Protocol { return proto }
201+
202+ go func() {
203+ errCh <- sess.start()
204+ }()
205+
206+ c.Check(takeNext(downCh), Equals, "deadline 0")
207+ _, ok := takeNext(downCh).(protocol.ConnectMsg)
208+ c.Check(ok, Equals, true)
209+ upCh <- nil // no error
210+ upCh <- io.EOF
211+ err = <-errCh
212+ c.Check(err, ErrorMatches, ".*EOF.*")
213+}
214+
215+func (cs *clientSessionSuite) TestStartBadConnack(c *C) {
216+ sess, err := NewSession("", nil, 0, "wah", debuglog)
217+ c.Assert(err, IsNil)
218+ sess.Connection = &testConn{Name: "TestStartBadConnack"}
219+ errCh := make(chan error, 1)
220+ upCh := make(chan interface{}, 5)
221+ downCh := make(chan interface{}, 5)
222+ proto := &testProtocol{up: upCh, down: downCh}
223+ sess.Protocolator = func(_ net.Conn) protocol.Protocol { return proto }
224+
225+ go func() {
226+ errCh <- sess.start()
227+ }()
228+
229+ c.Check(takeNext(downCh), Equals, "deadline 0")
230+ _, ok := takeNext(downCh).(protocol.ConnectMsg)
231+ c.Check(ok, Equals, true)
232+ upCh <- nil // no error
233+ upCh <- protocol.ConnAckMsg{Type: "connack"}
234+ err = <-errCh
235+ c.Check(err, ErrorMatches, ".*invalid.*")
236+}
237+
238+func (cs *clientSessionSuite) TestStartNotConnack(c *C) {
239+ sess, err := NewSession("", nil, 0, "wah", debuglog)
240+ c.Assert(err, IsNil)
241+ sess.Connection = &testConn{Name: "TestStartBadConnack"}
242+ errCh := make(chan error, 1)
243+ upCh := make(chan interface{}, 5)
244+ downCh := make(chan interface{}, 5)
245+ proto := &testProtocol{up: upCh, down: downCh}
246+ sess.Protocolator = func(_ net.Conn) protocol.Protocol { return proto }
247+
248+ go func() {
249+ errCh <- sess.start()
250+ }()
251+
252+ c.Check(takeNext(downCh), Equals, "deadline 0")
253+ _, ok := takeNext(downCh).(protocol.ConnectMsg)
254+ c.Check(ok, Equals, true)
255+ upCh <- nil // no error
256+ upCh <- protocol.ConnAckMsg{Type: "connnak"}
257+ err = <-errCh
258+ c.Check(err, ErrorMatches, ".*CONNACK.*")
259+}
260+
261+func (cs *clientSessionSuite) TestStartWorks(c *C) {
262+ sess, err := NewSession("", nil, 0, "wah", debuglog)
263+ c.Assert(err, IsNil)
264+ sess.Connection = &testConn{Name: "TestStartWorks"}
265+ errCh := make(chan error, 1)
266+ upCh := make(chan interface{}, 5)
267+ downCh := make(chan interface{}, 5)
268+ proto := &testProtocol{up: upCh, down: downCh}
269+ sess.Protocolator = func(_ net.Conn) protocol.Protocol { return proto }
270+
271+ go func() {
272+ errCh <- sess.start()
273+ }()
274+
275+ c.Check(takeNext(downCh), Equals, "deadline 0")
276+ _, ok := takeNext(downCh).(protocol.ConnectMsg)
277+ c.Check(ok, Equals, true)
278+ upCh <- nil // no error
279+ upCh <- protocol.ConnAckMsg{
280+ Type: "connack",
281+ Params: protocol.ConnAckParams{(10 * time.Millisecond).String()},
282+ }
283+ // start is now done.
284+ err = <-errCh
285+ c.Assert(err, IsNil)
286+}

Subscribers

People subscribed via source and target branches