1package imap_test 2 3import ( 4 "bytes" 5 "reflect" 6 "testing" 7 8 "github.com/emersion/go-imap" 9) 10 11func TestResp_WriteTo(t *testing.T) { 12 var b bytes.Buffer 13 w := imap.NewWriter(&b) 14 15 resp := imap.NewUntaggedResp([]interface{}{imap.RawString("76"), imap.RawString("FETCH"), []interface{}{imap.RawString("UID"), 783}}) 16 if err := resp.WriteTo(w); err != nil { 17 t.Fatal(err) 18 } 19 20 if b.String() != "* 76 FETCH (UID 783)\r\n" { 21 t.Error("Invalid response:", b.String()) 22 } 23} 24 25func TestContinuationReq_WriteTo(t *testing.T) { 26 var b bytes.Buffer 27 w := imap.NewWriter(&b) 28 29 resp := &imap.ContinuationReq{} 30 31 if err := resp.WriteTo(w); err != nil { 32 t.Fatal(err) 33 } 34 35 if b.String() != "+\r\n" { 36 t.Error("Invalid continuation:", b.String()) 37 } 38} 39 40func TestContinuationReq_WriteTo_WithInfo(t *testing.T) { 41 var b bytes.Buffer 42 w := imap.NewWriter(&b) 43 44 resp := &imap.ContinuationReq{Info: "send literal"} 45 46 if err := resp.WriteTo(w); err != nil { 47 t.Fatal(err) 48 } 49 50 if b.String() != "+ send literal\r\n" { 51 t.Error("Invalid continuation:", b.String()) 52 } 53} 54 55func TestReadResp_ContinuationReq(t *testing.T) { 56 b := bytes.NewBufferString("+ send literal\r\n") 57 r := imap.NewReader(b) 58 59 resp, err := imap.ReadResp(r) 60 if err != nil { 61 t.Fatal(err) 62 } 63 64 cont, ok := resp.(*imap.ContinuationReq) 65 if !ok { 66 t.Fatal("Response is not a continuation request") 67 } 68 69 if cont.Info != "send literal" { 70 t.Error("Invalid info:", cont.Info) 71 } 72} 73 74func TestReadResp_ContinuationReq_NoInfo(t *testing.T) { 75 b := bytes.NewBufferString("+\r\n") 76 r := imap.NewReader(b) 77 78 resp, err := imap.ReadResp(r) 79 if err != nil { 80 t.Fatal(err) 81 } 82 83 cont, ok := resp.(*imap.ContinuationReq) 84 if !ok { 85 t.Fatal("Response is not a continuation request") 86 } 87 88 if cont.Info != "" { 89 t.Error("Invalid info:", cont.Info) 90 } 91} 92 93func TestReadResp_Resp(t *testing.T) { 94 b := bytes.NewBufferString("* 1 EXISTS\r\n") 95 r := imap.NewReader(b) 96 97 resp, err := imap.ReadResp(r) 98 if err != nil { 99 t.Fatal(err) 100 } 101 102 data, ok := resp.(*imap.DataResp) 103 if !ok { 104 t.Fatal("Invalid response type") 105 } 106 107 if data.Tag != "*" { 108 t.Error("Invalid tag:", data.Tag) 109 } 110 if len(data.Fields) != 2 { 111 t.Error("Invalid fields:", data.Fields) 112 } 113} 114 115func TestReadResp_Resp_NoArgs(t *testing.T) { 116 b := bytes.NewBufferString("* SEARCH\r\n") 117 r := imap.NewReader(b) 118 119 resp, err := imap.ReadResp(r) 120 if err != nil { 121 t.Fatal(err) 122 } 123 124 data, ok := resp.(*imap.DataResp) 125 if !ok { 126 t.Fatal("Invalid response type") 127 } 128 129 if data.Tag != "*" { 130 t.Error("Invalid tag:", data.Tag) 131 } 132 if len(data.Fields) != 1 || data.Fields[0] != "SEARCH" { 133 t.Error("Invalid fields:", data.Fields) 134 } 135} 136 137func TestReadResp_StatusResp(t *testing.T) { 138 tests := []struct { 139 input string 140 expected *imap.StatusResp 141 }{ 142 { 143 input: "* OK IMAP4rev1 Service Ready\r\n", 144 expected: &imap.StatusResp{ 145 Tag: "*", 146 Type: imap.StatusRespOk, 147 Info: "IMAP4rev1 Service Ready", 148 }, 149 }, 150 { 151 input: "* PREAUTH Welcome Pauline!\r\n", 152 expected: &imap.StatusResp{ 153 Tag: "*", 154 Type: imap.StatusRespPreauth, 155 Info: "Welcome Pauline!", 156 }, 157 }, 158 { 159 input: "a001 OK NOOP completed\r\n", 160 expected: &imap.StatusResp{ 161 Tag: "a001", 162 Type: imap.StatusRespOk, 163 Info: "NOOP completed", 164 }, 165 }, 166 { 167 input: "a001 OK [READ-ONLY] SELECT completed\r\n", 168 expected: &imap.StatusResp{ 169 Tag: "a001", 170 Type: imap.StatusRespOk, 171 Code: "READ-ONLY", 172 Info: "SELECT completed", 173 }, 174 }, 175 { 176 input: "a001 OK [CAPABILITY IMAP4rev1 UIDPLUS] LOGIN completed\r\n", 177 expected: &imap.StatusResp{ 178 Tag: "a001", 179 Type: imap.StatusRespOk, 180 Code: "CAPABILITY", 181 Arguments: []interface{}{"IMAP4rev1", "UIDPLUS"}, 182 Info: "LOGIN completed", 183 }, 184 }, 185 } 186 187 for _, test := range tests { 188 b := bytes.NewBufferString(test.input) 189 r := imap.NewReader(b) 190 191 resp, err := imap.ReadResp(r) 192 if err != nil { 193 t.Fatal(err) 194 } 195 196 status, ok := resp.(*imap.StatusResp) 197 if !ok { 198 t.Fatal("Response is not a status:", resp) 199 } 200 201 if status.Tag != test.expected.Tag { 202 t.Errorf("Invalid tag: expected %v but got %v", status.Tag, test.expected.Tag) 203 } 204 if status.Type != test.expected.Type { 205 t.Errorf("Invalid type: expected %v but got %v", status.Type, test.expected.Type) 206 } 207 if status.Code != test.expected.Code { 208 t.Errorf("Invalid code: expected %v but got %v", status.Code, test.expected.Code) 209 } 210 if len(status.Arguments) != len(test.expected.Arguments) { 211 t.Errorf("Invalid arguments: expected %v but got %v", status.Arguments, test.expected.Arguments) 212 } 213 if status.Info != test.expected.Info { 214 t.Errorf("Invalid info: expected %v but got %v", status.Info, test.expected.Info) 215 } 216 } 217} 218 219func TestParseNamedResp(t *testing.T) { 220 tests := []struct { 221 resp *imap.DataResp 222 name string 223 fields []interface{} 224 }{ 225 { 226 resp: &imap.DataResp{Fields: []interface{}{"CAPABILITY", "IMAP4rev1"}}, 227 name: "CAPABILITY", 228 fields: []interface{}{"IMAP4rev1"}, 229 }, 230 { 231 resp: &imap.DataResp{Fields: []interface{}{"42", "EXISTS"}}, 232 name: "EXISTS", 233 fields: []interface{}{"42"}, 234 }, 235 { 236 resp: &imap.DataResp{Fields: []interface{}{"42", "FETCH", "blah"}}, 237 name: "FETCH", 238 fields: []interface{}{"42", "blah"}, 239 }, 240 } 241 242 for _, test := range tests { 243 name, fields, ok := imap.ParseNamedResp(test.resp) 244 if !ok { 245 t.Errorf("ParseNamedResp(%v)[2] = false, want true", test.resp) 246 } else if name != test.name { 247 t.Errorf("ParseNamedResp(%v)[0] = %v, want %v", test.resp, name, test.name) 248 } else if !reflect.DeepEqual(fields, test.fields) { 249 t.Errorf("ParseNamedResp(%v)[1] = %v, want %v", test.resp, fields, test.fields) 250 } 251 } 252} 253