credit_card_unittest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/basictypes.h"
6#include "base/guid.h"
7#include "base/strings/utf_string_conversions.h"
8#include "components/autofill/core/browser/autofill_common_test.h"
9#include "components/autofill/core/browser/credit_card.h"
10#include "components/autofill/core/browser/validation.h"
11#include "components/autofill/core/common/form_field_data.h"
12#include "grit/webkit_resources.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace autofill {
16namespace {
17
18// From https://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
19const char* const kValidNumbers[] = {
20  "378282246310005",
21  "3714 4963 5398 431",
22  "3787-3449-3671-000",
23  "5610591081018250",
24  "3056 9309 0259 04",
25  "3852-0000-0232-37",
26  "6011111111111117",
27  "6011 0009 9013 9424",
28  "3530-1113-3330-0000",
29  "3566002020360505",
30  "5555 5555 5555 4444",
31  "5105-1051-0510-5100",
32  "4111111111111111",
33  "4012 8888 8888 1881",
34  "4222-2222-2222-2",
35  "5019717010103742",
36  "6331101999990016",
37
38  // A UnionPay card that doesn't pass the Luhn checksum
39  "6200000000000000",
40};
41const char* const kInvalidNumbers[] = {
42  "4111 1111 112", /* too short */
43  "41111111111111111115", /* too long */
44  "4111-1111-1111-1110", /* wrong Luhn checksum */
45  "3056 9309 0259 04aa", /* non-digit characters */
46};
47
48}  // namespace
49
50// Tests credit card summary string generation.  This test simulates a variety
51// of different possible summary strings.  Variations occur based on the
52// existence of credit card number, month, and year fields.
53TEST(CreditCardTest, PreviewSummaryAndObfuscatedNumberStrings) {
54  // Case 0: empty credit card.
55  CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com/");
56  base::string16 summary0 = credit_card0.Label();
57  EXPECT_EQ(base::string16(), summary0);
58  base::string16 obfuscated0 = credit_card0.ObfuscatedNumber();
59  EXPECT_EQ(base::string16(), obfuscated0);
60
61  // Case 00: Empty credit card with empty strings.
62  CreditCard credit_card00(base::GenerateGUID(), "https://www.example.com/");
63  test::SetCreditCardInfo(&credit_card00,"John Dillinger", "", "", "");
64  base::string16 summary00 = credit_card00.Label();
65  EXPECT_EQ(base::string16(ASCIIToUTF16("John Dillinger")), summary00);
66  base::string16 obfuscated00 = credit_card00.ObfuscatedNumber();
67  EXPECT_EQ(base::string16(), obfuscated00);
68
69  // Case 1: No credit card number.
70  CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com/");
71  test::SetCreditCardInfo(&credit_card1,"John Dillinger", "", "01", "2010");
72  base::string16 summary1 = credit_card1.Label();
73  EXPECT_EQ(base::string16(ASCIIToUTF16("John Dillinger")), summary1);
74  base::string16 obfuscated1 = credit_card1.ObfuscatedNumber();
75  EXPECT_EQ(base::string16(), obfuscated1);
76
77  // Case 2: No month.
78  CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com/");
79  test::SetCreditCardInfo(
80      &credit_card2, "John Dillinger", "5105 1051 0510 5100", "", "2010");
81  base::string16 summary2 = credit_card2.Label();
82  EXPECT_EQ(ASCIIToUTF16("************5100"), summary2);
83  base::string16 obfuscated2 = credit_card2.ObfuscatedNumber();
84  EXPECT_EQ(ASCIIToUTF16("************5100"), obfuscated2);
85
86  // Case 3: No year.
87  CreditCard credit_card3(base::GenerateGUID(), "https://www.example.com/");
88  test::SetCreditCardInfo(
89      &credit_card3, "John Dillinger", "5105 1051 0510 5100", "01", "");
90  base::string16 summary3 = credit_card3.Label();
91  EXPECT_EQ(ASCIIToUTF16("************5100"), summary3);
92  base::string16 obfuscated3 = credit_card3.ObfuscatedNumber();
93  EXPECT_EQ(ASCIIToUTF16("************5100"), obfuscated3);
94
95  // Case 4: Have everything.
96  CreditCard credit_card4(base::GenerateGUID(), "https://www.example.com/");
97  test::SetCreditCardInfo(
98      &credit_card4, "John Dillinger", "5105 1051 0510 5100", "01", "2010");
99  base::string16 summary4 = credit_card4.Label();
100  EXPECT_EQ(ASCIIToUTF16("************5100, Exp: 01/2010"), summary4);
101  base::string16 obfuscated4 = credit_card4.ObfuscatedNumber();
102  EXPECT_EQ(ASCIIToUTF16("************5100"), obfuscated4);
103
104  // Case 5: Very long credit card
105  CreditCard credit_card5(base::GenerateGUID(), "https://www.example.com/");
106  test::SetCreditCardInfo(
107      &credit_card5,
108      "John Dillinger",
109      "0123456789 0123456789 0123456789 5105 1051 0510 5100", "01", "2010");
110  base::string16 summary5 = credit_card5.Label();
111  EXPECT_EQ(ASCIIToUTF16("********************5100, Exp: 01/2010"), summary5);
112  base::string16 obfuscated5 = credit_card5.ObfuscatedNumber();
113  EXPECT_EQ(ASCIIToUTF16("********************5100"), obfuscated5);
114}
115
116TEST(CreditCardTest, AssignmentOperator) {
117  CreditCard a(base::GenerateGUID(), "some origin");
118  test::SetCreditCardInfo(&a, "John Dillinger", "123456789012", "01", "2010");
119
120  // Result of assignment should be logically equal to the original profile.
121  CreditCard b(base::GenerateGUID(), "some other origin");
122  b = a;
123  EXPECT_TRUE(a == b);
124
125  // Assignment to self should not change the profile value.
126  a = a;
127  EXPECT_TRUE(a == b);
128}
129
130TEST(CreditCardTest, Copy) {
131  CreditCard a(base::GenerateGUID(), "https://www.example.com");
132  test::SetCreditCardInfo(&a, "John Dillinger", "123456789012", "01", "2010");
133
134  // Clone should be logically equal to the original.
135  CreditCard b(a);
136  EXPECT_TRUE(a == b);
137}
138
139TEST(CreditCardTest, Compare) {
140  CreditCard a(base::GenerateGUID(), std::string());
141  CreditCard b(base::GenerateGUID(), std::string());
142
143  // Empty cards are the same.
144  EXPECT_EQ(0, a.Compare(b));
145
146  // GUIDs don't count.
147  a.set_guid(base::GenerateGUID());
148  b.set_guid(base::GenerateGUID());
149  EXPECT_EQ(0, a.Compare(b));
150
151  // Origins don't count.
152  a.set_origin("apple");
153  b.set_origin("banana");
154  EXPECT_EQ(0, a.Compare(b));
155
156  // Different values produce non-zero results.
157  test::SetCreditCardInfo(&a, "Jimmy", NULL, NULL, NULL);
158  test::SetCreditCardInfo(&b, "Ringo", NULL, NULL, NULL);
159  EXPECT_GT(0, a.Compare(b));
160  EXPECT_LT(0, b.Compare(a));
161}
162
163// Test we get the correct icon for each card type.
164TEST(CreditCardTest, IconResourceId) {
165  EXPECT_EQ(IDR_AUTOFILL_CC_AMEX,
166            CreditCard::IconResourceId(kAmericanExpressCard));
167  EXPECT_EQ(IDR_AUTOFILL_CC_DINERS,
168            CreditCard::IconResourceId(kDinersCard));
169  EXPECT_EQ(IDR_AUTOFILL_CC_DISCOVER,
170            CreditCard::IconResourceId(kDiscoverCard));
171  EXPECT_EQ(IDR_AUTOFILL_CC_JCB,
172            CreditCard::IconResourceId(kJCBCard));
173  EXPECT_EQ(IDR_AUTOFILL_CC_MASTERCARD,
174            CreditCard::IconResourceId(kMasterCard));
175  EXPECT_EQ(IDR_AUTOFILL_CC_VISA,
176            CreditCard::IconResourceId(kVisaCard));
177}
178
179TEST(CreditCardTest, UpdateFromImportedCard) {
180  CreditCard original_card(base::GenerateGUID(), "https://www.example.com");
181  test::SetCreditCardInfo(
182      &original_card, "John Dillinger", "123456789012", "09", "2017");
183
184  CreditCard a = original_card;
185
186  // The new card has a different name, expiration date, and origin.
187  CreditCard b = a;
188  b.set_guid(base::GenerateGUID());
189  b.set_origin("https://www.example.org");
190  b.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("J. Dillinger"));
191  b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08"));
192  b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019"));
193
194  EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
195  EXPECT_EQ("https://www.example.org", a.origin());
196  EXPECT_EQ(ASCIIToUTF16("J. Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME));
197  EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
198  EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
199
200  // Try again, but with no name set for |b|.
201  a = original_card;
202  b.SetRawInfo(CREDIT_CARD_NAME, base::string16());
203
204  EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
205  EXPECT_EQ("https://www.example.org", a.origin());
206  EXPECT_EQ(ASCIIToUTF16("John Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME));
207  EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
208  EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
209
210  // Try again, but with only the original card having a verified origin.
211  // |a| should be unchanged.
212  a = original_card;
213  a.set_origin("Chrome settings");
214  b.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("J. Dillinger"));
215
216  EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
217  EXPECT_EQ("Chrome settings", a.origin());
218  EXPECT_EQ(ASCIIToUTF16("John Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME));
219  EXPECT_EQ(ASCIIToUTF16("09"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
220  EXPECT_EQ(ASCIIToUTF16("2017"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
221
222  // Try again, but with only the new card having a verified origin.
223  a = original_card;
224  b.set_origin("Chrome settings");
225
226  EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
227  EXPECT_EQ("Chrome settings", a.origin());
228  EXPECT_EQ(ASCIIToUTF16("J. Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME));
229  EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
230  EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
231
232  // Try again, with both cards having a verified origin.
233  a = original_card;
234  a.set_origin("Chrome Autofill dialog");
235  b.set_origin("Chrome settings");
236
237  EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
238  EXPECT_EQ("Chrome settings", a.origin());
239  EXPECT_EQ(ASCIIToUTF16("J. Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME));
240  EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
241  EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
242
243  // Try again, but with |b| having a different card number.
244  // |a| should be unchanged.
245  a = original_card;
246  b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
247
248  EXPECT_FALSE(a.UpdateFromImportedCard(b, "en-US"));
249  EXPECT_EQ(original_card, a);
250}
251
252TEST(CreditCardTest, IsComplete) {
253  CreditCard card(base::GenerateGUID(), "https://www.example.com/");
254  EXPECT_FALSE(card.IsComplete());
255  card.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("Wally T. Walrus"));
256  EXPECT_FALSE(card.IsComplete());
257  card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("01"));
258  EXPECT_FALSE(card.IsComplete());
259  card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2014"));
260
261  for (size_t i = 0; i < arraysize(kValidNumbers); ++i) {
262    SCOPED_TRACE(kValidNumbers[i]);
263    card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16(kValidNumbers[i]));
264    EXPECT_TRUE(card.IsComplete());
265  }
266  for (size_t i = 0; i < arraysize(kInvalidNumbers); ++i) {
267    SCOPED_TRACE(kInvalidNumbers[i]);
268    card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16(kInvalidNumbers[i]));
269    EXPECT_FALSE(card.IsComplete());
270  }
271}
272
273TEST(CreditCardTest, IsValid) {
274  CreditCard card;
275  // Invalid because expired
276  card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("1"));
277  card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2010"));
278  card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
279  EXPECT_FALSE(card.IsValid());
280
281  // Invalid because card number is not complete
282  card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("12"));
283  card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("9999"));
284  card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("41111"));
285  EXPECT_FALSE(card.IsValid());
286
287  // Valid
288  card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("12"));
289  card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("9999"));
290  card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
291  EXPECT_TRUE(card.IsValid());
292}
293
294TEST(CreditCardTest, InvalidMastercardNumber) {
295  CreditCard card(base::GenerateGUID(), "https://www.example.com/");
296
297  test::SetCreditCardInfo(&card, "Baby Face Nelson",
298                          "5200000000000004", "01", "2010");
299  EXPECT_EQ(kMasterCard, card.type());
300  EXPECT_FALSE(card.IsComplete());
301}
302
303// Verify that we preserve exactly what the user typed for credit card numbers.
304TEST(CreditCardTest, SetRawInfoCreditCardNumber) {
305  CreditCard card(base::GenerateGUID(), "https://www.example.com/");
306
307  test::SetCreditCardInfo(&card, "Bob Dylan",
308                          "4321-5432-6543-xxxx", "07", "2013");
309  EXPECT_EQ(ASCIIToUTF16("4321-5432-6543-xxxx"),
310            card.GetRawInfo(CREDIT_CARD_NUMBER));
311}
312
313// Verify that we can handle both numeric and named months.
314TEST(CreditCardTest, SetExpirationMonth) {
315  CreditCard card(base::GenerateGUID(), "https://www.example.com/");
316
317  card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("05"));
318  EXPECT_EQ(ASCIIToUTF16("05"), card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
319  EXPECT_EQ(5, card.expiration_month());
320
321  card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("7"));
322  EXPECT_EQ(ASCIIToUTF16("07"), card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
323  EXPECT_EQ(7, card.expiration_month());
324
325  // This should fail, and preserve the previous value.
326  card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("January"));
327  EXPECT_EQ(ASCIIToUTF16("07"), card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
328  EXPECT_EQ(7, card.expiration_month());
329
330  card.SetInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("January"), "en-US");
331  EXPECT_EQ(ASCIIToUTF16("01"), card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
332  EXPECT_EQ(1, card.expiration_month());
333
334  card.SetInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("Apr"), "en-US");
335  EXPECT_EQ(ASCIIToUTF16("04"), card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
336  EXPECT_EQ(4, card.expiration_month());
337}
338
339TEST(CreditCardTest, CreditCardType) {
340  CreditCard card(base::GenerateGUID(), "https://www.example.com/");
341
342  // The card type cannot be set directly.
343  card.SetRawInfo(CREDIT_CARD_TYPE, ASCIIToUTF16("Visa"));
344  EXPECT_EQ(base::string16(), card.GetRawInfo(CREDIT_CARD_TYPE));
345
346  // Setting the number should implicitly set the type.
347  card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111 1111 1111 1111"));
348  EXPECT_EQ(ASCIIToUTF16("Visa"), card.GetRawInfo(CREDIT_CARD_TYPE));
349}
350
351TEST(CreditCardTest, CreditCardVerificationCode) {
352  CreditCard card(base::GenerateGUID(), "https://www.example.com/");
353
354  // The verification code cannot be set, as Chrome does not store this data.
355  card.SetRawInfo(CREDIT_CARD_VERIFICATION_CODE, ASCIIToUTF16("999"));
356  EXPECT_EQ(base::string16(), card.GetRawInfo(CREDIT_CARD_VERIFICATION_CODE));
357}
358
359
360TEST(CreditCardTest, CreditCardMonthExact) {
361  const char* const kMonthsNumeric[] = {
362    "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12",
363  };
364  std::vector<base::string16> options(arraysize(kMonthsNumeric));
365  for (size_t i = 0; i < arraysize(kMonthsNumeric); ++i) {
366    options[i] = ASCIIToUTF16(kMonthsNumeric[i]);
367  }
368
369  FormFieldData field;
370  field.form_control_type = "select-one";
371  field.option_values = options;
372  field.option_contents = options;
373
374  CreditCard credit_card(base::GenerateGUID(), "https://www.example.com/");
375  credit_card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("01"));
376  credit_card.FillSelectControl(CREDIT_CARD_EXP_MONTH, "en-US", &field);
377  EXPECT_EQ(ASCIIToUTF16("01"), field.value);
378}
379
380TEST(CreditCardTest, CreditCardMonthAbbreviated) {
381  const char* const kMonthsAbbreviated[] = {
382    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
383    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
384  };
385  std::vector<base::string16> options(arraysize(kMonthsAbbreviated));
386  for (size_t i = 0; i < arraysize(kMonthsAbbreviated); ++i) {
387    options[i] = ASCIIToUTF16(kMonthsAbbreviated[i]);
388  }
389
390  FormFieldData field;
391  field.form_control_type = "select-one";
392  field.option_values = options;
393  field.option_contents = options;
394
395  CreditCard credit_card(base::GenerateGUID(), "https://www.example.com/");
396  credit_card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("01"));
397  credit_card.FillSelectControl(CREDIT_CARD_EXP_MONTH, "en-US", &field);
398  EXPECT_EQ(ASCIIToUTF16("Jan"), field.value);
399}
400
401TEST(CreditCardTest, CreditCardMonthFull) {
402  const char* const kMonthsFull[] = {
403    "January", "February", "March", "April", "May", "June",
404    "July", "August", "September", "October", "November", "December",
405  };
406  std::vector<base::string16> options(arraysize(kMonthsFull));
407  for (size_t i = 0; i < arraysize(kMonthsFull); ++i) {
408    options[i] = ASCIIToUTF16(kMonthsFull[i]);
409  }
410
411  FormFieldData field;
412  field.form_control_type = "select-one";
413  field.option_values = options;
414  field.option_contents = options;
415
416  CreditCard credit_card(base::GenerateGUID(), "https://www.example.com/");
417  credit_card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("01"));
418  credit_card.FillSelectControl(CREDIT_CARD_EXP_MONTH, "en-US", &field);
419  EXPECT_EQ(ASCIIToUTF16("January"), field.value);
420}
421
422TEST(CreditCardTest, CreditCardMonthNumeric) {
423  const char* const kMonthsNumeric[] = {
424    "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
425  };
426  std::vector<base::string16> options(arraysize(kMonthsNumeric));
427  for (size_t i = 0; i < arraysize(kMonthsNumeric); ++i) {
428    options[i] = ASCIIToUTF16(kMonthsNumeric[i]);
429  }
430
431  FormFieldData field;
432  field.form_control_type = "select-one";
433  field.option_values = options;
434  field.option_contents = options;
435
436  CreditCard credit_card(base::GenerateGUID(), "https://www.example.com/");
437  credit_card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("01"));
438  credit_card.FillSelectControl(CREDIT_CARD_EXP_MONTH, "en-US", &field);
439  EXPECT_EQ(ASCIIToUTF16("1"), field.value);
440}
441
442TEST(CreditCardTest, CreditCardTwoDigitYear) {
443  const char* const kYears[] = {
444    "12", "13", "14", "15", "16", "17", "18", "19"
445  };
446  std::vector<base::string16> options(arraysize(kYears));
447  for (size_t i = 0; i < arraysize(kYears); ++i) {
448    options[i] = ASCIIToUTF16(kYears[i]);
449  }
450
451  FormFieldData field;
452  field.form_control_type = "select-one";
453  field.option_values = options;
454  field.option_contents = options;
455
456  CreditCard credit_card(base::GenerateGUID(), "https://www.example.com/");
457  credit_card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2017"));
458  credit_card.FillSelectControl(CREDIT_CARD_EXP_4_DIGIT_YEAR, "en-US", &field);
459  EXPECT_EQ(ASCIIToUTF16("17"), field.value);
460  EXPECT_EQ(2017, credit_card.expiration_year());
461}
462
463TEST(CreditCardTest, CreditCardTypeSelectControl) {
464  const char* const kCreditCardTypes[] = {
465    "Visa", "Master Card", "AmEx", "discover"
466  };
467  std::vector<base::string16> options(arraysize(kCreditCardTypes));
468  for (size_t i = 0; i < arraysize(kCreditCardTypes); ++i) {
469    options[i] = ASCIIToUTF16(kCreditCardTypes[i]);
470  }
471
472  FormFieldData field;
473  field.form_control_type = "select-one";
474  field.option_values = options;
475  field.option_contents = options;
476
477  // Credit card types are inferred from the numbers, so we use test numbers for
478  // each card type. Test card numbers are drawn from
479  // http://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
480
481  {
482    // Normal case:
483    CreditCard credit_card(base::GenerateGUID(), "https://www.example.com/");
484    credit_card.SetRawInfo(CREDIT_CARD_NUMBER,
485                           ASCIIToUTF16("4111111111111111"));
486    credit_card.FillSelectControl(CREDIT_CARD_TYPE, "en-US", &field);
487    EXPECT_EQ(ASCIIToUTF16("Visa"), field.value);
488  }
489
490  {
491    // Filling should be able to handle intervening whitespace:
492    CreditCard credit_card(base::GenerateGUID(), "https://www.example.com/");
493    credit_card.SetRawInfo(CREDIT_CARD_NUMBER,
494                           ASCIIToUTF16("5105105105105100"));
495    credit_card.FillSelectControl(CREDIT_CARD_TYPE, "en-US", &field);
496    EXPECT_EQ(ASCIIToUTF16("Master Card"), field.value);
497  }
498
499  {
500    // American Express is sometimes abbreviated as AmEx:
501    CreditCard credit_card(base::GenerateGUID(), "https://www.example.com/");
502    credit_card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("371449635398431"));
503    credit_card.FillSelectControl(CREDIT_CARD_TYPE, "en-US", &field);
504    EXPECT_EQ(ASCIIToUTF16("AmEx"), field.value);
505  }
506
507  {
508    // Case insensitivity:
509    CreditCard credit_card(base::GenerateGUID(), "https://www.example.com/");
510    credit_card.SetRawInfo(CREDIT_CARD_NUMBER,
511                           ASCIIToUTF16("6011111111111117"));
512    credit_card.FillSelectControl(CREDIT_CARD_TYPE, "en-US", &field);
513    EXPECT_EQ(ASCIIToUTF16("discover"), field.value);
514  }
515}
516
517TEST(CreditCardTest, GetCreditCardType) {
518  struct {
519    std::string card_number;
520    std::string type;
521    bool is_valid;
522  } test_cases[] = {
523    // The relevant sample numbers from
524    // http://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
525    { "378282246310005", kAmericanExpressCard, true },
526    { "371449635398431", kAmericanExpressCard, true },
527    { "378734493671000", kAmericanExpressCard, true },
528    { "30569309025904", kDinersCard, true },
529    { "38520000023237", kDinersCard, true },
530    { "6011111111111117", kDiscoverCard, true },
531    { "6011000990139424", kDiscoverCard, true },
532    { "3530111333300000", kJCBCard, true },
533    { "3566002020360505", kJCBCard, true },
534    { "5555555555554444", kMasterCard, true },
535    { "5105105105105100", kMasterCard, true },
536    { "4111111111111111", kVisaCard, true },
537    { "4012888888881881", kVisaCard, true },
538    { "4222222222222", kVisaCard, true },
539
540    // The relevant sample numbers from
541    // http://auricsystems.com/support-center/sample-credit-card-numbers/
542    { "343434343434343", kAmericanExpressCard, true },
543    { "371144371144376", kAmericanExpressCard, true },
544    { "341134113411347", kAmericanExpressCard, true },
545    { "36438936438936", kDinersCard, true },
546    { "36110361103612", kDinersCard, true },
547    { "36111111111111", kDinersCard, true },
548    { "6011016011016011", kDiscoverCard, true },
549    { "6011000990139424", kDiscoverCard, true },
550    { "6011000000000004", kDiscoverCard, true },
551    { "6011000995500000", kDiscoverCard, true },
552    { "6500000000000002", kDiscoverCard, true },
553    { "3566002020360505", kJCBCard, true },
554    { "3528000000000007", kJCBCard, true },
555    { "5500005555555559", kMasterCard, true },
556    { "5555555555555557", kMasterCard, true },
557    { "5454545454545454", kMasterCard, true },
558    { "5555515555555551", kMasterCard, true },
559    { "5405222222222226", kMasterCard, true },
560    { "5478050000000007", kMasterCard, true },
561    { "5111005111051128", kMasterCard, true },
562    { "5112345112345114", kMasterCard, true },
563    { "5115915115915118", kMasterCard, true },
564
565    // A UnionPay card that doesn't pass the Luhn checksum
566    { "6200000000000000", kUnionPay, true },
567
568    // Empty string
569    { std::string(), kGenericCard, false },
570
571    // Non-numeric
572    { "garbage", kGenericCard, false },
573    { "4garbage", kVisaCard, false },
574
575    // Fails Luhn check.
576    { "4111111111111112", kVisaCard, false },
577
578    // Invalid length.
579    { "3434343434343434", kAmericanExpressCard, false },
580    { "411111111111116", kVisaCard, false },
581
582    // Issuer Identification Numbers (IINs) that Chrome recognizes.
583    { "4", kVisaCard, false },
584    { "34", kAmericanExpressCard, false },
585    { "37", kAmericanExpressCard, false },
586    { "300", kDinersCard, false },
587    { "301", kDinersCard, false },
588    { "302", kDinersCard, false },
589    { "303", kDinersCard, false },
590    { "304", kDinersCard, false },
591    { "305", kDinersCard, false },
592    { "3095", kDinersCard, false },
593    { "36", kDinersCard, false },
594    { "38", kDinersCard, false },
595    { "39", kDinersCard, false },
596    { "6011", kDiscoverCard, false },
597    { "644", kDiscoverCard, false },
598    { "645", kDiscoverCard, false },
599    { "646", kDiscoverCard, false },
600    { "647", kDiscoverCard, false },
601    { "648", kDiscoverCard, false },
602    { "649", kDiscoverCard, false },
603    { "65", kDiscoverCard, false },
604    { "3528", kJCBCard, false },
605    { "3531", kJCBCard, false },
606    { "3589", kJCBCard, false },
607    { "51", kMasterCard, false },
608    { "52", kMasterCard, false },
609    { "53", kMasterCard, false },
610    { "54", kMasterCard, false },
611    { "55", kMasterCard, false },
612    { "62", kUnionPay, false },
613
614    // Not enough data to determine an IIN uniquely.
615    { "3", kGenericCard, false },
616    { "30", kGenericCard, false },
617    { "309", kGenericCard, false },
618    { "35", kGenericCard, false },
619    { "5", kGenericCard, false },
620    { "6", kGenericCard, false },
621    { "60", kGenericCard, false },
622    { "601", kGenericCard, false },
623    { "64", kGenericCard, false },
624
625    // Unknown IINs.
626    { "0", kGenericCard, false },
627    { "1", kGenericCard, false },
628    { "2", kGenericCard, false },
629    { "306", kGenericCard, false },
630    { "307", kGenericCard, false },
631    { "308", kGenericCard, false },
632    { "3091", kGenericCard, false },
633    { "3094", kGenericCard, false },
634    { "3096", kGenericCard, false },
635    { "31", kGenericCard, false },
636    { "32", kGenericCard, false },
637    { "33", kGenericCard, false },
638    { "351", kGenericCard, false },
639    { "3527", kGenericCard, false },
640    { "359", kGenericCard, false },
641    { "50", kGenericCard, false },
642    { "56", kGenericCard, false },
643    { "57", kGenericCard, false },
644    { "58", kGenericCard, false },
645    { "59", kGenericCard, false },
646    { "600", kGenericCard, false },
647    { "602", kGenericCard, false },
648    { "603", kGenericCard, false },
649    { "604", kGenericCard, false },
650    { "605", kGenericCard, false },
651    { "606", kGenericCard, false },
652    { "607", kGenericCard, false },
653    { "608", kGenericCard, false },
654    { "609", kGenericCard, false },
655    { "61", kGenericCard, false },
656    { "63", kGenericCard, false },
657    { "640", kGenericCard, false },
658    { "641", kGenericCard, false },
659    { "642", kGenericCard, false },
660    { "643", kGenericCard, false },
661    { "66", kGenericCard, false },
662    { "67", kGenericCard, false },
663    { "68", kGenericCard, false },
664    { "69", kGenericCard, false },
665    { "7", kGenericCard, false },
666    { "8", kGenericCard, false },
667    { "9", kGenericCard, false },
668
669    // Oddball case: Unknown issuer, but valid Luhn check and plausible length.
670    { "7000700070007000", kGenericCard, true },
671  };
672
673  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
674    base::string16 card_number = ASCIIToUTF16(test_cases[i].card_number);
675    SCOPED_TRACE(card_number);
676    EXPECT_EQ(test_cases[i].type, CreditCard::GetCreditCardType(card_number));
677    EXPECT_EQ(test_cases[i].is_valid, IsValidCreditCardNumber(card_number));
678  }
679}
680
681}  // namespace autofill
682