blob: 53095cf88856264541ab172615fc92a9afcead31 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include "base/guid.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/grit/components_scaled_resources.h"
#include "components/variations/variations_params_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
using base::UTF8ToUTF16;
namespace autofill {
const CreditCard::RecordType LOCAL_CARD = CreditCard::LOCAL_CARD;
const CreditCard::RecordType MASKED_SERVER_CARD =
CreditCard::MASKED_SERVER_CARD;
const CreditCard::RecordType FULL_SERVER_CARD = CreditCard::FULL_SERVER_CARD;
namespace {
// From https://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
const char* const kValidNumbers[] = {
"378282246310005",
"3714 4963 5398 431",
"3787-3449-3671-000",
"5610591081018250",
"3056 9309 0259 04",
"3852-0000-0232-37",
"6011111111111117",
"6011 0009 9013 9424",
"3530-1113-3330-0000",
"3566002020360505",
"5555 5555 5555 4444",
"5105-1051-0510-5100",
"4111111111111111",
"4012 8888 8888 1881",
"4222-2222-2222-2",
"5019717010103742",
"6331101999990016",
"6247130048162403",
"4532261615476013542",
"6362970000457013",
};
const char* const kInvalidNumbers[] = {
"4111 1111 112", /* too short */
"41111111111111111115", /* too long */
"4111-1111-1111-1110", /* wrong Luhn checksum */
"3056 9309 0259 04aa", /* non-digit characters */
};
} // namespace
TEST(CreditCardTest, GetObfuscatedStringForCardDigits) {
const base::string16 digits = base::ASCIIToUTF16("1235");
const base::string16 expected =
base::string16() + base::i18n::kLeftToRightEmbeddingMark +
kMidlineEllipsis + digits + base::i18n::kPopDirectionalFormatting;
EXPECT_EQ(expected, internal::GetObfuscatedStringForCardDigits(digits));
}
// Tests credit card summary string generation. This test simulates a variety
// of different possible summary strings. Variations occur based on the
// existence of credit card number, month, and year fields.
TEST(CreditCardTest, PreviewSummaryAndNetworkAndLastFourDigitsStrings) {
// Case 0: empty credit card.
CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com/");
base::string16 summary0 = credit_card0.Label();
EXPECT_EQ(base::string16(), summary0);
base::string16 obfuscated0 = credit_card0.NetworkAndLastFourDigits();
EXPECT_EQ(ASCIIToUTF16(std::string("Card")), obfuscated0);
// Case 00: Empty credit card with empty strings.
CreditCard credit_card00(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&credit_card00, "John Dillinger", "", "", "", "");
base::string16 summary00 = credit_card00.Label();
EXPECT_EQ(base::string16(ASCIIToUTF16("John Dillinger")), summary00);
base::string16 obfuscated00 = credit_card00.NetworkAndLastFourDigits();
EXPECT_EQ(ASCIIToUTF16(std::string("Card")), obfuscated00);
// Case 1: No credit card number.
CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&credit_card1, "John Dillinger", "", "01", "2010",
"1");
base::string16 summary1 = credit_card1.Label();
EXPECT_EQ(base::string16(ASCIIToUTF16("John Dillinger")), summary1);
base::string16 obfuscated1 = credit_card1.NetworkAndLastFourDigits();
EXPECT_EQ(ASCIIToUTF16(std::string("Card")), obfuscated1);
// Case 2: No month.
CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&credit_card2, "John Dillinger",
"5105 1051 0510 5100", "", "2010", "1");
base::string16 summary2 = credit_card2.Label();
EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("5100")),
summary2);
base::string16 obfuscated2 = credit_card2.NetworkAndLastFourDigits();
EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("5100")),
obfuscated2);
// Case 3: No year.
CreditCard credit_card3(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&credit_card3, "John Dillinger",
"5105 1051 0510 5100", "01", "", "1");
base::string16 summary3 = credit_card3.Label();
EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("5100")),
summary3);
base::string16 obfuscated3 = credit_card3.NetworkAndLastFourDigits();
EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("5100")),
obfuscated3);
// Case 4: Have everything.
CreditCard credit_card4(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&credit_card4, "John Dillinger",
"5105 1051 0510 5100", "01", "2010", "1");
base::string16 summary4 = credit_card4.Label();
EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("5100") + ", 01/2010"),
summary4);
base::string16 obfuscated4 = credit_card4.NetworkAndLastFourDigits();
EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("5100")),
obfuscated4);
// Case 5: Very long credit card
CreditCard credit_card5(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(
&credit_card5, "John Dillinger",
"0123456789 0123456789 0123456789 5105 1051 0510 5100", "01", "2010",
"1");
base::string16 summary5 = credit_card5.Label();
EXPECT_EQ(UTF8ToUTF16(std::string("Card ") +
test::ObfuscatedCardDigitsAsUTF8("5100") + ", 01/2010"),
summary5);
base::string16 obfuscated5 = credit_card5.NetworkAndLastFourDigits();
EXPECT_EQ(UTF8ToUTF16(std::string("Card ") +
test::ObfuscatedCardDigitsAsUTF8("5100")),
obfuscated5);
}
// Tests credit card bank name and last four digits string generation.
TEST(CreditCardTest, BankNameAndLastFourDigitsStrings) {
// Case 1: Have everything and show bank name.
CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&credit_card1, "John Dillinger",
"5105 1051 0510 5100", "01", "2010", "1");
credit_card1.set_bank_name("Chase");
base::string16 obfuscated1 = credit_card1.BankNameAndLastFourDigits();
EXPECT_FALSE(credit_card1.bank_name().empty());
EXPECT_EQ(UTF8ToUTF16(std::string("Chase ") +
test::ObfuscatedCardDigitsAsUTF8("5100")),
obfuscated1);
// Case 2: Have no bank name and not show bank name.
CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&credit_card2, "John Dillinger",
"5105 1051 0510 5100", "01", "2010", "1");
base::string16 obfuscated2 = credit_card2.BankNameAndLastFourDigits();
EXPECT_TRUE(credit_card2.bank_name().empty());
EXPECT_EQ(
internal::GetObfuscatedStringForCardDigits(base::ASCIIToUTF16("5100")),
obfuscated2);
// Case 3: Have bank name but no last four digits, only show bank name.
CreditCard credit_card3(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&credit_card3, "John Dillinger", "", "01", "2010",
"1");
credit_card3.set_bank_name("Chase");
base::string16 obfuscated3 = credit_card3.BankNameAndLastFourDigits();
EXPECT_FALSE(credit_card3.bank_name().empty());
EXPECT_EQ(UTF8ToUTF16(std::string("Chase")), obfuscated3);
}
// Tests function NetworkOrBankNameAndLastFourDigits.
TEST(CreditCardTest, NetworkOrBankNameAndLastFourDigitsStrings) {
// Case 1: Bank name is empty -> show network name.
CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&credit_card2, "John Dillinger",
"5105 1051 0510 5100" /* Mastercard */, "01", "2010",
"1");
EXPECT_TRUE(credit_card2.bank_name().empty());
base::string16 obfuscated2 =
credit_card2.NetworkOrBankNameAndLastFourDigits();
EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("5100")),
obfuscated2);
// Case 2: Bank name is not empty -> show bank name.
CreditCard credit_card3(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&credit_card3, "John Dillinger",
"5105 1051 0510 5100" /* Mastercard */, "01", "2010",
"1");
credit_card3.set_bank_name("Chase");
base::string16 obfuscated3 =
credit_card3.NetworkOrBankNameAndLastFourDigits();
EXPECT_FALSE(credit_card3.bank_name().empty());
EXPECT_EQ(UTF8ToUTF16(std::string("Chase ") +
test::ObfuscatedCardDigitsAsUTF8("5100")),
obfuscated3);
}
TEST(CreditCardTest, AssignmentOperator) {
CreditCard a(base::GenerateGUID(), "some origin");
test::SetCreditCardInfo(&a, "John Dillinger", "123456789012", "01", "2010",
"1");
// Result of assignment should be logically equal to the original profile.
CreditCard b(base::GenerateGUID(), "some other origin");
b = a;
EXPECT_TRUE(a == b);
// Assignment to self should not change the profile value.
a = *&a; // The *& defeats Clang's -Wself-assign warning.
EXPECT_TRUE(a == b);
}
struct SetExpirationYearFromStringTestCase {
std::string expiration_year;
int expected_year;
};
class SetExpirationYearFromStringTest
: public testing::TestWithParam<SetExpirationYearFromStringTestCase> {};
TEST_P(SetExpirationYearFromStringTest, SetExpirationYearFromString) {
auto test_case = GetParam();
CreditCard card(base::GenerateGUID(), "some origin");
card.SetExpirationYearFromString(ASCIIToUTF16(test_case.expiration_year));
EXPECT_EQ(test_case.expected_year, card.expiration_year())
<< test_case.expiration_year << " " << test_case.expected_year;
}
INSTANTIATE_TEST_CASE_P(CreditCardTest,
SetExpirationYearFromStringTest,
testing::Values(
// Valid values.
SetExpirationYearFromStringTestCase{"2040", 2040},
SetExpirationYearFromStringTestCase{"45", 2045},
SetExpirationYearFromStringTestCase{"045", 2045},
SetExpirationYearFromStringTestCase{"9", 2009},
// Unrecognized year values.
SetExpirationYearFromStringTestCase{"052045", 0},
SetExpirationYearFromStringTestCase{"123", 0},
SetExpirationYearFromStringTestCase{"y2045", 0}));
struct SetExpirationDateFromStringTestCase {
std::string expiration_date;
int expected_month;
int expected_year;
};
class SetExpirationDateFromStringTest
: public testing::TestWithParam<SetExpirationDateFromStringTestCase> {};
TEST_P(SetExpirationDateFromStringTest, SetExpirationDateFromString) {
auto test_case = GetParam();
CreditCard card(base::GenerateGUID(), "some origin");
card.SetExpirationDateFromString(ASCIIToUTF16(test_case.expiration_date));
EXPECT_EQ(test_case.expected_month, card.expiration_month());
EXPECT_EQ(test_case.expected_year, card.expiration_year());
}
INSTANTIATE_TEST_CASE_P(
CreditCardTest,
SetExpirationDateFromStringTest,
testing::Values(
SetExpirationDateFromStringTestCase{"10", 0, 0}, // Too small.
SetExpirationDateFromStringTestCase{"1020451", 0, 0}, // Too long.
// No separators.
SetExpirationDateFromStringTestCase{"105", 0, 0}, // Too ambiguous.
SetExpirationDateFromStringTestCase{"0545", 5, 2045},
SetExpirationDateFromStringTestCase{"52045", 0, 0}, // Too ambiguous.
SetExpirationDateFromStringTestCase{"052045", 5, 2045},
// "/" separator.
SetExpirationDateFromStringTestCase{"05/45", 5, 2045},
SetExpirationDateFromStringTestCase{"5/2045", 5, 2045},
SetExpirationDateFromStringTestCase{"05/2045", 5, 2045},
// "-" separator.
SetExpirationDateFromStringTestCase{"05-45", 5, 2045},
SetExpirationDateFromStringTestCase{"5-2045", 5, 2045},
SetExpirationDateFromStringTestCase{"05-2045", 5, 2045},
// "|" separator.
SetExpirationDateFromStringTestCase{"05|45", 5, 2045},
SetExpirationDateFromStringTestCase{"5|2045", 5, 2045},
SetExpirationDateFromStringTestCase{"05|2045", 5, 2045},
// Invalid values.
SetExpirationDateFromStringTestCase{"13/2016", 0, 2016},
SetExpirationDateFromStringTestCase{"16/13", 0, 2013},
SetExpirationDateFromStringTestCase{"May-2015", 0, 0},
SetExpirationDateFromStringTestCase{"05-/2045", 0, 0},
SetExpirationDateFromStringTestCase{"05_2045", 0, 0}));
TEST(CreditCardTest, Copy) {
CreditCard a(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&a, "John Dillinger", "123456789012", "01", "2010",
base::GenerateGUID());
// Clone should be logically equal to the original.
CreditCard b(a);
EXPECT_TRUE(a == b);
}
struct IsLocalDuplicateOfServerCardTestCase {
CreditCard::RecordType first_card_record_type;
const char* first_card_name;
const char* first_card_number;
const char* first_card_exp_mo;
const char* first_card_exp_yr;
const char* first_billing_address_id;
CreditCard::RecordType second_card_record_type;
const char* second_card_name;
const char* second_card_number;
const char* second_card_exp_mo;
const char* second_card_exp_yr;
const char* second_billing_address_id;
const char* second_card_issuer_network;
bool is_local_duplicate;
};
class IsLocalDuplicateOfServerCardTest
: public testing::TestWithParam<IsLocalDuplicateOfServerCardTestCase> {};
TEST_P(IsLocalDuplicateOfServerCardTest, IsLocalDuplicateOfServerCard) {
auto test_case = GetParam();
CreditCard a(base::GenerateGUID(), std::string());
a.set_record_type(test_case.first_card_record_type);
test::SetCreditCardInfo(
&a, test_case.first_card_name, test_case.first_card_number,
test_case.first_card_exp_mo, test_case.first_card_exp_yr,
test_case.first_billing_address_id);
CreditCard b(base::GenerateGUID(), std::string());
b.set_record_type(test_case.second_card_record_type);
test::SetCreditCardInfo(
&b, test_case.second_card_name, test_case.second_card_number,
test_case.second_card_exp_mo, test_case.second_card_exp_yr,
test_case.second_billing_address_id);
if (test_case.second_card_record_type == CreditCard::MASKED_SERVER_CARD)
b.SetNetworkForMaskedCard(test_case.second_card_issuer_network);
EXPECT_EQ(test_case.is_local_duplicate, a.IsLocalDuplicateOfServerCard(b))
<< " when comparing cards " << a.Label() << " and " << b.Label();
}
INSTANTIATE_TEST_CASE_P(
CreditCardTest,
IsLocalDuplicateOfServerCardTest,
testing::Values(
IsLocalDuplicateOfServerCardTestCase{LOCAL_CARD, "", "", "", "", "",
LOCAL_CARD, "", "", "", "", "",
nullptr, false},
IsLocalDuplicateOfServerCardTestCase{LOCAL_CARD, "", "", "", "", "",
FULL_SERVER_CARD, "", "", "", "",
"", nullptr, true},
IsLocalDuplicateOfServerCardTestCase{FULL_SERVER_CARD, "", "", "", "",
"", FULL_SERVER_CARD, "", "", "",
"", "", nullptr, false},
IsLocalDuplicateOfServerCardTestCase{
LOCAL_CARD, "John Dillinger", "423456789012", "01", "2010", "1",
FULL_SERVER_CARD, "John Dillinger", "423456789012", "01", "2010",
"1", nullptr, true},
IsLocalDuplicateOfServerCardTestCase{
LOCAL_CARD, "J Dillinger", "423456789012", "01", "2010", "1",
FULL_SERVER_CARD, "John Dillinger", "423456789012", "01", "2010",
"1", nullptr, false},
IsLocalDuplicateOfServerCardTestCase{
LOCAL_CARD, "", "423456789012", "01", "2010", "1", FULL_SERVER_CARD,
"John Dillinger", "423456789012", "01", "2010", "1", nullptr, true},
IsLocalDuplicateOfServerCardTestCase{
LOCAL_CARD, "", "423456789012", "", "", "1", FULL_SERVER_CARD,
"John Dillinger", "423456789012", "01", "2010", "1", nullptr, true},
IsLocalDuplicateOfServerCardTestCase{
LOCAL_CARD, "", "423456789012", "", "", "1", MASKED_SERVER_CARD,
"John Dillinger", "9012", "01", "2010", "1", kVisaCard, true},
IsLocalDuplicateOfServerCardTestCase{
LOCAL_CARD, "", "423456789012", "", "", "1", MASKED_SERVER_CARD,
"John Dillinger", "9012", "01", "2010", "1", kMasterCard, false},
IsLocalDuplicateOfServerCardTestCase{
LOCAL_CARD, "John Dillinger", "4234-5678-9012", "01", "2010", "1",
FULL_SERVER_CARD, "John Dillinger", "423456789012", "01", "2010",
"1", nullptr, true},
IsLocalDuplicateOfServerCardTestCase{
LOCAL_CARD, "John Dillinger", "4234-5678-9012", "01", "2010", "1",
FULL_SERVER_CARD, "John Dillinger", "423456789012", "01", "2010",
"2", nullptr, false}));
TEST(CreditCardTest, HasSameNumberAs) {
CreditCard a(base::GenerateGUID(), std::string());
CreditCard b(base::GenerateGUID(), std::string());
// Empty cards have the same empty number.
EXPECT_TRUE(a.HasSameNumberAs(b));
EXPECT_TRUE(b.HasSameNumberAs(a));
// Same number.
a.set_record_type(CreditCard::LOCAL_CARD);
a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
a.set_record_type(CreditCard::LOCAL_CARD);
b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
EXPECT_TRUE(a.HasSameNumberAs(b));
EXPECT_TRUE(b.HasSameNumberAs(a));
// Local cards shouldn't match even if the last 4 are the same.
a.set_record_type(CreditCard::LOCAL_CARD);
a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
a.set_record_type(CreditCard::LOCAL_CARD);
b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111222222221111"));
EXPECT_FALSE(a.HasSameNumberAs(b));
EXPECT_FALSE(b.HasSameNumberAs(a));
// Likewise if one is an unmasked server card.
a.set_record_type(CreditCard::FULL_SERVER_CARD);
EXPECT_FALSE(a.HasSameNumberAs(b));
EXPECT_FALSE(b.HasSameNumberAs(a));
// But if one is a masked card, then they should.
b.set_record_type(CreditCard::MASKED_SERVER_CARD);
EXPECT_TRUE(a.HasSameNumberAs(b));
EXPECT_TRUE(b.HasSameNumberAs(a));
}
TEST(CreditCardTest, Compare) {
CreditCard a(base::GenerateGUID(), std::string());
CreditCard b(base::GenerateGUID(), std::string());
// Empty cards are the same.
EXPECT_EQ(0, a.Compare(b));
// GUIDs don't count.
a.set_guid(base::GenerateGUID());
b.set_guid(base::GenerateGUID());
EXPECT_EQ(0, a.Compare(b));
// Origins don't count.
a.set_origin("apple");
b.set_origin("banana");
EXPECT_EQ(0, a.Compare(b));
// Different values produce non-zero results.
test::SetCreditCardInfo(&a, "Jimmy", nullptr, nullptr, nullptr, "");
test::SetCreditCardInfo(&b, "Ringo", nullptr, nullptr, nullptr, "");
EXPECT_GT(0, a.Compare(b));
EXPECT_LT(0, b.Compare(a));
}
// Test we get the correct icon for each card type.
TEST(CreditCardTest, IconResourceId) {
EXPECT_EQ(IDR_AUTOFILL_CC_AMEX,
CreditCard::IconResourceId(kAmericanExpressCard));
EXPECT_EQ(IDR_AUTOFILL_CC_DINERS,
CreditCard::IconResourceId(kDinersCard));
EXPECT_EQ(IDR_AUTOFILL_CC_DISCOVER,
CreditCard::IconResourceId(kDiscoverCard));
EXPECT_EQ(IDR_AUTOFILL_CC_ELO,
CreditCard::IconResourceId(kEloCard));
EXPECT_EQ(IDR_AUTOFILL_CC_JCB,
CreditCard::IconResourceId(kJCBCard));
EXPECT_EQ(IDR_AUTOFILL_CC_MASTERCARD,
CreditCard::IconResourceId(kMasterCard));
EXPECT_EQ(IDR_AUTOFILL_CC_MIR,
CreditCard::IconResourceId(kMirCard));
EXPECT_EQ(IDR_AUTOFILL_CC_UNIONPAY,
CreditCard::IconResourceId(kUnionPay));
EXPECT_EQ(IDR_AUTOFILL_CC_VISA,
CreditCard::IconResourceId(kVisaCard));
}
TEST(CreditCardTest, UpdateFromImportedCard) {
CreditCard original_card(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012",
"09", "2017", "1");
CreditCard a = original_card;
// The new card has a different name, expiration date, and origin.
CreditCard b = a;
b.set_guid(base::GenerateGUID());
b.set_origin("https://www.example.org");
b.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger"));
b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08"));
b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019"));
// |a| should be updated with the information from |b|.
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ("https://www.example.org", a.origin());
EXPECT_EQ(ASCIIToUTF16("J. Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
// Try again, but with no name set for |b|.
// |a| should be updated with |b|'s expiration date and keep its original
// name.
a = original_card;
b.SetRawInfo(CREDIT_CARD_NAME_FULL, base::string16());
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ("https://www.example.org", a.origin());
EXPECT_EQ(ASCIIToUTF16("John Dillinger"),
a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
// Try again, but with only the original card having a verified origin.
// |a| should be unchanged.
a = original_card;
a.set_origin(kSettingsOrigin);
b.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger"));
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ(kSettingsOrigin, a.origin());
EXPECT_EQ(ASCIIToUTF16("John Dillinger"),
a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("09"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(ASCIIToUTF16("2017"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
// Try again, but with using an expired verified original card.
// |a| should not be updated because the name on the cards are not identical.
a = original_card;
a.set_origin("Chrome settings");
a.SetExpirationYear(2010);
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ("Chrome settings", a.origin());
EXPECT_EQ(ASCIIToUTF16("John Dillinger"),
a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("09"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(ASCIIToUTF16("2010"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
// Try again, but with using identical name on the cards.
// |a|'s expiration date should be updated.
a = original_card;
a.set_origin("Chrome settings");
a.SetExpirationYear(2010);
a.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger"));
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ("Chrome settings", a.origin());
EXPECT_EQ(ASCIIToUTF16("J. Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
// Try again, but with |b| being expired.
// |a|'s expiration date should not be updated.
a = original_card;
a.set_origin("Chrome settings");
a.SetExpirationYear(2010);
a.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger"));
b.SetExpirationYear(2009);
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ("Chrome settings", a.origin());
EXPECT_EQ(ASCIIToUTF16("J. Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("09"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(ASCIIToUTF16("2010"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
// Put back |b|'s initial expiration date.
b.SetExpirationYear(2019);
// Try again, but with only the new card having a verified origin.
// |a| should be updated.
a = original_card;
b.set_origin(kSettingsOrigin);
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ(kSettingsOrigin, a.origin());
EXPECT_EQ(ASCIIToUTF16("J. Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
// Try again, with both cards having a verified origin.
// |a| should be updated.
a = original_card;
a.set_origin("Chrome Autofill dialog");
b.set_origin(kSettingsOrigin);
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ(kSettingsOrigin, a.origin());
EXPECT_EQ(ASCIIToUTF16("J. Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
// Try again, but with |b| having a different card number.
// |a| should be unchanged.
a = original_card;
b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
EXPECT_FALSE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ(original_card, a);
}
TEST(CreditCardTest, IsValidCardNumberAndExpiryDate) {
CreditCard card;
// Invalid because expired
const base::Time now(base::Time::Now());
base::Time::Exploded now_exploded;
now.LocalExplode(&now_exploded);
card.SetRawInfo(CREDIT_CARD_EXP_MONTH,
base::IntToString16(now_exploded.month));
card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR,
base::IntToString16(now_exploded.year - 1));
card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
EXPECT_FALSE(card.IsValid());
EXPECT_FALSE(card.HasValidExpirationDate());
EXPECT_TRUE(card.HasValidCardNumber());
// Invalid because card number is not complete
card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("12"));
card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2999"));
card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("41111"));
EXPECT_FALSE(card.IsValid());
for (const char* valid_number : kValidNumbers) {
SCOPED_TRACE(valid_number);
card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16(valid_number));
EXPECT_TRUE(card.IsValid());
EXPECT_TRUE(card.HasValidCardNumber());
EXPECT_TRUE(card.HasValidExpirationDate());
}
for (const char* invalid_number : kInvalidNumbers) {
SCOPED_TRACE(invalid_number);
card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16(invalid_number));
EXPECT_FALSE(card.IsValid());
EXPECT_TRUE(card.HasValidExpirationDate());
EXPECT_FALSE(card.HasValidCardNumber());
}
}
// Verify that we preserve exactly what the user typed for credit card numbers.
TEST(CreditCardTest, SetRawInfoCreditCardNumber) {
CreditCard card(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&card, "Bob Dylan", "4321-5432-6543-xxxx", "07",
"2013", "1");
EXPECT_EQ(ASCIIToUTF16("4321-5432-6543-xxxx"),
card.GetRawInfo(CREDIT_CARD_NUMBER));
}
// Verify that we can handle both numeric and named months.
TEST(CreditCardTest, SetExpirationMonth) {
CreditCard card(base::GenerateGUID(), "https://www.example.com/");
card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("05"));
EXPECT_EQ(ASCIIToUTF16("05"), card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(5, card.expiration_month());
card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("7"));
EXPECT_EQ(ASCIIToUTF16("07"), card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(7, card.expiration_month());
// This should fail, and preserve the previous value.
card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("January"));
EXPECT_EQ(ASCIIToUTF16("07"), card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(7, card.expiration_month());
card.SetInfo(
AutofillType(CREDIT_CARD_EXP_MONTH), ASCIIToUTF16("January"), "en-US");
EXPECT_EQ(ASCIIToUTF16("01"), card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(1, card.expiration_month());
card.SetInfo(
AutofillType(CREDIT_CARD_EXP_MONTH), ASCIIToUTF16("Apr"), "en-US");
EXPECT_EQ(ASCIIToUTF16("04"), card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(4, card.expiration_month());
card.SetInfo(AutofillType(CREDIT_CARD_EXP_MONTH),
UTF8ToUTF16("FÉVRIER"), "fr-FR");
EXPECT_EQ(ASCIIToUTF16("02"), card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(2, card.expiration_month());
}
TEST(CreditCardTest, CreditCardType) {
CreditCard card(base::GenerateGUID(), "https://www.example.com/");
// The card type cannot be set directly.
card.SetRawInfo(CREDIT_CARD_TYPE, ASCIIToUTF16("Visa"));
EXPECT_EQ(base::string16(), card.GetRawInfo(CREDIT_CARD_TYPE));
// Setting the number should implicitly set the type.
card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111 1111 1111 1111"));
EXPECT_EQ(ASCIIToUTF16("Visa"), card.GetRawInfo(CREDIT_CARD_TYPE));
}
TEST(CreditCardTest, CreditCardVerificationCode) {
CreditCard card(base::GenerateGUID(), "https://www.example.com/");
// The verification code cannot be set, as Chrome does not store this data.
card.SetRawInfo(CREDIT_CARD_VERIFICATION_CODE, ASCIIToUTF16("999"));
EXPECT_EQ(base::string16(), card.GetRawInfo(CREDIT_CARD_VERIFICATION_CODE));
}
struct CreditCardMatchingTypesCase {
CreditCardMatchingTypesCase(const char* value,
const char* card_exp_month,
const char* card_exp_year,
CreditCard::RecordType record_type,
ServerFieldTypeSet expected_matched_types,
const char* locale = "US")
: value(value),
card_exp_month(card_exp_month),
card_exp_year(card_exp_year),
record_type(record_type),
expected_matched_types(expected_matched_types),
locale(locale) {}
// The value entered by the user.
const char* value;
// Some values for an already saved card. Card number will be fixed to
// 4012888888881881.
const char* card_exp_month;
const char* card_exp_year;
const CreditCard::RecordType record_type;
// The types that are expected to match.
const ServerFieldTypeSet expected_matched_types;
const char* locale = "US";
};
class CreditCardMatchingTypesTest
: public testing::TestWithParam<CreditCardMatchingTypesCase> {};
TEST_P(CreditCardMatchingTypesTest, Cases) {
auto test_case = GetParam();
CreditCard card(base::GenerateGUID(), "https://www.example.com/");
card.set_record_type(test_case.record_type);
card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4012888888881881"));
card.SetRawInfo(CREDIT_CARD_EXP_MONTH,
ASCIIToUTF16(test_case.card_exp_month));
card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR,
ASCIIToUTF16(test_case.card_exp_year));
ServerFieldTypeSet matching_types;
card.GetMatchingTypes(UTF8ToUTF16(test_case.value), test_case.locale,
&matching_types);
EXPECT_EQ(test_case.expected_matched_types, matching_types);
}
const CreditCardMatchingTypesCase kCreditCardMatchingTypesTestCases[] = {
// If comparing against a masked card, last four digits are checked.
{"1881", "01", "2020", MASKED_SERVER_CARD, {CREDIT_CARD_NUMBER}},
{"4012888888881881",
"01",
"2020",
MASKED_SERVER_CARD,
{CREDIT_CARD_NUMBER}},
{"4111111111111111", "01", "2020", CreditCard::MASKED_SERVER_CARD,
ServerFieldTypeSet()},
// Same value will not match a local card or full server card since we
// have the full number for those. However the full number will.
{"1881", "01", "2020", LOCAL_CARD, ServerFieldTypeSet()},
{"1881", "01", "2020", FULL_SERVER_CARD, ServerFieldTypeSet()},
{"4012888888881881", "01", "2020", LOCAL_CARD, {CREDIT_CARD_NUMBER}},
{"4012888888881881", "01", "2020", FULL_SERVER_CARD, {CREDIT_CARD_NUMBER}},
// Wrong last four digits.
{"1111", "01", "2020", MASKED_SERVER_CARD, ServerFieldTypeSet()},
{"1111", "01", "2020", LOCAL_CARD, ServerFieldTypeSet()},
{"1111", "01", "2020", FULL_SERVER_CARD, ServerFieldTypeSet()},
{"4111111111111111", "01", "2020", MASKED_SERVER_CARD,
ServerFieldTypeSet()},
{"4111111111111111", "01", "2020", LOCAL_CARD, ServerFieldTypeSet()},
{"4111111111111111", "01", "2020", FULL_SERVER_CARD, ServerFieldTypeSet()},
// Matching the expiration month.
{"01", "01", "2020", LOCAL_CARD, {CREDIT_CARD_EXP_MONTH}},
{"1", "01", "2020", LOCAL_CARD, {CREDIT_CARD_EXP_MONTH}},
{"jan", "01", "2020", LOCAL_CARD, {CREDIT_CARD_EXP_MONTH}, "US"},
// Locale-specific interpretations.
{"janv", "01", "2020", LOCAL_CARD, {CREDIT_CARD_EXP_MONTH}, "FR"},
{"janv.", "01", "2020", LOCAL_CARD, {CREDIT_CARD_EXP_MONTH}, "FR"},
{"janvier", "01", "2020", LOCAL_CARD, {CREDIT_CARD_EXP_MONTH}, "FR"},
{"février", "02", "2020", LOCAL_CARD, {CREDIT_CARD_EXP_MONTH}, "FR"},
{"mars", "01", "2020", LOCAL_CARD, ServerFieldTypeSet(), "FR"},
// Matching the expiration year.
{"2019", "01", "2019", LOCAL_CARD, {CREDIT_CARD_EXP_4_DIGIT_YEAR}},
{"19", "01", "2019", LOCAL_CARD, {CREDIT_CARD_EXP_2_DIGIT_YEAR}},
{"01/2019", "01", "2019", LOCAL_CARD, {CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR}},
{"01-2019", "01", "2019", LOCAL_CARD, {CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR}},
{"01/2020", "01", "2019", LOCAL_CARD, ServerFieldTypeSet()},
{"20", "01", "2019", LOCAL_CARD, ServerFieldTypeSet()},
{"2021", "01", "2019", LOCAL_CARD, ServerFieldTypeSet()},
};
INSTANTIATE_TEST_CASE_P(CreditCardTest,
CreditCardMatchingTypesTest,
testing::ValuesIn(kCreditCardMatchingTypesTestCases));
struct GetCardNetworkTestCase {
const char* card_number;
const char* issuer_network;
bool is_valid;
};
// We are doing batches here because INSTANTIATE_TEST_CASE_P has a
// 50 upper limit.
class GetCardNetworkTestBatch1
: public testing::TestWithParam<GetCardNetworkTestCase> {};
TEST_P(GetCardNetworkTestBatch1, GetCardNetwork) {
auto test_case = GetParam();
base::string16 card_number = ASCIIToUTF16(test_case.card_number);
SCOPED_TRACE(card_number);
EXPECT_EQ(test_case.issuer_network, CreditCard::GetCardNetwork(card_number));
EXPECT_EQ(test_case.is_valid, IsValidCreditCardNumber(card_number));
}
INSTANTIATE_TEST_CASE_P(
CreditCardTest,
GetCardNetworkTestBatch1,
testing::Values(
// The relevant sample numbers from
// http://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
GetCardNetworkTestCase{"378282246310005", kAmericanExpressCard, true},
GetCardNetworkTestCase{"371449635398431", kAmericanExpressCard, true},
GetCardNetworkTestCase{"378734493671000", kAmericanExpressCard, true},
GetCardNetworkTestCase{"30569309025904", kDinersCard, true},
GetCardNetworkTestCase{"38520000023237", kDinersCard, true},
GetCardNetworkTestCase{"6011111111111117", kDiscoverCard, true},
GetCardNetworkTestCase{"6011000990139424", kDiscoverCard, true},
GetCardNetworkTestCase{"3530111333300000", kJCBCard, true},
GetCardNetworkTestCase{"3566002020360505", kJCBCard, true},
GetCardNetworkTestCase{"5555555555554444", kMasterCard, true},
GetCardNetworkTestCase{"5105105105105100", kMasterCard, true},
GetCardNetworkTestCase{"4111111111111111", kVisaCard, true},
GetCardNetworkTestCase{"4012888888881881", kVisaCard, true},
GetCardNetworkTestCase{"4222222222222", kVisaCard, true},
GetCardNetworkTestCase{"4532261615476013542", kVisaCard, true},
// The relevant sample numbers from
// https://www.auricsystems.com/sample-credit-card-numbers/
GetCardNetworkTestCase{"343434343434343", kAmericanExpressCard, true},
GetCardNetworkTestCase{"371144371144376", kAmericanExpressCard, true},
GetCardNetworkTestCase{"341134113411347", kAmericanExpressCard, true},
GetCardNetworkTestCase{"36438936438936", kDinersCard, true},
GetCardNetworkTestCase{"36110361103612", kDinersCard, true},
GetCardNetworkTestCase{"36111111111111", kDinersCard, true},
GetCardNetworkTestCase{"6011016011016011", kDiscoverCard, true},
GetCardNetworkTestCase{"6011000990139424", kDiscoverCard, true},
GetCardNetworkTestCase{"6011000000000004", kDiscoverCard, true},
GetCardNetworkTestCase{"6011000995500000", kDiscoverCard, true},
GetCardNetworkTestCase{"6500000000000002", kDiscoverCard, true},
GetCardNetworkTestCase{"3566002020360505", kJCBCard, true},
GetCardNetworkTestCase{"3528000000000007", kJCBCard, true},
GetCardNetworkTestCase{"2222400061240016", kMasterCard, true},
GetCardNetworkTestCase{"2223000048400011", kMasterCard, true},
GetCardNetworkTestCase{"5500005555555559", kMasterCard, true},
GetCardNetworkTestCase{"5555555555555557", kMasterCard, true},
GetCardNetworkTestCase{"5454545454545454", kMasterCard, true},
GetCardNetworkTestCase{"5478050000000007", kMasterCard, true},
GetCardNetworkTestCase{"5112345112345114", kMasterCard, true},
GetCardNetworkTestCase{"5115915115915118", kMasterCard, true},
GetCardNetworkTestCase{"6247130048162403", kUnionPay, true},
GetCardNetworkTestCase{"6247130048162403", kUnionPay, true},
GetCardNetworkTestCase{"622384452162063648", kUnionPay, true},
GetCardNetworkTestCase{"2204883716636153", kMirCard, true},
GetCardNetworkTestCase{"2200111234567898", kMirCard, true},
GetCardNetworkTestCase{"2200481349288130", kMirCard, true},
// The relevant sample numbers from
// https://www.bincodes.com/bank-creditcard-generator/ and
// https://www.ebanx.com/business/en/developers/integrations/testing/credit-card-test-numbers
GetCardNetworkTestCase{"5067001446391275", kEloCard, true},
GetCardNetworkTestCase{"6362970000457013", kEloCard, true},
// Empty string
GetCardNetworkTestCase{"", kGenericCard, false},
// Non-numeric
GetCardNetworkTestCase{"garbage", kGenericCard, false},
GetCardNetworkTestCase{"4garbage", kVisaCard, false},
// Fails Luhn check.
GetCardNetworkTestCase{"4111111111111112", kVisaCard, false},
GetCardNetworkTestCase{"6247130048162413", kUnionPay, false},
GetCardNetworkTestCase{"2204883716636154", kMirCard, false}));
class GetCardNetworkTestBatch2
: public testing::TestWithParam<GetCardNetworkTestCase> {};
TEST_P(GetCardNetworkTestBatch2, GetCardNetwork) {
auto test_case = GetParam();
base::string16 card_number = ASCIIToUTF16(test_case.card_number);
SCOPED_TRACE(card_number);
EXPECT_EQ(test_case.issuer_network, CreditCard::GetCardNetwork(card_number));
EXPECT_EQ(test_case.is_valid, IsValidCreditCardNumber(card_number));
}
INSTANTIATE_TEST_CASE_P(
CreditCardTest,
GetCardNetworkTestBatch2,
testing::Values(
// Invalid length.
GetCardNetworkTestCase{"3434343434343434", kAmericanExpressCard, false},
GetCardNetworkTestCase{"411111111111116", kVisaCard, false},
GetCardNetworkTestCase{"220011123456783", kMirCard, false},
// Issuer Identification Numbers (IINs) that Chrome recognizes.
GetCardNetworkTestCase{"4", kVisaCard, false},
GetCardNetworkTestCase{"2200", kMirCard, false},
GetCardNetworkTestCase{"2202", kMirCard, false},
GetCardNetworkTestCase{"2204", kMirCard, false},
GetCardNetworkTestCase{"2221", kMasterCard, false},
GetCardNetworkTestCase{"2720", kMasterCard, false},
GetCardNetworkTestCase{"34", kAmericanExpressCard, false},
GetCardNetworkTestCase{"37", kAmericanExpressCard, false},
GetCardNetworkTestCase{"300", kDinersCard, false},
GetCardNetworkTestCase{"301", kDinersCard, false},
GetCardNetworkTestCase{"302", kDinersCard, false},
GetCardNetworkTestCase{"303", kDinersCard, false},
GetCardNetworkTestCase{"304", kDinersCard, false},
GetCardNetworkTestCase{"305", kDinersCard, false},
GetCardNetworkTestCase{"309", kDinersCard, false},
GetCardNetworkTestCase{"36", kDinersCard, false},
GetCardNetworkTestCase{"38", kDinersCard, false},
GetCardNetworkTestCase{"39", kDinersCard, false},
GetCardNetworkTestCase{"6011", kDiscoverCard, false},
GetCardNetworkTestCase{"644", kDiscoverCard, false},
GetCardNetworkTestCase{"645", kDiscoverCard, false},
GetCardNetworkTestCase{"646", kDiscoverCard, false},
GetCardNetworkTestCase{"647", kDiscoverCard, false},
GetCardNetworkTestCase{"648", kDiscoverCard, false},
GetCardNetworkTestCase{"649", kDiscoverCard, false},
GetCardNetworkTestCase{"65", kDiscoverCard, false},
GetCardNetworkTestCase{"5067", kEloCard, false},
GetCardNetworkTestCase{"5090", kEloCard, false},
GetCardNetworkTestCase{"636297", kEloCard, false},
GetCardNetworkTestCase{"3528", kJCBCard, false},
GetCardNetworkTestCase{"3531", kJCBCard, false},
GetCardNetworkTestCase{"3589", kJCBCard, false},
GetCardNetworkTestCase{"51", kMasterCard, false},
GetCardNetworkTestCase{"52", kMasterCard, false},
GetCardNetworkTestCase{"53", kMasterCard, false},
GetCardNetworkTestCase{"54", kMasterCard, false},
GetCardNetworkTestCase{"55", kMasterCard, false},
GetCardNetworkTestCase{"62", kUnionPay, false},
// Not enough data to determine an IIN uniquely.
GetCardNetworkTestCase{"2", kGenericCard, false},
GetCardNetworkTestCase{"3", kGenericCard, false},
GetCardNetworkTestCase{"30", kGenericCard, false},
GetCardNetworkTestCase{"35", kGenericCard, false},
GetCardNetworkTestCase{"5", kGenericCard, false},
GetCardNetworkTestCase{"6", kGenericCard, false},
GetCardNetworkTestCase{"60", kGenericCard, false},
GetCardNetworkTestCase{"601", kGenericCard, false},
GetCardNetworkTestCase{"64", kGenericCard, false}));
class GetCardNetworkTestBatch3
: public testing::TestWithParam<GetCardNetworkTestCase> {};
TEST_P(GetCardNetworkTestBatch3, GetCardNetwork) {
auto test_case = GetParam();
base::string16 card_number = ASCIIToUTF16(test_case.card_number);
SCOPED_TRACE(card_number);
EXPECT_EQ(test_case.issuer_network, CreditCard::GetCardNetwork(card_number));
EXPECT_EQ(test_case.is_valid, IsValidCreditCardNumber(card_number));
}
INSTANTIATE_TEST_CASE_P(
CreditCardTest,
GetCardNetworkTestBatch3,
testing::Values(
// Unknown IINs.
GetCardNetworkTestCase{"0", kGenericCard, false},
GetCardNetworkTestCase{"1", kGenericCard, false},
GetCardNetworkTestCase{"306", kGenericCard, false},
GetCardNetworkTestCase{"307", kGenericCard, false},
GetCardNetworkTestCase{"308", kGenericCard, false},
GetCardNetworkTestCase{"31", kGenericCard, false},
GetCardNetworkTestCase{"32", kGenericCard, false},
GetCardNetworkTestCase{"33", kGenericCard, false},
GetCardNetworkTestCase{"351", kGenericCard, false},
GetCardNetworkTestCase{"3527", kGenericCard, false},
GetCardNetworkTestCase{"359", kGenericCard, false},
GetCardNetworkTestCase{"50", kGenericCard, false},
GetCardNetworkTestCase{"56", kGenericCard, false},
GetCardNetworkTestCase{"57", kGenericCard, false},
GetCardNetworkTestCase{"58", kGenericCard, false},
GetCardNetworkTestCase{"59", kGenericCard, false},
GetCardNetworkTestCase{"600", kGenericCard, false},
GetCardNetworkTestCase{"602", kGenericCard, false},
GetCardNetworkTestCase{"603", kGenericCard, false},
GetCardNetworkTestCase{"604", kGenericCard, false},
GetCardNetworkTestCase{"605", kGenericCard, false},
GetCardNetworkTestCase{"606", kGenericCard, false},
GetCardNetworkTestCase{"607", kGenericCard, false},
GetCardNetworkTestCase{"608", kGenericCard, false},
GetCardNetworkTestCase{"609", kGenericCard, false},
GetCardNetworkTestCase{"61", kGenericCard, false},
GetCardNetworkTestCase{"63", kGenericCard, false},
GetCardNetworkTestCase{"640", kGenericCard, false},
GetCardNetworkTestCase{"641", kGenericCard, false},
GetCardNetworkTestCase{"642", kGenericCard, false},
GetCardNetworkTestCase{"643", kGenericCard, false},
GetCardNetworkTestCase{"66", kGenericCard, false},
GetCardNetworkTestCase{"67", kGenericCard, false},
GetCardNetworkTestCase{"68", kGenericCard, false},
GetCardNetworkTestCase{"69", kGenericCard, false},
GetCardNetworkTestCase{"7", kGenericCard, false},
GetCardNetworkTestCase{"8", kGenericCard, false},
GetCardNetworkTestCase{"9", kGenericCard, false},
// Oddball case: Unknown issuer, but valid Luhn check and plausible
// length.
GetCardNetworkTestCase{"7000700070007000", kGenericCard, true}));
TEST(CreditCardTest, LastFourDigits) {
CreditCard card(base::GenerateGUID(), "https://www.example.com/");
ASSERT_EQ(base::string16(), card.LastFourDigits());
ASSERT_EQ(internal::GetObfuscatedStringForCardDigits(base::string16()),
card.ObfuscatedLastFourDigits());
test::SetCreditCardInfo(&card, "Baby Face Nelson", "5212341234123489", "01",
"2010", "1");
ASSERT_EQ(base::ASCIIToUTF16("3489"), card.LastFourDigits());
ASSERT_EQ(
internal::GetObfuscatedStringForCardDigits(base::ASCIIToUTF16("3489")),
card.ObfuscatedLastFourDigits());
card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("3489"));
ASSERT_EQ(base::ASCIIToUTF16("3489"), card.LastFourDigits());
ASSERT_EQ(
internal::GetObfuscatedStringForCardDigits(base::ASCIIToUTF16("3489")),
card.ObfuscatedLastFourDigits());
card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("489"));
ASSERT_EQ(base::ASCIIToUTF16("489"), card.LastFourDigits());
ASSERT_EQ(
internal::GetObfuscatedStringForCardDigits(base::ASCIIToUTF16("489")),
card.ObfuscatedLastFourDigits());
}
// Verifies that a credit card should be updated.
struct ShouldUpdateExpirationTestCase {
bool should_update_expiration;
int month;
int year;
CreditCard::RecordType record_type;
CreditCard::ServerStatus server_status;
};
class ShouldUpdateExpirationTest
: public testing::TestWithParam<ShouldUpdateExpirationTestCase> {};
class TestingTimes {
public:
TestingTimes() {
now_ = base::Time::Now();
(now_ - base::TimeDelta::FromDays(365)).LocalExplode(&last_year_);
(now_ - base::TimeDelta::FromDays(31)).LocalExplode(&last_month_);
now_.LocalExplode(&current_);
(now_ + base::TimeDelta::FromDays(31)).LocalExplode(&next_month_);
(now_ + base::TimeDelta::FromDays(365)).LocalExplode(&next_year_);
}
base::Time now_;
base::Time::Exploded last_year_;
base::Time::Exploded last_month_;
base::Time::Exploded current_;
base::Time::Exploded next_month_;
base::Time::Exploded next_year_;
};
TestingTimes testingTimes;
TEST_P(ShouldUpdateExpirationTest, ShouldUpdateExpiration) {
auto test_case = GetParam();
CreditCard card;
card.SetExpirationMonth(test_case.month);
card.SetExpirationYear(test_case.year);
card.set_record_type(test_case.record_type);
if (card.record_type() != CreditCard::LOCAL_CARD)
card.SetServerStatus(test_case.server_status);
EXPECT_EQ(test_case.should_update_expiration,
card.ShouldUpdateExpiration(testingTimes.now_));
}
INSTANTIATE_TEST_CASE_P(
CreditCardTest,
ShouldUpdateExpirationTest,
testing::Values(
// Cards that expired last year should always be updated.
ShouldUpdateExpirationTestCase{true, testingTimes.last_year_.month,
testingTimes.last_year_.year,
CreditCard::LOCAL_CARD},
ShouldUpdateExpirationTestCase{
true, testingTimes.last_year_.month, testingTimes.last_year_.year,
CreditCard::FULL_SERVER_CARD, CreditCard::OK},
ShouldUpdateExpirationTestCase{
true, testingTimes.last_year_.month, testingTimes.last_year_.year,
CreditCard::MASKED_SERVER_CARD, CreditCard::OK},
ShouldUpdateExpirationTestCase{
true, testingTimes.last_year_.month, testingTimes.last_year_.year,
CreditCard::FULL_SERVER_CARD, CreditCard::EXPIRED},
ShouldUpdateExpirationTestCase{
true, testingTimes.last_year_.month, testingTimes.last_year_.year,
CreditCard::MASKED_SERVER_CARD, CreditCard::EXPIRED},
// Cards that expired last month should always be updated.
ShouldUpdateExpirationTestCase{true, testingTimes.last_month_.month,
testingTimes.last_month_.year,
CreditCard::LOCAL_CARD},
ShouldUpdateExpirationTestCase{
true, testingTimes.last_month_.month, testingTimes.last_month_.year,
CreditCard::FULL_SERVER_CARD, CreditCard::OK},
ShouldUpdateExpirationTestCase{
true, testingTimes.last_month_.month, testingTimes.last_month_.year,
CreditCard::MASKED_SERVER_CARD, CreditCard::OK},
ShouldUpdateExpirationTestCase{
true, testingTimes.last_month_.month, testingTimes.last_month_.year,
CreditCard::FULL_SERVER_CARD, CreditCard::EXPIRED},
ShouldUpdateExpirationTestCase{
true, testingTimes.last_month_.month, testingTimes.last_month_.year,
CreditCard::MASKED_SERVER_CARD, CreditCard::EXPIRED},
// Cards that expire this month should be updated only if the server
// status is EXPIRED.
ShouldUpdateExpirationTestCase{false, testingTimes.current_.month,
testingTimes.current_.year,
CreditCard::LOCAL_CARD},
ShouldUpdateExpirationTestCase{
false, testingTimes.current_.month, testingTimes.current_.year,
CreditCard::FULL_SERVER_CARD, CreditCard::OK},
ShouldUpdateExpirationTestCase{
false, testingTimes.current_.month, testingTimes.current_.year,
CreditCard::MASKED_SERVER_CARD, CreditCard::OK},
ShouldUpdateExpirationTestCase{
true, testingTimes.current_.month, testingTimes.current_.year,
CreditCard::FULL_SERVER_CARD, CreditCard::EXPIRED},
ShouldUpdateExpirationTestCase{
true, testingTimes.current_.month, testingTimes.current_.year,
CreditCard::MASKED_SERVER_CARD, CreditCard::EXPIRED},
// Cards that expire next month should be updated only if the server
// status is EXPIRED.
ShouldUpdateExpirationTestCase{false, testingTimes.next_month_.month,
testingTimes.next_month_.year,
CreditCard::LOCAL_CARD},
ShouldUpdateExpirationTestCase{false, testingTimes.next_month_.month,
testingTimes.next_month_.year,
CreditCard::MASKED_SERVER_CARD,
CreditCard::OK},
ShouldUpdateExpirationTestCase{false, testingTimes.next_month_.month,
testingTimes.next_month_.year,
CreditCard::FULL_SERVER_CARD,
CreditCard::OK},
ShouldUpdateExpirationTestCase{
true, testingTimes.next_month_.month, testingTimes.next_month_.year,
CreditCard::MASKED_SERVER_CARD, CreditCard::EXPIRED},
ShouldUpdateExpirationTestCase{
true, testingTimes.next_month_.month, testingTimes.next_month_.year,
CreditCard::FULL_SERVER_CARD, CreditCard::EXPIRED},
// Cards that expire next year should be updated only if the server
// status is EXPIRED.
ShouldUpdateExpirationTestCase{false, testingTimes.next_year_.month,
testingTimes.next_year_.year,
CreditCard::LOCAL_CARD},
ShouldUpdateExpirationTestCase{
false, testingTimes.next_year_.month, testingTimes.next_year_.year,
CreditCard::MASKED_SERVER_CARD, CreditCard::OK},
ShouldUpdateExpirationTestCase{
false, testingTimes.next_year_.month, testingTimes.next_year_.year,
CreditCard::FULL_SERVER_CARD, CreditCard::OK},
ShouldUpdateExpirationTestCase{
true, testingTimes.next_year_.month, testingTimes.next_year_.year,
CreditCard::MASKED_SERVER_CARD, CreditCard::EXPIRED},
ShouldUpdateExpirationTestCase{
true, testingTimes.next_year_.month, testingTimes.next_year_.year,
CreditCard::FULL_SERVER_CARD, CreditCard::EXPIRED}));
} // namespace autofill