package protocol import ( "bufio" "bytes" "testing" ) func TestParseSimpleString(t *testing.T) { tests := []struct { input string expected Status }{ {"+OK\r\n", "OK"}, {"+PONG\r\n", "PONG"}, {"+\r\n", ""}, } for _, tt := range tests { reader := bufio.NewReader(bytes.NewReader([]byte(tt.input))) val, err := Parse(reader) if err != nil { t.Errorf("Parse(%q) error: %v", tt.input, err) continue } status, ok := val.(Status) if !ok { t.Errorf("Parse(%q) got %T, want Status", tt.input, val) continue } if status != tt.expected { t.Errorf("Parse(%q) = %q, want %q", tt.input, status, tt.expected) } } } func TestParseError(t *testing.T) { input := "-ERR unknown command\r\n" reader := bufio.NewReader(bytes.NewReader([]byte(input))) val, err := Parse(reader) if err != nil { t.Fatalf("Parse error: %v", err) } errVal, ok := val.(Error) if !ok { t.Fatalf("got %T, want Error", val) } if errVal.Message != "ERR unknown command" { t.Errorf("got %q, want 'ERR unknown command'", errVal.Message) } } func TestParseInteger(t *testing.T) { tests := []struct { input string expected Int }{ {":0\r\n", 0}, {":12345\r\n", 12345}, {":-100\r\n", -100}, } for _, tt := range tests { reader := bufio.NewReader(bytes.NewReader([]byte(tt.input))) val, err := Parse(reader) if err != nil { t.Errorf("Parse(%q) error: %v", tt.input, err) continue } n, ok := val.(Int) if !ok { t.Errorf("Parse(%q) got %T, want Int", tt.input, val) continue } if n != tt.expected { t.Errorf("Parse(%q) = %d, want %d", tt.input, n, tt.expected) } } } func TestParseBulkString(t *testing.T) { tests := []struct { input string expected []byte }{ {"$5\r\nhello\r\n", []byte("hello")}, {"$0\r\n\r\n", []byte("")}, {"$-1\r\n", nil}, } for _, tt := range tests { reader := bufio.NewReader(bytes.NewReader([]byte(tt.input))) val, err := Parse(reader) if err != nil { t.Errorf("Parse(%q) error: %v", tt.input, err) continue } if tt.expected == nil { if val != nil { t.Errorf("Parse(%q) = %v, want nil", tt.input, val) } continue } bulk, ok := val.(Bulk) if !ok { t.Errorf("Parse(%q) got %T, want Bulk", tt.input, val) continue } if string(bulk) != string(tt.expected) { t.Errorf("Parse(%q) = %q, want %q", tt.input, string(bulk), string(tt.expected)) } } } func TestParseArray(t *testing.T) { input := "*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n" reader := bufio.NewReader(bytes.NewReader([]byte(input))) val, err := Parse(reader) if err != nil { t.Fatalf("Parse error: %v", err) } arr, ok := val.(Array) if !ok { t.Fatalf("got %T, want Array", val) } if len(arr) != 2 { t.Errorf("array length = %d, want 2", len(arr)) } } func TestParseEmptyArray(t *testing.T) { input := "*0\r\n" reader := bufio.NewReader(bytes.NewReader([]byte(input))) val, err := Parse(reader) if err != nil { t.Fatalf("Parse error: %v", err) } arr, ok := val.(Array) if !ok { t.Fatalf("got %T, want Array", val) } if len(arr) != 0 { t.Errorf("array length = %d, want 0", len(arr)) } } func TestMakeStatus(t *testing.T) { result := MakeStatus("OK") expected := "+OK\r\n" if string(result) != expected { t.Errorf("MakeStatus() = %q, want %q", string(result), expected) } } func TestMakeInt(t *testing.T) { result := MakeInt(42) expected := ":42\r\n" if string(result) != expected { t.Errorf("MakeInt() = %q, want %q", string(result), expected) } } func TestMakeBulk(t *testing.T) { tests := []struct { input []byte expected string }{ {[]byte("hello"), "$5\r\nhello\r\n"}, {[]byte(""), "$0\r\n\r\n"}, {nil, "$-1\r\n"}, } for _, tt := range tests { result := MakeBulk(tt.input) if string(result) != tt.expected { t.Errorf("MakeBulk(%q) = %q, want %q", tt.input, string(result), tt.expected) } } } func TestMakeMultiBulk(t *testing.T) { result := MakeMultiBulk([]Value{Bulk("message"), Bulk("mychannel"), Bulk("hello")}) if len(result) == 0 { t.Error("MakeMultiBulk returned empty") } } func TestToBytes(t *testing.T) { tests := []struct { input Value expected string }{ {nil, "$-1\r\n"}, {Status("OK"), "+OK\r\n"}, {Int(42), ":42\r\n"}, {Error{Message: "ERR"}, "-ERR\r\n"}, {Bulk("test"), "$4\r\ntest\r\n"}, } for _, tt := range tests { result := ToBytes(tt.input) if string(result) != tt.expected { t.Errorf("ToBytes(%v) = %q, want %q", tt.input, string(result), tt.expected) } } }