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
=== modified file 'client/session/session.go'
--- client/session/session.go 2014-01-31 17:40:56 +0000
+++ client/session/session.go 2014-01-31 19:56:23 +0000
@@ -22,6 +22,7 @@
22 "crypto/tls"22 "crypto/tls"
23 "crypto/x509"23 "crypto/x509"
24 "errors"24 "errors"
25 "fmt"
25 "launchpad.net/ubuntu-push/client/session/levelmap"26 "launchpad.net/ubuntu-push/client/session/levelmap"
26 "launchpad.net/ubuntu-push/logger"27 "launchpad.net/ubuntu-push/logger"
27 "launchpad.net/ubuntu-push/protocol"28 "launchpad.net/ubuntu-push/protocol"
@@ -138,7 +139,7 @@
138 sess.Levels.Set(bcast.ChanId, bcast.TopLevel)139 sess.Levels.Set(bcast.ChanId, bcast.TopLevel)
139 sess.MsgCh <- &Notification{}140 sess.MsgCh <- &Notification{}
140 } else {141 } else {
141 sess.Log.Debugf("what is this weird channel, %s?", bcast.ChanId)142 sess.Log.Debugf("what is this weird channel, %#v?", bcast.ChanId)
142 }143 }
143 return nil144 return nil
144}145}
@@ -165,3 +166,44 @@
165 }166 }
166 }167 }
167}168}
169
170// Call this when you've connected and are ready to start running.
171func (sess *ClientSession) start() error {
172 conn := sess.Connection
173 err := conn.SetDeadline(time.Now().Add(sess.ExchangeTimeout))
174 if err != nil {
175 return err
176 }
177 _, err = conn.Write(wireVersionBytes)
178 // The Writer docs: Write must return a non-nil error if it returns
179 // n < len(p). So, no need to check number of bytes written, hooray.
180 if err != nil {
181 return err
182 }
183 proto := sess.Protocolator(conn)
184 proto.SetDeadline(time.Now().Add(sess.ExchangeTimeout))
185 err = proto.WriteMessage(protocol.ConnectMsg{
186 Type: "connect",
187 DeviceId: sess.DeviceId,
188 Levels: sess.Levels.GetAll(),
189 })
190 if err != nil {
191 return err
192 }
193 var connAck protocol.ConnAckMsg
194 err = proto.ReadMessage(&connAck)
195 if err != nil {
196 return err
197 }
198 if connAck.Type != "connack" {
199 return fmt.Errorf("expecting CONNACK, got %#v", connAck.Type)
200 }
201 pingInterval, err := time.ParseDuration(connAck.Params.PingInterval)
202 if err != nil {
203 return err
204 }
205 sess.proto = proto
206 sess.pingInterval = pingInterval
207 sess.Log.Debugf("Connected %v.", conn.LocalAddr())
208 return nil
209}
168210
=== modified file 'client/session/session_test.go'
--- client/session/session_test.go 2014-01-31 17:40:56 +0000
+++ client/session/session_test.go 2014-01-31 19:56:23 +0000
@@ -20,6 +20,7 @@
20 "encoding/json"20 "encoding/json"
21 "errors"21 "errors"
22 "fmt"22 "fmt"
23 "io"
23 "io/ioutil"24 "io/ioutil"
24 . "launchpad.net/gocheck"25 . "launchpad.net/gocheck"
25 "launchpad.net/ubuntu-push/logger"26 "launchpad.net/ubuntu-push/logger"
@@ -73,11 +74,29 @@
73 }74 }
74}75}
7576
76func (tc *testConn) SetDeadline(t time.Time) error { panic("SetDeadline not implemented.") }77func (tc *testConn) SetDeadline(t time.Time) error {
78 tc.Deadlines = append(tc.Deadlines, t.Sub(time.Now()))
79 if tc.DeadlineCondition == nil || tc.DeadlineCondition.OK() {
80 return nil
81 } else {
82 return errors.New("deadliner on fire")
83 }
84}
85
77func (tc *testConn) SetReadDeadline(t time.Time) error { panic("SetReadDeadline not implemented.") }86func (tc *testConn) SetReadDeadline(t time.Time) error { panic("SetReadDeadline not implemented.") }
78func (tc *testConn) SetWriteDeadline(t time.Time) error { panic("SetWriteDeadline not implemented.") }87func (tc *testConn) SetWriteDeadline(t time.Time) error { panic("SetWriteDeadline not implemented.") }
79func (tc *testConn) Read(buf []byte) (n int, err error) { panic("Read not implemented.") }88func (tc *testConn) Read(buf []byte) (n int, err error) { panic("Read not implemented.") }
80func (tc *testConn) Write(buf []byte) (int, error) { panic("Write not implemented.") }89
90func (tc *testConn) Write(buf []byte) (int, error) {
91 store := make([]byte, len(buf))
92 copy(store, buf)
93 tc.Writes = append(tc.Writes, store)
94 if tc.WriteCondition == nil || tc.WriteCondition.OK() {
95 return len(store), nil
96 } else {
97 return -1, errors.New("writer on fire")
98 }
99}
81100
82// test protocol (from session_test)101// test protocol (from session_test)
83102
@@ -174,8 +193,7 @@
174 sess, err := NewSession("", nil, 0, "wah", debuglog)193 sess, err := NewSession("", nil, 0, "wah", debuglog)
175 c.Assert(err, IsNil)194 c.Assert(err, IsNil)
176 err = sess.Dial()195 err = sess.Dial()
177 c.Assert(err, NotNil)196 c.Check(err, ErrorMatches, ".*dial.*address.*")
178 c.Check(err.Error(), Matches, ".*dial.*address.*")
179}197}
180198
181func (cs *clientSessionSuite) TestDialConnects(c *C) {199func (cs *clientSessionSuite) TestDialConnects(c *C) {
@@ -196,9 +214,7 @@
196 srv.Close()214 srv.Close()
197 c.Assert(err, IsNil)215 c.Assert(err, IsNil)
198 err = sess.Dial()216 err = sess.Dial()
199 c.Check(sess.Connection, IsNil)217 c.Check(err, ErrorMatches, ".*connection refused")
200 c.Assert(err, NotNil)
201 c.Check(err.Error(), Matches, ".*connection refused")
202}218}
203219
204/****************************************************************220/****************************************************************
@@ -376,8 +392,7 @@
376func (s *runSuite) TestRunReadError(c *C) {392func (s *runSuite) TestRunReadError(c *C) {
377 s.upCh <- errors.New("Read")393 s.upCh <- errors.New("Read")
378 err := <-s.errCh394 err := <-s.errCh
379 c.Assert(err, NotNil)395 c.Check(err, ErrorMatches, "Read")
380 c.Check(err.Error(), Equals, "Read")
381}396}
382397
383func (s *runSuite) TestRunPing(c *C) {398func (s *runSuite) TestRunPing(c *C) {
@@ -416,3 +431,145 @@
416 s.upCh <- failure431 s.upCh <- failure
417 c.Check(<-s.errCh, Equals, failure)432 c.Check(<-s.errCh, Equals, failure)
418}433}
434
435/****************************************************************
436 start() tests
437****************************************************************/
438func (cs *clientSessionSuite) TestStartFailsIfSetDeadlineFails(c *C) {
439 sess, err := NewSession("", nil, 0, "wah", debuglog)
440 c.Assert(err, IsNil)
441 sess.Connection = &testConn{Name: "TestStartFailsIfSetDeadlineFails",
442 DeadlineCondition: condition.Work(false)} // setdeadline will fail
443 err = sess.start()
444 c.Check(err, ErrorMatches, ".*deadline.*")
445}
446
447func (cs *clientSessionSuite) TestStartFailsIfWriteFails(c *C) {
448 sess, err := NewSession("", nil, 0, "wah", debuglog)
449 c.Assert(err, IsNil)
450 sess.Connection = &testConn{Name: "TestStartFailsIfWriteFails",
451 WriteCondition: condition.Work(false)} // write will fail
452 err = sess.start()
453 c.Check(err, ErrorMatches, ".*write.*")
454}
455
456func (cs *clientSessionSuite) TestStartConnectMessageFails(c *C) {
457 sess, err := NewSession("", nil, 0, "wah", debuglog)
458 c.Assert(err, IsNil)
459 sess.Connection = &testConn{Name: "TestStartConnectMessageFails"}
460 errCh := make(chan error, 1)
461 upCh := make(chan interface{}, 5)
462 downCh := make(chan interface{}, 5)
463 proto := &testProtocol{up: upCh, down: downCh}
464 sess.Protocolator = func(_ net.Conn) protocol.Protocol { return proto }
465
466 go func() {
467 errCh <- sess.start()
468 }()
469
470 c.Check(takeNext(downCh), Equals, "deadline 0")
471 c.Check(takeNext(downCh), DeepEquals, protocol.ConnectMsg{
472 Type: "connect",
473 DeviceId: sess.DeviceId,
474 Levels: map[string]int64{},
475 })
476 upCh <- errors.New("Overflow error in /dev/null")
477 err = <-errCh
478 c.Check(err, ErrorMatches, "Overflow.*null")
479}
480
481func (cs *clientSessionSuite) TestStartConnackReadError(c *C) {
482 sess, err := NewSession("", nil, 0, "wah", debuglog)
483 c.Assert(err, IsNil)
484 sess.Connection = &testConn{Name: "TestStartConnackReadError"}
485 errCh := make(chan error, 1)
486 upCh := make(chan interface{}, 5)
487 downCh := make(chan interface{}, 5)
488 proto := &testProtocol{up: upCh, down: downCh}
489 sess.Protocolator = func(_ net.Conn) protocol.Protocol { return proto }
490
491 go func() {
492 errCh <- sess.start()
493 }()
494
495 c.Check(takeNext(downCh), Equals, "deadline 0")
496 _, ok := takeNext(downCh).(protocol.ConnectMsg)
497 c.Check(ok, Equals, true)
498 upCh <- nil // no error
499 upCh <- io.EOF
500 err = <-errCh
501 c.Check(err, ErrorMatches, ".*EOF.*")
502}
503
504func (cs *clientSessionSuite) TestStartBadConnack(c *C) {
505 sess, err := NewSession("", nil, 0, "wah", debuglog)
506 c.Assert(err, IsNil)
507 sess.Connection = &testConn{Name: "TestStartBadConnack"}
508 errCh := make(chan error, 1)
509 upCh := make(chan interface{}, 5)
510 downCh := make(chan interface{}, 5)
511 proto := &testProtocol{up: upCh, down: downCh}
512 sess.Protocolator = func(_ net.Conn) protocol.Protocol { return proto }
513
514 go func() {
515 errCh <- sess.start()
516 }()
517
518 c.Check(takeNext(downCh), Equals, "deadline 0")
519 _, ok := takeNext(downCh).(protocol.ConnectMsg)
520 c.Check(ok, Equals, true)
521 upCh <- nil // no error
522 upCh <- protocol.ConnAckMsg{Type: "connack"}
523 err = <-errCh
524 c.Check(err, ErrorMatches, ".*invalid.*")
525}
526
527func (cs *clientSessionSuite) TestStartNotConnack(c *C) {
528 sess, err := NewSession("", nil, 0, "wah", debuglog)
529 c.Assert(err, IsNil)
530 sess.Connection = &testConn{Name: "TestStartBadConnack"}
531 errCh := make(chan error, 1)
532 upCh := make(chan interface{}, 5)
533 downCh := make(chan interface{}, 5)
534 proto := &testProtocol{up: upCh, down: downCh}
535 sess.Protocolator = func(_ net.Conn) protocol.Protocol { return proto }
536
537 go func() {
538 errCh <- sess.start()
539 }()
540
541 c.Check(takeNext(downCh), Equals, "deadline 0")
542 _, ok := takeNext(downCh).(protocol.ConnectMsg)
543 c.Check(ok, Equals, true)
544 upCh <- nil // no error
545 upCh <- protocol.ConnAckMsg{Type: "connnak"}
546 err = <-errCh
547 c.Check(err, ErrorMatches, ".*CONNACK.*")
548}
549
550func (cs *clientSessionSuite) TestStartWorks(c *C) {
551 sess, err := NewSession("", nil, 0, "wah", debuglog)
552 c.Assert(err, IsNil)
553 sess.Connection = &testConn{Name: "TestStartWorks"}
554 errCh := make(chan error, 1)
555 upCh := make(chan interface{}, 5)
556 downCh := make(chan interface{}, 5)
557 proto := &testProtocol{up: upCh, down: downCh}
558 sess.Protocolator = func(_ net.Conn) protocol.Protocol { return proto }
559
560 go func() {
561 errCh <- sess.start()
562 }()
563
564 c.Check(takeNext(downCh), Equals, "deadline 0")
565 _, ok := takeNext(downCh).(protocol.ConnectMsg)
566 c.Check(ok, Equals, true)
567 upCh <- nil // no error
568 upCh <- protocol.ConnAckMsg{
569 Type: "connack",
570 Params: protocol.ConnAckParams{(10 * time.Millisecond).String()},
571 }
572 // start is now done.
573 err = <-errCh
574 c.Assert(err, IsNil)
575}

Subscribers

People subscribed via source and target branches