package frame import ( "io" "strings" "testing/iotest" . "gopkg.in/check.v1" ) type ReaderSuite struct{} var _ = Suite(&ReaderSuite{}) func (s *ReaderSuite) TestConnect(c *C) { reader := NewReader(strings.NewReader("CONNECT\nlogin:xxx\npasscode:yyy\n\n\x00")) frame, err := reader.Read() c.Assert(err, IsNil) c.Assert(frame, NotNil) c.Assert(len(frame.Body), Equals, 0) // ensure we are at the end of input frame, err = reader.Read() c.Assert(frame, IsNil) c.Assert(err, Equals, io.EOF) } func (s *ReaderSuite) TestMultipleReads(c *C) { text := "SEND\ndestination:xxx\n\nPayload\x00\n" + "SEND\ndestination:yyy\ncontent-length:12\n" + "dodgy\\c\\n\\cheader:dodgy\\c\\n\\r\\nvalue\\ \\\n\n" + "123456789AB\x00\x00" ioreaders := []io.Reader{ strings.NewReader(text), iotest.DataErrReader(strings.NewReader(text)), iotest.HalfReader(strings.NewReader(text)), iotest.OneByteReader(strings.NewReader(text)), } for _, ioreader := range ioreaders { // uncomment the following line to view the bytes being read //ioreader = iotest.NewReadLogger("RX", ioreader) reader := NewReader(ioreader) frame, err := reader.Read() c.Assert(err, IsNil) c.Assert(frame, NotNil) c.Assert(frame.Command, Equals, "SEND") c.Assert(frame.Header.Len(), Equals, 1) v := frame.Header.Get("destination") c.Assert(v, Equals, "xxx") c.Assert(string(frame.Body), Equals, "Payload") // now read a heart-beat from the input frame, err = reader.Read() c.Assert(err, IsNil) c.Assert(frame, IsNil) // this frame has content-length frame, err = reader.Read() c.Assert(err, IsNil) c.Assert(frame, NotNil) c.Assert(frame.Command, Equals, "SEND") c.Assert(frame.Header.Len(), Equals, 3) v = frame.Header.Get("destination") c.Assert(v, Equals, "yyy") n, ok, err := frame.Header.ContentLength() c.Assert(n, Equals, 12) c.Assert(ok, Equals, true) c.Assert(err, IsNil) k, v := frame.Header.GetAt(2) c.Assert(k, Equals, "dodgy:\n:header") c.Assert(v, Equals, "dodgy:\n\r\nvalue\\ \\") c.Assert(string(frame.Body), Equals, "123456789AB\x00") // ensure we are at the end of input frame, err = reader.Read() c.Assert(frame, IsNil) c.Assert(err, Equals, io.EOF) } } func (s *ReaderSuite) TestSendWithContentLength(c *C) { reader := NewReader(strings.NewReader("SEND\ndestination:xxx\ncontent-length:5\n\n\x00\x01\x02\x03\x04\x00")) frame, err := reader.Read() c.Assert(err, IsNil) c.Assert(frame, NotNil) c.Assert(frame.Command, Equals, "SEND") c.Assert(frame.Header.Len(), Equals, 2) v := frame.Header.Get("destination") c.Assert(v, Equals, "xxx") c.Assert(frame.Body, DeepEquals, []byte{0x00, 0x01, 0x02, 0x03, 0x04}) // ensure we are at the end of input frame, err = reader.Read() c.Assert(frame, IsNil) c.Assert(err, Equals, io.EOF) } func (s *ReaderSuite) TestInvalidCommand(c *C) { reader := NewReader(strings.NewReader("sEND\ndestination:xxx\ncontent-length:5\n\n\x00\x01\x02\x03\x04\x00")) frame, err := reader.Read() c.Check(frame, IsNil) c.Assert(err, NotNil) c.Check(err.Error(), Equals, "invalid command") } func (s *ReaderSuite) TestMissingNull(c *C) { reader := NewReader(strings.NewReader("SEND\ndeestination:xxx\ncontent-length:5\n\n\x00\x01\x02\x03\x04\n")) f, err := reader.Read() c.Check(f, IsNil) c.Assert(err, NotNil) c.Check(err.Error(), Equals, "invalid frame format") } func (s *ReaderSuite) TestSubscribeWithoutId(c *C) { c.Skip("TODO: implement validate") reader := NewReader(strings.NewReader("SUBSCRIBE\ndestination:xxx\nIId:7\n\n\x00")) frame, err := reader.Read() c.Check(frame, IsNil) c.Assert(err, NotNil) c.Check(err.Error(), Equals, "missing header: id") } func (s *ReaderSuite) TestUnsubscribeWithoutId(c *C) { c.Skip("TODO: implement validate") reader := NewReader(strings.NewReader("UNSUBSCRIBE\nIId:7\n\n\x00")) frame, err := reader.Read() c.Check(frame, IsNil) c.Assert(err, NotNil) c.Check(err.Error(), Equals, "missing header: id") }