1package imap_test 2 3import ( 4 "fmt" 5 "reflect" 6 "sort" 7 "testing" 8 9 "github.com/emersion/go-imap" 10 "github.com/emersion/go-imap/internal" 11) 12 13func TestCanonicalMailboxName(t *testing.T) { 14 if got := imap.CanonicalMailboxName("Inbox"); got != imap.InboxName { 15 t.Errorf("Invalid canonical mailbox name: expected %q but got %q", imap.InboxName, got) 16 } 17 if got := imap.CanonicalMailboxName("Drafts"); got != "Drafts" { 18 t.Errorf("Invalid canonical mailbox name: expected %q but got %q", "Drafts", got) 19 } 20} 21 22var mailboxInfoTests = []struct { 23 fields []interface{} 24 info *imap.MailboxInfo 25}{ 26 { 27 fields: []interface{}{ 28 []interface{}{"\\Noselect", "\\Recent", "\\Unseen"}, 29 "/", 30 "INBOX", 31 }, 32 info: &imap.MailboxInfo{ 33 Attributes: []string{"\\Noselect", "\\Recent", "\\Unseen"}, 34 Delimiter: "/", 35 Name: "INBOX", 36 }, 37 }, 38} 39 40func TestMailboxInfo_Parse(t *testing.T) { 41 for _, test := range mailboxInfoTests { 42 info := &imap.MailboxInfo{} 43 if err := info.Parse(test.fields); err != nil { 44 t.Fatal(err) 45 } 46 47 if fmt.Sprint(info.Attributes) != fmt.Sprint(test.info.Attributes) { 48 t.Fatal("Invalid flags:", info.Attributes) 49 } 50 if info.Delimiter != test.info.Delimiter { 51 t.Fatal("Invalid delimiter:", info.Delimiter) 52 } 53 if info.Name != test.info.Name { 54 t.Fatal("Invalid name:", info.Name) 55 } 56 } 57} 58 59func TestMailboxInfo_Format(t *testing.T) { 60 for _, test := range mailboxInfoTests { 61 fields := test.info.Format() 62 63 if fmt.Sprint(fields) != fmt.Sprint(test.fields) { 64 t.Fatal("Invalid fields:", fields) 65 } 66 } 67} 68 69var mailboxInfoMatchTests = []struct { 70 name, ref, pattern string 71 result bool 72}{ 73 {name: "INBOX", pattern: "INBOX", result: true}, 74 {name: "INBOX", pattern: "Asuka", result: false}, 75 {name: "INBOX", pattern: "*", result: true}, 76 {name: "INBOX", pattern: "%", result: true}, 77 {name: "Neon Genesis Evangelion/Misato", pattern: "*", result: true}, 78 {name: "Neon Genesis Evangelion/Misato", pattern: "%", result: false}, 79 {name: "Neon Genesis Evangelion/Misato", pattern: "Neon Genesis Evangelion/*", result: true}, 80 {name: "Neon Genesis Evangelion/Misato", pattern: "Neon Genesis Evangelion/%", result: true}, 81 {name: "Neon Genesis Evangelion/Misato", pattern: "Neo* Evangelion/Misato", result: true}, 82 {name: "Neon Genesis Evangelion/Misato", pattern: "Neo% Evangelion/Misato", result: true}, 83 {name: "Neon Genesis Evangelion/Misato", pattern: "*Eva*/Misato", result: true}, 84 {name: "Neon Genesis Evangelion/Misato", pattern: "%Eva%/Misato", result: true}, 85 {name: "Neon Genesis Evangelion/Misato", pattern: "*X*/Misato", result: false}, 86 {name: "Neon Genesis Evangelion/Misato", pattern: "%X%/Misato", result: false}, 87 {name: "Neon Genesis Evangelion/Misato", pattern: "Neon Genesis Evangelion/Mi%o", result: true}, 88 {name: "Neon Genesis Evangelion/Misato", pattern: "Neon Genesis Evangelion/Mi%too", result: false}, 89 {name: "Misato/Misato", pattern: "Mis*to/Misato", result: true}, 90 {name: "Misato/Misato", pattern: "Mis*to", result: true}, 91 {name: "Misato/Misato/Misato", pattern: "Mis*to/Mis%to", result: true}, 92 {name: "Misato/Misato", pattern: "Mis**to/Misato", result: true}, 93 {name: "Misato/Misato", pattern: "Misat%/Misato", result: true}, 94 {name: "Misato/Misato", pattern: "Misat%Misato", result: false}, 95 {name: "Misato/Misato", ref: "Misato", pattern: "Misato", result: true}, 96 {name: "Misato/Misato", ref: "Misato/", pattern: "Misato", result: true}, 97 {name: "Misato/Misato", ref: "Shinji", pattern: "/Misato/*", result: true}, 98 {name: "Misato/Misato", ref: "Misato", pattern: "/Misato", result: false}, 99 {name: "Misato/Misato", ref: "Misato", pattern: "Shinji", result: false}, 100 {name: "Misato/Misato", ref: "Shinji", pattern: "Misato", result: false}, 101} 102 103func TestMailboxInfo_Match(t *testing.T) { 104 for _, test := range mailboxInfoMatchTests { 105 info := &imap.MailboxInfo{Name: test.name, Delimiter: "/"} 106 result := info.Match(test.ref, test.pattern) 107 if result != test.result { 108 t.Errorf("Matching name %q with pattern %q and reference %q returns %v, but expected %v", test.name, test.pattern, test.ref, result, test.result) 109 } 110 } 111} 112 113func TestNewMailboxStatus(t *testing.T) { 114 status := imap.NewMailboxStatus("INBOX", []imap.StatusItem{imap.StatusMessages, imap.StatusUnseen}) 115 116 expected := &imap.MailboxStatus{ 117 Name: "INBOX", 118 Items: map[imap.StatusItem]interface{}{imap.StatusMessages: nil, imap.StatusUnseen: nil}, 119 } 120 121 if !reflect.DeepEqual(expected, status) { 122 t.Errorf("Invalid mailbox status: expected \n%+v\n but got \n%+v", expected, status) 123 } 124} 125 126var mailboxStatusTests = [...]struct { 127 fields []interface{} 128 status *imap.MailboxStatus 129}{ 130 { 131 fields: []interface{}{ 132 "MESSAGES", uint32(42), 133 "RECENT", uint32(1), 134 "UNSEEN", uint32(6), 135 "UIDNEXT", uint32(65536), 136 "UIDVALIDITY", uint32(4242), 137 }, 138 status: &imap.MailboxStatus{ 139 Items: map[imap.StatusItem]interface{}{ 140 imap.StatusMessages: nil, 141 imap.StatusRecent: nil, 142 imap.StatusUnseen: nil, 143 imap.StatusUidNext: nil, 144 imap.StatusUidValidity: nil, 145 }, 146 Messages: 42, 147 Recent: 1, 148 Unseen: 6, 149 UidNext: 65536, 150 UidValidity: 4242, 151 }, 152 }, 153} 154 155func TestMailboxStatus_Parse(t *testing.T) { 156 for i, test := range mailboxStatusTests { 157 status := &imap.MailboxStatus{} 158 if err := status.Parse(test.fields); err != nil { 159 t.Errorf("Expected no error while parsing mailbox status #%v, got: %v", i, err) 160 continue 161 } 162 163 if !reflect.DeepEqual(status, test.status) { 164 t.Errorf("Invalid parsed mailbox status for #%v: got \n%+v\n but expected \n%+v", i, status, test.status) 165 } 166 } 167} 168 169func TestMailboxStatus_Format(t *testing.T) { 170 for i, test := range mailboxStatusTests { 171 fields := test.status.Format() 172 173 // MapListSorter does not know about RawString and will panic. 174 stringFields := make([]interface{}, 0, len(fields)) 175 for _, field := range fields { 176 if s, ok := field.(imap.RawString); ok { 177 stringFields = append(stringFields, string(s)) 178 } else { 179 stringFields = append(stringFields, field) 180 } 181 } 182 183 sort.Sort(internal.MapListSorter(stringFields)) 184 185 sort.Sort(internal.MapListSorter(test.fields)) 186 187 if !reflect.DeepEqual(stringFields, test.fields) { 188 t.Errorf("Invalid mailbox status fields for #%v: got \n%+v\n but expected \n%+v", i, fields, test.fields) 189 } 190 } 191} 192