package cnp import ( "bytes" "io" "strconv" "strings" "testing" ) var ( messageTests = []messageTest{ { "qweasd", "text/plain", nil, nil, "cnp/0.4 test1 length=6 type=text/plain\nqweasd", &Message{ Header: Header{ VersionMajor: 0, VersionMinor: 4, Intent: "test1", Parameters: Parameters{ "type": "text/plain", "length": "6", }, }, Body: strings.NewReader("qweasd"), }, }, { "qweasd", "text", nil, ErrorInvalid{}, "cnp/0.4 test2 length=w type=text/plain\nqweasd", &Message{ Header: Header{ VersionMajor: 0, VersionMinor: 4, Intent: "test2", Parameters: Parameters{ "type": "text/plain", "length": "w", }, }, Body: strings.NewReader("qweasd"), }, }, { "", "text/plain", ErrorSyntax{}, nil, "cnp/0.4 test3 type=text/plain", nil, }, { "", "text/plain", nil, nil, "cnp/0.4 test4 type=text/plain\n", &Message{ Header: Header{ VersionMajor: 0, VersionMinor: 4, Intent: "test4", Parameters: Parameters{ "type": "text/plain", }, }, Body: nil, }, }, } ) type messageTest struct { b, t string p, v error s string m *Message } func (tst *messageTest) Reset() { if tst.m != nil && tst.b != "" { tst.m.Body = strings.NewReader(tst.b) } } func TestParse(t *testing.T) { for _, tst := range messageTests { tst.Reset() msg, err := ParseMessage(strings.NewReader(tst.s)) if tst.p != nil || err != nil { if !errorEqual(tst.p, err) { t.Errorf("ParseMessage(%q): expected error %+v, got %+v (%v)", tst.s, tst.p, err, err) continue } } else if !msgEqual(msg, tst.m) { t.Errorf("\nexpected: %+v\ngot: %+v", tst.m, msg) } else if l := msg.Length(); tst.v == nil && (l != int64(len(tst.b)) && !(l < 0 == (len(tst.b) == 0))) { t.Errorf("%+v: expected length %d, got %d", tst.m, len(tst.b), l) } else if err = msg.Validate(); !errorEqual(err, tst.v) { t.Errorf("%+v: expected validation error %+v, got %+v (%s)", msg, tst.v, err, err) } } } func TestNew(t *testing.T) { for i, tst := range messageTests { if tst.v != nil || tst.p != nil { continue // skip invalid messages } tst.Reset() var r io.Reader if tst.b != "" { r = strings.NewReader(tst.b) } msg := NewMessage("test"+strconv.Itoa(i+1), r) msg.SetParam("type", tst.t) if !msgEqual(msg, tst.m) { t.Errorf("\nexpected: %+v\ngot: %+v", tst.m, msg) } } } func TestWrite(t *testing.T) { for _, tst := range messageTests { if tst.p != nil { continue // skip invalid messages } tst.Reset() var buf bytes.Buffer err := tst.m.Write(&buf) if err != nil { t.Errorf("%+v: error writing message body: %s", tst.m, err) } if buf.String() != tst.s { t.Errorf("%+v:\nexpected: %q\ngot: %q", tst.m, tst.s, buf.String()) } } } func TestComputeLength(t *testing.T) { s := "qweasd" r := &testStringReader{"qweasd"} msg := NewMessage("ok", r) if _, ok := msg.Header.Parameters["length"]; msg.Length() != 0 || msg.Param("length") != "" || ok { t.Fatalf("%+v: expected no length parameter", msg) } if err := msg.ComputeLength(); err != nil { t.Fatalf("%+v.ComputeLength(): error: %s", msg, err) } if l := msg.Length(); l != int64(len(s)) { t.Fatalf("%+v: invalid length %d, expected %d\n", msg, l, len(s)) } if _, ok := msg.Body.(*testStringReader); r.s != "" || ok || r == msg.Body { t.Fatalf("%+v: did not buffer body correctly", msg) } if !bodyEqual(msg.Body, strings.NewReader(s)) { t.Fatalf("%+v: incorrect buffered body", msg) } } func TestParseTooLarge(t *testing.T) { s := "cnp/0.4 ok text=" str := s + strings.Repeat(".", MaxHeaderLength-len(s)) + "\n" _, err := ParseMessage(strings.NewReader(str)) if _, ok := err.(ErrorTooLarge); !ok { t.Errorf("\nexpected: ErrorTooLarge\ngot: %+v", err) } } type noopCloser struct { r io.Reader closed bool } func (n *noopCloser) Close() error { n.closed = true return nil } func (n *noopCloser) Read(b []byte) (int, error) { return n.r.Read(b) } func TestClose(t *testing.T) { var r io.Reader = strings.NewReader("cnp/0.4 ok\nqweasd") if msg, err := ParseMessage(r); err != nil { t.Errorf("ParseMessage error: %v", err) } else if err = msg.Close(); err != nil { t.Errorf("Error closing message: %v", err) } r = &noopCloser{r: strings.NewReader("cnp/0.4 ok\nqweasd")} if msg, err := ParseMessage(r); err != nil { t.Errorf("ParseMessage error: %v", err) } else if err = msg.Close(); err != nil { t.Errorf("Error closing message: %v", err) } else if !r.(*noopCloser).closed { t.Errorf("Reader was not closed") } r = &noopCloser{r: strings.NewReader("qweasd")} msg := NewMessage("ok", r) if err := msg.Close(); err != nil { t.Errorf("Error closing message: %v", err) } else if !r.(*noopCloser).closed { t.Errorf("Reader was not closed") } }