1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.emailcommon.mail; 18 19 import android.test.AndroidTestCase; 20 import android.test.suitebuilder.annotation.SmallTest; 21 import org.apache.james.mime4j.decoder.DecoderUtil; 22 23 /** 24 * This is a series of unit tests for the Address class. These tests must be locally 25 * complete - no server(s) required. 26 */ 27 @SmallTest 28 public class AddressUnitTests extends AndroidTestCase { 29 30 private static final String MULTI_ADDRESSES_LIST = 31 "noname1 (at) dom1.com, " 32 + "<noname2 (at) dom2.com>, " 33 + "simple name <address3 (at) dom3.org>, " 34 + "\"name,4\" <address4 (at) dom4.org>," 35 + "\"big \\\"G\\\"\" <bigG (at) dom5.net>," 36 + "\u65E5\u672C\u8A9E <address6 (at) co.jp>," 37 + "\"\u65E5\u672C\u8A9E\" <address7 (at) co.jp>," 38 + "\uD834\uDF01\uD834\uDF46 <address8 (at) ne.jp>," 39 + "\"\uD834\uDF01\uD834\uDF46\" <address9 (at) ne.jp>," 40 + "noname (at) dom.com <noname (at) dom.com>" // personal == address 41 ; 42 private static final int MULTI_ADDRESSES_COUNT = 10; 43 44 private static final Address ADDR_1 = new Address("john (at) gmail.com", "John Doe"); 45 private static final Address ADDR_2 = new Address("foo (at) bar.com", null); 46 private static final Address ADDR_3 = new Address("mar.y+test (at) gmail.com", "Mar-y, B; B*arr"); 47 private static final Address[][] TO_HEADER_CASES = { 48 {ADDR_2}, {ADDR_1}, 49 {ADDR_1, ADDR_2}, {ADDR_2, ADDR_1}, 50 {ADDR_1, ADDR_3}, {ADDR_2, ADDR_2}, 51 {ADDR_1, ADDR_2, ADDR_3}, {ADDR_3, ADDR_1, ADDR_2} 52 }; 53 54 Address mAddress1; 55 Address mAddress2; 56 Address mAddress3; 57 58 /** 59 * Setup code. We generate a handful of Address objects 60 */ 61 @Override 62 protected void setUp() throws Exception { 63 super.setUp(); 64 65 mAddress1 = new Address("address1", "personal1"); 66 mAddress2 = new Address("address2", ""); 67 mAddress3 = new Address("address3", null); 68 } 69 70 // see documentation of DecoderUtil.decodeEncodedWords() for details 71 private static String padEncoded(String s) { 72 return "=?UTF-8?B?" + s + "?="; 73 } 74 75 /** 76 * Generate strings of incresing lenght by taking prefix substrings. 77 * For each of them, compare with the decoding of the precomputed base-64 encoding. 78 */ 79 public void testBase64Decode() { 80 String testString = "xyza\0\""; 81 String base64Encoded[] = {"", "eA==", "eHk=", "eHl6", "eHl6YQ==", "eHl6YQA=", "eHl6YQAi"}; 82 int len = testString.length(); 83 for (int i = 1; i <= len; ++i) { 84 String encoded = padEncoded(base64Encoded[i]); 85 String decoded = DecoderUtil.decodeEncodedWords(encoded); 86 String prefix = testString.substring(0, i); 87 assertEquals(""+i, prefix, decoded); 88 } 89 } 90 91 @SmallTest 92 public void testEncodedWords() { 93 final String body = "=?UTF-8?B?Foobar?="; 94 DecoderUtil.decodeEncodedWords(body); 95 96 final String body2 = "=?UTF-8?B?Foobar?==?"; 97 DecoderUtil.decodeEncodedWords(body2); 98 } 99 100 @SmallTest 101 public void testEncodedWord() { 102 final String body = "=?UTF-8?B?Foobar?="; 103 DecoderUtil.decodeEncodedWord(body, 0, body.length()); 104 105 final String body2 = "=?Foobar"; 106 DecoderUtil.decodeEncodedWord(body2, 0, body2.length()); 107 } 108 109 /** 110 * Test for setAddress(). 111 */ 112 public void testSetAddress() { 113 String bareAddress = "user1 (at) dom1.com"; 114 String bracketAddress = "<user2 (at) dom2.com>"; 115 116 Address address = new Address(bareAddress); 117 assertEquals("bare address", "user1 (at) dom1.com", address.getAddress()); 118 119 address.setAddress(bracketAddress); 120 assertEquals("bracket address", "user2 (at) dom2.com", address.getAddress()); 121 } 122 123 /** 124 * Test for empty setPersonal(). 125 */ 126 public void brokentestNullPersonal() { 127 Address address = new Address("user1 (at) dom1.org"); 128 assertNull("no name", address.getPersonal()); 129 130 address.setPersonal(null); 131 assertNull("null name", address.getPersonal()); 132 133 address.setPersonal(""); 134 assertNull("empty name", address.getPersonal()); 135 136 address.setPersonal("\"\""); 137 assertNull("quoted empty address", address.getPersonal()); 138 } 139 140 /** 141 * Test for setPersonal(). 142 */ 143 public void brokentestSetPersonal() { 144 Address address = new Address("user1 (at) dom1.net", "simple name"); 145 assertEquals("simple name", "simple name", address.getPersonal()); 146 147 address.setPersonal("big \\\"G\\\""); 148 assertEquals("quoted name", "big \"G\"", address.getPersonal()); 149 150 address.setPersonal("=?UTF-8?Q?big \"G\"?="); 151 assertEquals("quoted printable name", "big \"G\"", address.getPersonal()); 152 153 address.setPersonal("=?UTF-8?B?YmlnICJHIg==?="); 154 assertEquals("base64 encoded name", "big \"G\"", address.getPersonal()); 155 } 156 157 /** 158 * Test for setPersonal() with utf-16 and utf-32. 159 */ 160 public void brokentestSetPersonalMultipleEncodings() { 161 Address address = new Address("user1 (at) dom1.co.jp", "=?UTF-8?B?5bK45pys?="); 162 assertEquals("base64 utf-16 name", "\u5CB8\u672C", address.getPersonal()); 163 164 address.setPersonal("\"=?UTF-8?Q?=E5=B2=B8=E6=9C=AC?=\""); 165 assertEquals("quoted printable utf-16 name", "\u5CB8\u672C", address.getPersonal()); 166 167 address.setPersonal("=?ISO-2022-JP?B?GyRCNF9LXBsoQg==?="); 168 assertEquals("base64 jis encoded name", "\u5CB8\u672C", address.getPersonal()); 169 170 address.setPersonal("\"=?UTF-8?B?8J2MgfCdjYY=?=\""); 171 assertEquals("base64 utf-32 name", "\uD834\uDF01\uD834\uDF46", address.getPersonal()); 172 173 address.setPersonal("=?UTF-8?Q?=F0=9D=8C=81=F0=9D=8D=86?="); 174 assertEquals("quoted printable utf-32 name", 175 "\uD834\uDF01\uD834\uDF46", address.getPersonal()); 176 } 177 178 /** 179 * TODO: more in-depth tests for parse() 180 */ 181 182 /** 183 * Simple quick checks of empty-input edge conditions for parse() 184 * 185 * NOTE: This is not a claim that these edge cases are "correct", only to maintain consistent 186 * behavior while I am changing some of the code in the function under test. 187 */ 188 public void testEmptyParse() { 189 Address[] result; 190 191 // null input => empty array 192 result = Address.parse(null); 193 assertTrue("parsing null address", result != null && result.length == 0); 194 195 // empty string input => empty array 196 result = Address.parse(""); 197 assertTrue("parsing zero-length", result != null && result.length == 0); 198 199 // spaces 200 result = Address.parse(" "); 201 assertTrue("parsing spaces", result != null && result.length == 0); 202 203 // spaces with comma 204 result = Address.parse(" , "); 205 assertTrue("parsing spaces with comma", result != null && result.length == 0); 206 } 207 208 /** 209 * Test parsing for single address. 210 */ 211 public void testSingleParse() { 212 Address[] address1 = Address.parse("address1 (at) dom1.com"); 213 assertEquals("bare address count", 1, address1.length); 214 assertEquals("bare address", "address1 (at) dom1.com", address1[0].getAddress()); 215 assertNull("name of bare address", address1[0].getPersonal()); 216 217 Address[] address2 = Address.parse("<address2 (at) dom2.com>"); 218 assertEquals("bracket address count", 1, address2.length); 219 assertEquals("bracket address", "address2 (at) dom2.com", address2[0].getAddress()); 220 assertNull("name of bracket address", address2[0].getPersonal()); 221 222 Address[] address3 = Address.parse("first last <address3 (at) dom3.org>"); 223 assertEquals("address with name count", 1, address3.length); 224 assertEquals("address with name", "address3 (at) dom3.org", address3[0].getAddress()); 225 assertEquals("name of address with name", "first last", address3[0].getPersonal()); 226 227 Address[] address4 = Address.parse("\"first,last\" <address4 (at) dom4.org>"); 228 assertEquals("address with quoted name count", 1, address4.length); 229 assertEquals("address with quoted name", "address4 (at) dom4.org", address4[0].getAddress()); 230 assertEquals("name of address with quoted name", "first,last", address4[0].getPersonal()); 231 } 232 233 /** 234 * Test parsing for illegal address. 235 */ 236 public void testIllegalParse() { 237 Address[] address1 = Address.parse("address1"); 238 assertEquals("no atmark", 0, address1.length); 239 240 Address[] address2 = Address.parse("address2@"); 241 assertEquals("no domain", 0, address2.length); 242 243 Address[] address3 = Address.parse("@dom3.com"); 244 assertEquals("no local part", 0, address3.length); 245 246 Address[] address4 = Address.parse("address4@sub (at) dom4.org"); 247 assertEquals("more than one atmark", 0, address4.length); 248 249 Address[] address5 = Address.parse("address5@dom5"); 250 assertEquals("not dot in domain part", 0, address5.length); 251 252 Address[] address6 = Address.parse("address6 (at) dom6.com."); 253 assertEquals("domain ends with dot", 0, address6.length); 254 255 Address[] address7 = Address.parse("address7 (at) .dom7.org"); 256 assertEquals("domain starts with dot", 0, address7.length); 257 } 258 259 /** 260 * Test parsing for address part. 261 */ 262 public void testParsingAddress() { 263 Address[] addresses = Address.parse("address1 (at) dom1.net, <address2 (at) dom2.com>"); 264 assertEquals("address count", 2, addresses.length); 265 266 assertEquals("bare address", "address1 (at) dom1.net", addresses[0].getAddress()); 267 assertNull("bare address name", addresses[0].getPersonal()); 268 269 assertEquals("bracket address", "address2 (at) dom2.com", addresses[1].getAddress()); 270 assertNull("bracket address name", addresses[1].getPersonal()); 271 } 272 273 /** 274 * Test parsing for simple name part. 275 */ 276 public void testParsingSimpleName() { 277 Address[] addresses = Address.parse( 278 "name 1 <address1 (at) dom1.net>, " + 279 "\"name,2\" <address2 (at) dom2.org>"); 280 assertEquals("address count", 2, addresses.length); 281 282 assertEquals("bare name address", "address1 (at) dom1.net", addresses[0].getAddress()); 283 assertEquals("bare name", "name 1", addresses[0].getPersonal()); 284 285 assertEquals("double quoted name address", "address2 (at) dom2.org", addresses[1].getAddress()); 286 assertEquals("double quoted name", "name,2", addresses[1].getPersonal()); 287 } 288 289 /** 290 * Test parsing for utf-16 name part. 291 */ 292 public void testParsingUtf16Name() { 293 Address[] addresses = Address.parse( 294 "\u3042\u3044\u3046 \u3048\u304A <address1 (at) dom1.jp>, " + 295 "\"\u3042\u3044\u3046,\u3048\u304A\" <address2 (at) dom2.jp>"); 296 assertEquals("address count", 2, addresses.length); 297 298 assertEquals("bare utf-16 name address", "address1 (at) dom1.jp", addresses[0].getAddress()); 299 assertEquals("bare utf-16 name", 300 "\u3042\u3044\u3046 \u3048\u304A", addresses[0].getPersonal()); 301 302 assertEquals("double quoted utf-16 name address", 303 "address2 (at) dom2.jp", addresses[1].getAddress()); 304 assertEquals("double quoted utf-16 name", 305 "\u3042\u3044\u3046,\u3048\u304A", addresses[1].getPersonal()); 306 } 307 308 /** 309 * Test parsing for utf-32 name part. 310 */ 311 public void testParsingUtf32Name() { 312 Address[] addresses = Address.parse( 313 "\uD834\uDF01\uD834\uDF46 \uD834\uDF22 <address1 (at) dom1.net>, " + 314 "\"\uD834\uDF01\uD834\uDF46,\uD834\uDF22\" <address2 (at) dom2.com>"); 315 assertEquals("address count", 2, addresses.length); 316 317 assertEquals("bare utf-32 name address", "address1 (at) dom1.net", addresses[0].getAddress()); 318 assertEquals("bare utf-32 name", 319 "\uD834\uDF01\uD834\uDF46 \uD834\uDF22", addresses[0].getPersonal()); 320 321 assertEquals("double quoted utf-32 name address", 322 "address2 (at) dom2.com", addresses[1].getAddress()); 323 assertEquals("double quoted utf-32 name", 324 "\uD834\uDF01\uD834\uDF46,\uD834\uDF22", addresses[1].getPersonal()); 325 } 326 327 /** 328 * Test parsing for multi addresses. 329 */ 330 public void testParseMulti() { 331 Address[] addresses = Address.parse(MULTI_ADDRESSES_LIST); 332 333 assertEquals("multi addrsses count", MULTI_ADDRESSES_COUNT, addresses.length); 334 335 assertEquals("no name 1 address", "noname1 (at) dom1.com", addresses[0].getAddress()); 336 assertNull("no name 1 name", addresses[0].getPersonal()); 337 assertEquals("no name 2 address", "noname2 (at) dom2.com", addresses[1].getAddress()); 338 assertNull("no name 2 name", addresses[1].getPersonal()); 339 assertEquals("simple name address", "address3 (at) dom3.org", addresses[2].getAddress()); 340 assertEquals("simple name name", "simple name", addresses[2].getPersonal()); 341 assertEquals("double quoted name address", "address4 (at) dom4.org", addresses[3].getAddress()); 342 assertEquals("double quoted name name", "name,4", addresses[3].getPersonal()); 343 assertEquals("quoted name address", "bigG (at) dom5.net", addresses[4].getAddress()); 344 assertEquals("quoted name name", "big \"G\"", addresses[4].getPersonal()); 345 assertEquals("utf-16 name address", "address6 (at) co.jp", addresses[5].getAddress()); 346 assertEquals("utf-16 name name", "\u65E5\u672C\u8A9E", addresses[5].getPersonal()); 347 assertEquals("utf-16 quoted name address", "address7 (at) co.jp", addresses[6].getAddress()); 348 assertEquals("utf-16 quoted name name", "\u65E5\u672C\u8A9E", 349 addresses[6].getPersonal()); 350 assertEquals("utf-32 name address", "address8 (at) ne.jp", addresses[7].getAddress()); 351 assertEquals("utf-32 name name", "\uD834\uDF01\uD834\uDF46", addresses[7].getPersonal()); 352 assertEquals("utf-32 quoted name address", "address9 (at) ne.jp", addresses[8].getAddress()); 353 assertEquals("utf-32 quoted name name", "\uD834\uDF01\uD834\uDF46", 354 addresses[8].getPersonal()); 355 } 356 357 /** 358 * Test various combinations of the toString (single) method 359 */ 360 public void testToStringSingle() { 361 Address[] addresses = Address.parse(MULTI_ADDRESSES_LIST); 362 363 assertEquals("multi addrsses count", MULTI_ADDRESSES_COUNT, addresses.length); 364 365 // test for toString() results. 366 assertEquals("no name 1", "noname1 (at) dom1.com", addresses[0].toString()); 367 assertEquals("no name 2", "noname2 (at) dom2.com", addresses[1].toString()); 368 assertEquals("simple name", "simple name <address3 (at) dom3.org>", addresses[2].toString()); 369 assertEquals("double quoted name", 370 "\"name,4\" <address4 (at) dom4.org>", addresses[3].toString()); 371 assertEquals("quoted name", "\"big \"G\"\" <bigG (at) dom5.net>", addresses[4].toString()); 372 assertEquals("utf-16 name", "\u65E5\u672C\u8A9E <address6 (at) co.jp>", 373 addresses[5].toString()); 374 assertEquals("utf-16 quoted name", "\u65E5\u672C\u8A9E <address7 (at) co.jp>", 375 addresses[6].toString()); 376 assertEquals("utf-32 name", "\uD834\uDF01\uD834\uDF46 <address8 (at) ne.jp>", 377 addresses[7].toString()); 378 assertEquals("utf-32 quoted name", "\uD834\uDF01\uD834\uDF46 <address9 (at) ne.jp>", 379 addresses[8].toString()); 380 assertEquals("name==address", "noname (at) dom.com", addresses[9].toString()); 381 } 382 383 /** 384 * Test various combinations of the toString (multi) method 385 */ 386 public void testToStringMulti() { 387 final Address[] address = Address.parse("noname1 (at) dom1.com"); 388 final Address[] addresses = Address.parse(MULTI_ADDRESSES_LIST); 389 390 assertEquals("multi addrsses count", MULTI_ADDRESSES_COUNT, addresses.length); 391 392 { 393 String line = Address.toString(address); 394 assertEquals("toString multi-1", 395 "noname1 (at) dom1.com", 396 line); 397 } 398 { 399 String line = Address.toString(addresses); 400 assertEquals("toString multi-n", 401 "noname1 (at) dom1.com," 402 + "noname2 (at) dom2.com," 403 + "simple name <address3 (at) dom3.org>," 404 + "\"name,4\" <address4 (at) dom4.org>," 405 + "\"big \"G\"\" <bigG (at) dom5.net>," 406 + "\u65E5\u672C\u8A9E <address6 (at) co.jp>," 407 + "\u65E5\u672C\u8A9E <address7 (at) co.jp>," 408 + "\uD834\uDF01\uD834\uDF46 <address8 (at) ne.jp>," 409 + "\uD834\uDF01\uD834\uDF46 <address9 (at) ne.jp>," 410 + "noname (at) dom.com", 411 line); 412 } 413 414 // With custom separator 415 { 416 String line = Address.toString(address, "$"); 417 assertEquals("toString multi-1", 418 "noname1 (at) dom1.com", 419 line); 420 } 421 422 { 423 String line = Address.toString(addresses, "$"); 424 assertEquals("toString multi-n", 425 "noname1 (at) dom1.com$" 426 + "noname2 (at) dom2.com$" 427 + "simple name <address3 (at) dom3.org>$" 428 + "\"name,4\" <address4 (at) dom4.org>$" 429 + "\"big \"G\"\" <bigG (at) dom5.net>$" 430 + "\u65E5\u672C\u8A9E <address6 (at) co.jp>$" 431 + "\u65E5\u672C\u8A9E <address7 (at) co.jp>$" 432 + "\uD834\uDF01\uD834\uDF46 <address8 (at) ne.jp>$" 433 + "\uD834\uDF01\uD834\uDF46 <address9 (at) ne.jp>$" 434 + "noname (at) dom.com", 435 line); 436 } 437 } 438 439 /** 440 * Test parsing for quoted and encoded name part. 441 */ 442 public void testParsingQuotedEncodedName() { 443 Address[] addresses = Address.parse( 444 "\"big \\\"G\\\"\" <bigG (at) dom1.com>, =?UTF-8?B?5pel5pys6Kqe?= <address2 (at) co.jp>"); 445 446 assertEquals("address count", 2, addresses.length); 447 448 assertEquals("quoted name address", "bigG (at) dom1.com", addresses[0].getAddress()); 449 assertEquals("quoted name", "big \"G\"", addresses[0].getPersonal()); 450 451 assertEquals("encoded name address", "address2 (at) co.jp", addresses[1].getAddress()); 452 assertEquals("encoded name", "\u65E5\u672C\u8A9E", addresses[1].getPersonal()); 453 } 454 455 /** 456 * Test various combinations of the toHeader (single) method 457 */ 458 public void testToHeaderSingle() { 459 Address noName1 = new Address("noname1 (at) dom1.com"); 460 Address noName2 = new Address("<noname2 (at) dom2.com>", ""); 461 Address simpleName = new Address("address3 (at) dom3.org", "simple name"); 462 Address dquoteName = new Address("address4 (at) dom4.org", "name,4"); 463 Address quotedName = new Address("bigG (at) dom5.net", "big \"G\""); 464 Address utf16Name = new Address("<address6 (at) co.jp>", "\"\u65E5\u672C\u8A9E\""); 465 Address utf32Name = new Address("<address8 (at) ne.jp>", "\uD834\uDF01\uD834\uDF46"); 466 Address sameName = new Address("address (at) dom.org", "address (at) dom.org"); 467 468 // test for internal states. 469 assertEquals("no name 1 address", "noname1 (at) dom1.com", noName1.getAddress()); 470 assertNull("no name 1 name", noName1.getPersonal()); 471 assertEquals("no name 2 address", "noname2 (at) dom2.com", noName2.getAddress()); 472 assertNull("no name 2 name", noName2.getPersonal()); 473 assertEquals("simple name address", "address3 (at) dom3.org", simpleName.getAddress()); 474 assertEquals("simple name name", "simple name", simpleName.getPersonal()); 475 assertEquals("double quoted name address", "address4 (at) dom4.org", dquoteName.getAddress()); 476 assertEquals("double quoted name name", "name,4", dquoteName.getPersonal()); 477 assertEquals("quoted name address", "bigG (at) dom5.net", quotedName.getAddress()); 478 assertEquals("quoted name name", "big \"G\"", quotedName.getPersonal()); 479 assertEquals("utf-16 name address", "address6 (at) co.jp", utf16Name.getAddress()); 480 assertEquals("utf-16 name name", "\u65E5\u672C\u8A9E", utf16Name.getPersonal()); 481 assertEquals("utf-32 name address", "address8 (at) ne.jp", utf32Name.getAddress()); 482 assertEquals("utf-32 name name", "\uD834\uDF01\uD834\uDF46", utf32Name.getPersonal()); 483 assertEquals("name == address address", "address (at) dom.org", sameName.getAddress()); 484 assertEquals("name == address name", "address (at) dom.org", sameName.getPersonal()); 485 486 // Test for toHeader() results. 487 assertEquals("no name 1", "noname1 (at) dom1.com", noName1.toHeader()); 488 assertEquals("no name 2", "noname2 (at) dom2.com", noName2.toHeader()); 489 assertEquals("simple name", "simple name <address3 (at) dom3.org>", simpleName.toHeader()); 490 assertEquals("double quoted name", "\"name,4\" <address4 (at) dom4.org>", dquoteName.toHeader()); 491 assertEquals("quoted name", "\"big \\\"G\\\"\" <bigG (at) dom5.net>", quotedName.toHeader()); 492 assertEquals("utf-16 name", "=?UTF-8?B?5pel5pys6Kqe?= <address6 (at) co.jp>", 493 utf16Name.toHeader()); 494 assertEquals("utf-32 name", "=?UTF-8?B?8J2MgfCdjYY=?= <address8 (at) ne.jp>", 495 utf32Name.toHeader()); 496 assertEquals("name == address", "\"address (at) dom.org\" <address (at) dom.org>", 497 sameName.toHeader()); 498 } 499 500 /** 501 * Test various combinations of the toHeader (multi) method 502 */ 503 public void testToHeaderMulti() { 504 Address noName1 = new Address("noname1 (at) dom1.com"); 505 Address noName2 = new Address("<noname2 (at) dom2.com>", ""); 506 Address simpleName = new Address("address3 (at) dom3.org", "simple name"); 507 Address dquoteName = new Address("address4 (at) dom4.org", "name,4"); 508 Address quotedName = new Address("bigG (at) dom5.net", "big \"G\""); 509 Address utf16Name = new Address("<address6 (at) co.jp>", "\"\u65E5\u672C\u8A9E\""); 510 Address utf32Name = new Address("<address8 (at) ne.jp>", "\uD834\uDF01\uD834\uDF46"); 511 512 // test for internal states. 513 assertEquals("no name 1 address", "noname1 (at) dom1.com", noName1.getAddress()); 514 assertNull("no name 1 name", noName1.getPersonal()); 515 assertEquals("no name 2 address", "noname2 (at) dom2.com", noName2.getAddress()); 516 assertNull("no name 2 name", noName2.getPersonal()); 517 assertEquals("simple name address", "address3 (at) dom3.org", simpleName.getAddress()); 518 assertEquals("simple name name", "simple name", simpleName.getPersonal()); 519 assertEquals("double quoted name address", "address4 (at) dom4.org", dquoteName.getAddress()); 520 assertEquals("double quoted name name", "name,4", dquoteName.getPersonal()); 521 assertEquals("quoted name address", "bigG (at) dom5.net", quotedName.getAddress()); 522 assertEquals("quoted name name", "big \"G\"", quotedName.getPersonal()); 523 assertEquals("utf-16 name address", "address6 (at) co.jp", utf16Name.getAddress()); 524 assertEquals("utf-16 name name", "\u65E5\u672C\u8A9E", utf16Name.getPersonal()); 525 assertEquals("utf-32 name address", "address8 (at) ne.jp", utf32Name.getAddress()); 526 assertEquals("utf-32 name name", "\uD834\uDF01\uD834\uDF46", utf32Name.getPersonal()); 527 528 Address[] addresses = new Address[] { 529 noName1, noName2, simpleName, dquoteName, quotedName, utf16Name, utf32Name, 530 }; 531 String line = Address.toHeader(addresses); 532 533 assertEquals("toHeader() multi", 534 "noname1 (at) dom1.com, " 535 + "noname2 (at) dom2.com, " 536 + "simple name <address3 (at) dom3.org>, " 537 + "\"name,4\" <address4 (at) dom4.org>, " 538 + "\"big \\\"G\\\"\" <bigG (at) dom5.net>, " 539 + "=?UTF-8?B?5pel5pys6Kqe?= <address6 (at) co.jp>, " 540 + "=?UTF-8?B?8J2MgfCdjYY=?= <address8 (at) ne.jp>", 541 line); 542 } 543 544 /** 545 * Test various combinations of the toFriendly (single) method 546 */ 547 public void testToFriendlySingle() { 548 assertEquals("personal1", mAddress1.toFriendly()); 549 assertEquals("address2", mAddress2.toFriendly()); 550 assertEquals("address3", mAddress3.toFriendly()); 551 } 552 553 /** 554 * Test various combinations of the toFriendly (array) method 555 */ 556 public void testToFriendlyArray() { 557 Address[] list1 = null; 558 Address[] list2 = new Address[0]; 559 Address[] list3 = new Address[] { mAddress1 }; 560 Address[] list4 = new Address[] { mAddress1, mAddress2, mAddress3 }; 561 562 assertEquals(null, Address.toFriendly(list1)); 563 assertEquals(null, Address.toFriendly(list2)); 564 assertEquals("personal1", Address.toFriendly(list3)); 565 assertEquals("personal1, address2, address3", Address.toFriendly(list4)); 566 } 567 568 /** 569 * Simple quick checks of empty-input edge conditions for pack() 570 * 571 * NOTE: This is not a claim that these edge cases are "correct", only to maintain consistent 572 * behavior while I am changing some of the code in the function under test. 573 */ 574 public void testEmptyToHeader() { 575 String result; 576 577 // null input => null string 578 result = Address.toHeader(null); 579 assertNull("packing null", result); 580 581 // zero-length input => null string 582 result = Address.toHeader(new Address[] { }); 583 assertNull("packing empty array", result); 584 } 585 586 /** 587 * Simple quick checks of empty-input edge conditions for fromHeader() 588 * 589 * NOTE: This is not a claim that these edge cases are "correct", only to maintain consistent 590 * behavior while I am changing some of the code in the function under test. 591 */ 592 public void testEmptyFromHeader() { 593 Address[] result; 594 595 /* 596 // null input => empty array 597 result = Address.fromHeader(null); 598 assertTrue("unpacking null address", result != null && result.length == 0); 599 */ 600 // empty string input => empty array 601 result = Address.fromHeader(""); 602 assertTrue("unpacking zero-length", result != null && result.length == 0); 603 } 604 605 private static boolean addressEquals(Address a1, Address a2) { 606 if (!a1.equals(a2)) { 607 return false; 608 } 609 final String displayName1 = a1.getPersonal(); 610 final String displayName2 = a2.getPersonal(); 611 if (displayName1 == null) { 612 return displayName2 == null; 613 } else { 614 return displayName1.equals(displayName2); 615 } 616 } 617 618 private static boolean addressArrayEquals(Address[] array1, Address[] array2) { 619 if (array1.length != array2.length) { 620 return false; 621 } 622 for (int i = array1.length - 1; i >= 0; --i) { 623 if (!addressEquals(array1[i], array2[i])) { 624 return false; 625 } 626 } 627 return true; 628 } 629 630 public void testToHeaderFromHeader() { 631 for (Address[] list : TO_HEADER_CASES) { 632 String packed = Address.toHeader(list); 633 assertTrue(packed, addressArrayEquals(list, Address.fromHeader(packed))); 634 } 635 } 636 637 /** 638 * Tests that fromHeaderToString() returns the same result as toString(fromHeader()). 639 */ 640 public void testFromHeaderToString() { 641 assertNull(Address.fromHeaderToString(null)); 642 assertNull(Address.fromHeaderToString("")); 643 644 for (Address[] list : TO_HEADER_CASES) { 645 String packed = Address.toHeader(list); 646 String s1 = Address.fromHeaderToString(packed); 647 String s2 = Address.toString(Address.fromHeader(packed)); 648 assertEquals(s2, s2, s1); 649 } 650 } 651 652 /** 653 * Tests that parseToHeader() returns the same result as toHeader(parse()). 654 */ 655 public void testParseAndPack() { 656 String s1 = Address.parseToHeader(MULTI_ADDRESSES_LIST); 657 String s2 = Address.toHeader(Address.parse(MULTI_ADDRESSES_LIST)); 658 assertEquals(s2, s1); 659 } 660 661 public void testSinglePack() { 662 Address[] addrArray = new Address[1]; 663 for (Address address : new Address[]{ADDR_1, ADDR_2, ADDR_3}) { 664 String packed1 = address.toHeader(); 665 addrArray[0] = address; 666 String packed2 = Address.toHeader(addrArray); 667 assertEquals(packed1, packed2); 668 } 669 } 670 671 /** 672 * Tests that: 673 * 1. firstAddress() with empty list returns null. 674 * 2. firstAddress() with non-empty returns the same as fromHeader()[0] 675 */ 676 public void testFirstAddress() { 677 assertNull(Address.firstAddress(null)); 678 assertNull(Address.firstAddress("")); 679 680 for (Address[] list : TO_HEADER_CASES) { 681 String packed = Address.toHeader(list); 682 Address[] array = Address.fromHeader(packed); 683 Address first = Address.firstAddress(packed); 684 assertTrue(packed, addressEquals(array[0], first)); 685 } 686 } 687 688 public void testIsValidAddress() { 689 String notValid[] = {"", "foo", "john@", "x@y", "x@y.", "foo.com"}; 690 String valid[] = {"x (at) y.z", "john (at) gmail.com", "a (at) b.c.d"}; 691 for (String address : notValid) { 692 assertTrue(address, !Address.isValidAddress(address)); 693 } 694 for (String address : valid) { 695 assertTrue(address, Address.isValidAddress(address)); 696 } 697 698 // isAllValid() must accept empty address list as valid 699 assertTrue("Empty address list is valid", Address.isAllValid("")); 700 } 701 } 702