From da77deba78c8a7447b4a38324d2422a5df293b26 Mon Sep 17 00:00:00 2001 From: clsr Date: Fri, 18 Aug 2017 13:46:10 +0200 Subject: Initial commit --- header_test.go | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 header_test.go (limited to 'header_test.go') diff --git a/header_test.go b/header_test.go new file mode 100644 index 0000000..b035078 --- /dev/null +++ b/header_test.go @@ -0,0 +1,200 @@ +package cnp + +import "testing" + +var escapes = map[string]string{ + "": ``, + "ContNet": `ContNet`, + " ": `\_`, + "=": `\-`, + "\n": `\n`, + "\x00": `\0`, + "\\": `\\`, + "a\nb c=d\x00e\\f": `a\nb\_c\-d\0e\\f`, + "\n\n\n": `\n\n\n`, + "===": `\-\-\-`, + " ": `\_\_\_`, + "\x00\x00\x00": `\0\0\0`, + "\\\\\\": `\\\\\\`, + " =\n\x00\\": `\_\-\n\0\\`, + "\b5Ὂg̀9! ℃ᾭG": "\b5Ὂg̀9!\\_℃ᾭG", + "\xff\x00\xee\xaa\xee": "\xff\\0\xee\xaa\xee", + "\x00\x10\x20\x30\x40": "\\0\x10\\_\x30\x40", + "\x10\x50\x90\xe0": "\x10\x50\x90\xe0", + "Hello, 世界": `Hello,\_世界`, + "\xed\x9f\xbf": "\xed\x9f\xbf", + "\xee\x80\x80": "\xee\x80\x80", + "\xef\xbf\xbd": "\xef\xbf\xbd", + "\x80\x80\x80\x80": "\x80\x80\x80\x80", +} + +func TestEscape(t *testing.T) { + for k, v := range escapes { + e := string(Escape(k)) + if e != v { + t.Errorf("Escape(%q) -> %q, expected %q", k, e, v) + } + } + for i := 0; i <= 255; i++ { + switch i { + case '\x00', ' ', '=', '\n', '\\': + continue + default: + s := string([]byte{byte(i)}) + b := Escape(s) + if s != string(b) { + t.Errorf("Escape(%q) -> %q, expected %q", s, b, s) + } + } + } +} + +func TestUnEscape(t *testing.T) { + for k, v := range escapes { + u, err := Unescape([]byte(v)) + if err != nil { + t.Errorf("Unescape(%q): error: %s", v, err) + } else if u != k { + t.Errorf("Unescape(%q) -> %q, expected %q", v, u, k) + } + } + for i := 0; i <= 255; i++ { + switch i { + case '\x00', ' ', '=', '\n', '\\': + continue + default: + b := []byte{byte(i)} + s, err := Unescape(b) + if err != nil { + t.Errorf("Unescape(%q): error: %s", b, err) + } else if string(b) != s { + t.Errorf("Escape(%q) -> %q, expected %q", b, s, b) + } + } + } +} + +var headers = map[string]struct { + h Header + e error +}{ + // invalid version + "cnp/0.3ok\n": {e: ErrorSyntax{}}, + "cwp/0.3 ok\n": {e: ErrorSyntax{}}, + "cnp/0.03 ok\n": {e: ErrorSyntax{}}, + "cnp/00.3 ok\n": {e: ErrorSyntax{}}, + "cnp/0..3 ok\n": {e: ErrorSyntax{}}, + "cnp/.3 ok\n": {e: ErrorSyntax{}}, + "cnp/0. ok\n": {e: ErrorSyntax{}}, + "cnp/. ok\n": {e: ErrorSyntax{}}, + "cnp/0,3 ok\n": {e: ErrorSyntax{}}, + "/0.3 ok\n": {e: ErrorSyntax{}}, + "0.3 ok\n": {e: ErrorSyntax{}}, + "cnp/ ok\n": {e: ErrorSyntax{}}, + "cnp ok\n": {e: ErrorSyntax{}}, + "cnp.0.3 ok\n": {e: ErrorSyntax{}}, + "cnp/03 ok\n": {e: ErrorSyntax{}}, + "cnp/3 ok\n": {e: ErrorSyntax{}}, + "cnp/0 ok\n": {e: ErrorSyntax{}}, + "cnp/0 3 ok\n": {e: ErrorSyntax{}}, + "cnp/0/3 ok\n": {e: ErrorSyntax{}}, + + // missing/invalid intent + "cnp/0.3\n": {e: ErrorSyntax{}}, + "cnp/0.3 \n": {e: ErrorSyntax{}}, + "cnp/0.3 o\x00k\n": {e: ErrorSyntax{}}, + "cnp/0.3 foo=bar\n": {e: ErrorSyntax{}}, + + // missing/invalid line end + "cnp/0.3 ok \n": {e: ErrorSyntax{}}, + "cnp/0.3 ok\n\n": {e: ErrorSyntax{}}, + "cnp/0.3 ok": {e: ErrorSyntax{}}, + "cnp/0.3 ok ": {e: ErrorSyntax{}}, + "cnp/0.3 ok foo=bar \n": {e: ErrorSyntax{}}, + "cnp/0.3 ok foo=bar": {e: ErrorSyntax{}}, + "cnp/0.3 ok = =\n": {e: ErrorSyntax{}}, + + // spaces + "cnp/0.3 ok foo=bar\n": {e: ErrorSyntax{}}, + "cnp/0.3 ok\n": {e: ErrorSyntax{}}, + "cnp/0.3\tok\n": {e: ErrorSyntax{}}, + + // invalid params + "cnp/0.3 ok foo==bar\n": {e: ErrorSyntax{}}, + "cnp/0.3 ok foo=bar=baz\n": {e: ErrorSyntax{}}, + "cnp/0.3 ok foo=bar baz=quux \n": {e: ErrorSyntax{}}, + "cnp/0.3 ok foo\\-bar\n": {e: ErrorSyntax{}}, + + // invalid escape sequences + "cnp/0.3 o\\k\n": {e: ErrorSyntax{}}, + "cnp/0.3 ok qwe=\\\n": {e: ErrorSyntax{}}, + "cnp/0.3 ok fo\\o=bar\n": {e: ErrorSyntax{}}, + + // valid + "cnp/0.0 ok\n": {h: Header{0, 0, "ok", nil}}, + "cnp/0.3 ok\n": {h: Header{0, 3, "ok", nil}}, + "cnp/1.0 ok\n": {h: Header{1, 0, "ok", nil}}, + "cnp/123456.987654 ok\n": {h: Header{123456, 987654, "ok", nil}}, + "cnp/0.1 ok\n": {h: Header{0, 1, "ok", nil}}, + "cnp/0.3 ok\r\n": {h: Header{0, 3, "ok\r", nil}}, + "cnp/0.3 foo\\nbar\n": {h: Header{0, 3, "foo\nbar", nil}}, + "cnp/0.3 \\-\\_\\n\\0\\\\\n": {h: Header{0, 3, "= \n\x00\\", nil}}, + + // valid with params + "cnp/0.3 ok type=text/plain\n": {h: Header{0, 3, "ok", Parameters{"type": "text/plain"}}}, + "cnp/0.3 ok baz=quux foo=bar qwe=asd\n": {h: Header{0, 3, "ok", Parameters{"foo": "bar", "baz": "quux", "qwe": "asd"}}}, + "cnp/0.3 ok = \\_=\\0 \\-=\\n\r\n": {h: Header{0, 3, "ok", Parameters{"": "", "=": "\n\r", " ": "\x00"}}}, +} + +func TestHeaderParse(t *testing.T) { + for raw, tst := range headers { + hdr, err := ParseHeader([]byte(raw)) + if err != nil || tst.e != nil { + if !errorEqual(err, tst.e) { + t.Errorf("ParseHeader(%q): expected error %+v, got %+v (%v)", raw, tst.e, err, err) + } + } else if !headerEqual(tst.h, hdr) { + t.Errorf("ParseHeader(%q): expected %+v, got %+v", raw, tst.h, hdr) + } + } +} + +func TestHeaderCompose(t *testing.T) { + for raw, tst := range headers { + if tst.e != nil { + continue + } + // Parameters.Write currently sorts parameter keys + /*if len(tst.h.Parameters) > 1 { + continue // can't depend on parameter order + }*/ + str := tst.h.String() + if raw != str { + t.Errorf("%+v.String(): expected %q, got %q", tst.h, raw, str) + } + } +} + +func TestNewHeader(t *testing.T) { + raw := "cnp/0.3 ok baz=quux foo=bar qwe=asd\n" + hdr := Header{0, 3, "ok", Parameters{"foo": "bar", "baz": "quux", "qwe": "asd"}} + h := NewHeader("ok", Parameters{"foo": "bar", "baz": "quux", "qwe": "asd"}) + if !headerEqual(hdr, h) { + t.Errorf("%+v: expected %+v", h, hdr) + } + s := h.String() + if raw != s { + t.Errorf("%q: expected %q", h, hdr) + } + + raw = "cnp/0.3 ok\n" + hdr = Header{0, 3, "ok", nil} + h = NewHeader("ok", nil) + if !headerEqual(hdr, h) { + t.Errorf("%+v: expected %+v", h, hdr) + } + s = h.String() + if raw != s { + t.Errorf("%q: expected %q", h, hdr) + } +} -- cgit