View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.validator.routines;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertNull;
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  
25  import org.apache.commons.validator.routines.CreditCardValidator.CreditCardRange;
26  import org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit;
27  import org.junit.jupiter.api.Test;
28  
29  /**
30   * Test the CreditCardValidator class.
31   */
32  class CreditCardValidatorTest {
33  
34      private static final String VALID_VISA = "4417123456789113"; // 16
35      private static final String ERROR_VISA = "4417123456789112";
36      private static final String VALID_SHORT_VISA = "4222222222222"; // 13
37      private static final String ERROR_SHORT_VISA = "4222222222229";
38      private static final String VALID_AMEX = "378282246310005"; // 15
39      private static final String ERROR_AMEX = "378282246310001";
40      private static final String VALID_MASTERCARD = "5105105105105100";
41      private static final String ERROR_MASTERCARD = "5105105105105105";
42      private static final String VALID_DISCOVER = "6011000990139424";
43      private static final String ERROR_DISCOVER = "6011000990139421";
44      private static final String VALID_DISCOVER65 = "6534567890123458"; // FIXME need verified test data for Discover with "65" prefix
45      private static final String ERROR_DISCOVER65 = "6534567890123450"; // FIXME need verified test data for Discover with "65" prefix
46      private static final String VALID_DINERS = "30569309025904"; // 14
47      private static final String ERROR_DINERS = "30569309025901";
48      private static final String VALID_VPAY = "4370000000000061"; // 16
49      private static final String VALID_VPAY2 = "4370000000000012";
50      private static final String ERROR_VPAY = "4370000000000069";
51  
52      private static final String[] VALID_CARDS = { VALID_VISA, VALID_SHORT_VISA, VALID_AMEX, VALID_MASTERCARD, VALID_DISCOVER, VALID_DISCOVER65, VALID_DINERS,
53              VALID_VPAY, VALID_VPAY2, "60115564485789458", // VALIDATOR-403
54      };
55  
56      private static final String[] ERROR_CARDS = { ERROR_VISA, ERROR_SHORT_VISA, ERROR_AMEX, ERROR_MASTERCARD, ERROR_DISCOVER, ERROR_DISCOVER65, ERROR_DINERS,
57              ERROR_VPAY,
58  //        ERROR_VPAY2,
59              "", "12345678901", // too short (11)
60              "12345678901234567890", // too long (20)
61              "4417123456789112", // invalid check digit
62      };
63  
64      @Test
65      void testAddAllowedCardType() {
66          final CreditCardValidator ccv = new CreditCardValidator(CreditCardValidator.NONE);
67          // Turned off all cards so even valid numbers should fail
68          assertFalse(ccv.isValid(VALID_VISA));
69          assertFalse(ccv.isValid(VALID_AMEX));
70          assertFalse(ccv.isValid(VALID_MASTERCARD));
71          assertFalse(ccv.isValid(VALID_DISCOVER));
72          assertFalse(ccv.isValid(VALID_DINERS));
73      }
74  
75      /**
76       * Test the Amex Card option
77       */
78      @Test
79      void testAmexOption() {
80          final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.AMEX);
81          assertFalse(validator.isValid(ERROR_AMEX), "Invalid");
82          assertNull(validator.validate(ERROR_AMEX), "validate()");
83          assertEquals(VALID_AMEX, validator.validate(VALID_AMEX));
84  
85          assertTrue(validator.isValid(VALID_AMEX), "Amex");
86          assertFalse(validator.isValid(VALID_DINERS), "Diners");
87          assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
88          assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
89          assertFalse(validator.isValid(VALID_VISA), "Visa");
90          assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
91      }
92  
93      /**
94       * Test the Amex Card validator
95       */
96      @Test
97      void testAmexValidator() {
98  
99          final CodeValidator validator = CreditCardValidator.AMEX_VALIDATOR;
100         final RegexValidator regex = validator.getRegexValidator();
101 
102         // ****** Test Regular Expression ******
103         // length 15 and start with a "34" or "37"
104         assertFalse(regex.isValid("343456789012"), "Length 12");
105         assertFalse(regex.isValid("3434567890123"), "Length 13");
106         assertFalse(regex.isValid("34345678901234"), "Length 14");
107         assertTrue(regex.isValid("343456789012345"), "Length 15");
108         assertFalse(regex.isValid("3434567890123456"), "Length 16");
109         assertFalse(regex.isValid("34345678901234567"), "Length 17");
110         assertFalse(regex.isValid("343456789012345678"), "Length 18");
111         assertFalse(regex.isValid("333456789012345"), "Prefix 33");
112         assertTrue(regex.isValid("343456789012345"), "Prefix 34");
113         assertFalse(regex.isValid("353456789012345"), "Prefix 35");
114         assertFalse(regex.isValid("363456789012345"), "Prefix 36");
115         assertTrue(regex.isValid("373456789012345"), "Prefix 37");
116         assertFalse(regex.isValid("383456789012345"), "Prefix 38");
117         assertFalse(regex.isValid("413456789012345"), "Prefix 41");
118         assertFalse(regex.isValid("3434567x9012345"), "Invalid Char");
119 
120         // *********** Test Validator **********
121         assertTrue(regex.isValid(ERROR_AMEX), "Valid regex");
122         assertFalse(validator.isValid(ERROR_AMEX), "Invalid");
123         assertNull(validator.validate(ERROR_AMEX), "validate()");
124         assertEquals(VALID_AMEX, validator.validate(VALID_AMEX));
125 
126         assertTrue(validator.isValid(VALID_AMEX), "Amex");
127         assertFalse(validator.isValid(VALID_DINERS), "Diners");
128         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
129         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
130         assertFalse(validator.isValid(VALID_VISA), "Visa");
131         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
132 
133         assertTrue(validator.isValid("371449635398431"), "Valid-A");
134         assertTrue(validator.isValid("340000000000009"), "Valid-B");
135         assertTrue(validator.isValid("370000000000002"), "Valid-C");
136         assertTrue(validator.isValid("378734493671000"), "Valid-D");
137     }
138 
139     /**
140      * Test the CodeValidator array constructor
141      */
142     @Test
143     void testArrayConstructor() {
144         final CreditCardValidator ccv = new CreditCardValidator(new CodeValidator[] { CreditCardValidator.VISA_VALIDATOR, CreditCardValidator.AMEX_VALIDATOR });
145 
146         assertTrue(ccv.isValid(VALID_VISA));
147         assertTrue(ccv.isValid(VALID_SHORT_VISA));
148         assertTrue(ccv.isValid(VALID_AMEX));
149         assertFalse(ccv.isValid(VALID_MASTERCARD));
150         assertFalse(ccv.isValid(VALID_DISCOVER));
151 
152         assertFalse(ccv.isValid(ERROR_VISA));
153         assertFalse(ccv.isValid(ERROR_SHORT_VISA));
154         assertFalse(ccv.isValid(ERROR_AMEX));
155         assertFalse(ccv.isValid(ERROR_MASTERCARD));
156         assertFalse(ccv.isValid(ERROR_DISCOVER));
157 
158         assertThrows(IllegalArgumentException.class, () -> new CreditCardValidator((CodeValidator[]) null));
159     }
160 
161     /**
162      * Test the Diners Card option
163      */
164     @Test
165     void testDinersOption() {
166         final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.DINERS);
167         assertFalse(validator.isValid(ERROR_DINERS), "Invalid");
168         assertNull(validator.validate(ERROR_DINERS), "validate()");
169         assertEquals(VALID_DINERS, validator.validate(VALID_DINERS));
170 
171         assertFalse(validator.isValid(VALID_AMEX), "Amex");
172         assertTrue(validator.isValid(VALID_DINERS), "Diners");
173         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
174         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
175         assertFalse(validator.isValid(VALID_VISA), "Visa");
176         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
177     }
178 
179     /**
180      * Test the Diners Card validator
181      */
182     @Test
183     void testDinersValidator() {
184 
185         final CodeValidator validator = CreditCardValidator.DINERS_VALIDATOR;
186         final RegexValidator regex = validator.getRegexValidator();
187 
188         // ****** Test Regular Expression ******
189         // length 14 and start with a "300-305" or "3095" or "36" or "38" or "39"
190         assertFalse(regex.isValid("300456789012"), "Length 12-300");
191         assertFalse(regex.isValid("363456789012"), "Length 12-36");
192         assertFalse(regex.isValid("3004567890123"), "Length 13-300");
193         assertFalse(regex.isValid("3634567890123"), "Length 13-36");
194         assertTrue(regex.isValid("30045678901234"), "Length 14-300");
195         assertTrue(regex.isValid("36345678901234"), "Length 14-36");
196         assertFalse(regex.isValid("300456789012345"), "Length 15-300");
197         assertFalse(regex.isValid("363456789012345"), "Length 15-36");
198         assertFalse(regex.isValid("3004567890123456"), "Length 16-300");
199         assertFalse(regex.isValid("3634567890123456"), "Length 16-36");
200         assertFalse(regex.isValid("30045678901234567"), "Length 17-300");
201         assertFalse(regex.isValid("36345678901234567"), "Length 17-36");
202         assertFalse(regex.isValid("300456789012345678"), "Length 18-300");
203         assertFalse(regex.isValid("363456789012345678"), "Length 18-36");
204 
205         assertTrue(regex.isValid("30045678901234"), "Prefix 300");
206         assertTrue(regex.isValid("30145678901234"), "Prefix 301");
207         assertTrue(regex.isValid("30245678901234"), "Prefix 302");
208         assertTrue(regex.isValid("30345678901234"), "Prefix 303");
209         assertTrue(regex.isValid("30445678901234"), "Prefix 304");
210         assertTrue(regex.isValid("30545678901234"), "Prefix 305");
211         assertFalse(regex.isValid("30645678901234"), "Prefix 306");
212         assertFalse(regex.isValid("30945678901234"), "Prefix 3094");
213         assertTrue(regex.isValid("30955678901234"), "Prefix 3095");
214         assertFalse(regex.isValid("30965678901234"), "Prefix 3096");
215         assertFalse(regex.isValid("35345678901234"), "Prefix 35");
216         assertTrue(regex.isValid("36345678901234"), "Prefix 36");
217         assertFalse(regex.isValid("37345678901234"), "Prefix 37");
218         assertTrue(regex.isValid("38345678901234"), "Prefix 38");
219         assertTrue(regex.isValid("39345678901234"), "Prefix 39");
220 
221         assertFalse(regex.isValid("3004567x901234"), "Invalid Char-A");
222         assertFalse(regex.isValid("3634567x901234"), "Invalid Char-B");
223 
224         // *********** Test Validator **********
225         assertTrue(regex.isValid(ERROR_DINERS), "Valid regex");
226         assertFalse(validator.isValid(ERROR_DINERS), "Invalid");
227         assertNull(validator.validate(ERROR_DINERS), "validate()");
228         assertEquals(VALID_DINERS, validator.validate(VALID_DINERS));
229 
230         assertFalse(validator.isValid(VALID_AMEX), "Amex");
231         assertTrue(validator.isValid(VALID_DINERS), "Diners");
232         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
233         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
234         assertFalse(validator.isValid(VALID_VISA), "Visa");
235         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
236 
237         assertTrue(validator.isValid("30000000000004"), "Valid-A");
238         assertTrue(validator.isValid("30123456789019"), "Valid-B");
239         assertTrue(validator.isValid("36432685260294"), "Valid-C");
240 
241     }
242 
243     /**
244      * Test the Discover Card option
245      */
246     @Test
247     void testDiscoverOption() {
248         final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.DISCOVER);
249         assertFalse(validator.isValid(ERROR_DISCOVER), "Invalid");
250         assertFalse(validator.isValid(ERROR_DISCOVER65), "Invalid65");
251         assertNull(validator.validate(ERROR_DISCOVER), "validate()");
252         assertEquals(VALID_DISCOVER, validator.validate(VALID_DISCOVER));
253         assertEquals(VALID_DISCOVER65, validator.validate(VALID_DISCOVER65));
254 
255         assertFalse(validator.isValid(VALID_AMEX), "Amex");
256         assertFalse(validator.isValid(VALID_DINERS), "Diners");
257         assertTrue(validator.isValid(VALID_DISCOVER), "Discover");
258         assertTrue(validator.isValid(VALID_DISCOVER65), "Discover");
259         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
260         assertFalse(validator.isValid(VALID_VISA), "Visa");
261         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
262     }
263 
264     /**
265      * Test the Discover Card validator
266      */
267     @Test
268     void testDiscoverValidator() {
269 
270         final CodeValidator validator = CreditCardValidator.DISCOVER_VALIDATOR;
271         final RegexValidator regex = validator.getRegexValidator();
272 
273         // ****** Test Regular Expression ******
274         // length 16 and start with either "6011" or or "64[4-9]" or "65"
275         assertFalse(regex.isValid("601156789012"), "Length 12-6011");
276         assertFalse(regex.isValid("653456789012"), "Length 12-65");
277         assertFalse(regex.isValid("6011567890123"), "Length 13-6011");
278         assertFalse(regex.isValid("6534567890123"), "Length 13-65");
279         assertFalse(regex.isValid("60115678901234"), "Length 14-6011");
280         assertFalse(regex.isValid("65345678901234"), "Length 14-65");
281         assertFalse(regex.isValid("601156789012345"), "Length 15-6011");
282         assertFalse(regex.isValid("653456789012345"), "Length 15-65");
283         assertTrue(regex.isValid("6011567890123456"), "Length 16-6011");
284         assertTrue(regex.isValid("6444567890123456"), "Length 16-644");
285         assertTrue(regex.isValid("6484567890123456"), "Length 16-648");
286         assertTrue(regex.isValid("6534567890123456"), "Length 16-65");
287         assertFalse(regex.isValid("65345678901234567"), "Length 17-65");
288         assertFalse(regex.isValid("601156789012345678"), "Length 18-6011");
289         assertFalse(regex.isValid("653456789012345678"), "Length 18-65");
290 
291         assertFalse(regex.isValid("6404567890123456"), "Prefix 640");
292         assertFalse(regex.isValid("6414567890123456"), "Prefix 641");
293         assertFalse(regex.isValid("6424567890123456"), "Prefix 642");
294         assertFalse(regex.isValid("6434567890123456"), "Prefix 643");
295         assertFalse(regex.isValid("6010567890123456"), "Prefix 6010");
296         assertFalse(regex.isValid("6012567890123456"), "Prefix 6012");
297         assertFalse(regex.isValid("6011567x90123456"), "Invalid Char");
298 
299         // *********** Test Validator **********
300         assertTrue(regex.isValid(ERROR_DISCOVER), "Valid regex");
301         assertTrue(regex.isValid(ERROR_DISCOVER65), "Valid regex65");
302         assertFalse(validator.isValid(ERROR_DISCOVER), "Invalid");
303         assertFalse(validator.isValid(ERROR_DISCOVER65), "Invalid65");
304         assertNull(validator.validate(ERROR_DISCOVER), "validate()");
305         assertEquals(VALID_DISCOVER, validator.validate(VALID_DISCOVER));
306         assertEquals(VALID_DISCOVER65, validator.validate(VALID_DISCOVER65));
307 
308         assertFalse(validator.isValid(VALID_AMEX), "Amex");
309         assertFalse(validator.isValid(VALID_DINERS), "Diners");
310         assertTrue(validator.isValid(VALID_DISCOVER), "Discover");
311         assertTrue(validator.isValid(VALID_DISCOVER65), "Discover");
312         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
313         assertFalse(validator.isValid(VALID_VISA), "Visa");
314         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
315 
316         assertTrue(validator.isValid("6011111111111117"), "Valid-A");
317         assertTrue(validator.isValid("6011000000000004"), "Valid-B");
318         assertTrue(validator.isValid("6011000000000012"), "Valid-C");
319 
320     }
321 
322     @Test
323     void testDisjointRange() {
324         CreditCardValidator ccv = new CreditCardValidator(new CreditCardRange[] { new CreditCardRange("305", "4", new int[] { 13, 16 }), });
325         assertEquals(13, VALID_SHORT_VISA.length());
326         assertEquals(16, VALID_VISA.length());
327         assertEquals(14, VALID_DINERS.length());
328         assertTrue(ccv.isValid(VALID_SHORT_VISA));
329         assertTrue(ccv.isValid(VALID_VISA));
330         assertFalse(ccv.isValid(ERROR_SHORT_VISA));
331         assertFalse(ccv.isValid(ERROR_VISA));
332         assertFalse(ccv.isValid(VALID_DINERS));
333         ccv = new CreditCardValidator(new CreditCardRange[] {
334                 // add 14 as a valid length
335                 new CreditCardRange("305", "4", new int[] { 13, 14, 16 }), });
336         assertTrue(ccv.isValid(VALID_DINERS));
337     }
338 
339     @Test
340     void testGeneric() {
341         final CreditCardValidator ccv = CreditCardValidator.genericCreditCardValidator();
342         for (final String s : VALID_CARDS) {
343             assertTrue(ccv.isValid(s), s);
344         }
345         for (final String s : ERROR_CARDS) {
346             assertFalse(ccv.isValid(s), s);
347         }
348     }
349 
350     @Test
351     void testIsValid() {
352         CreditCardValidator ccv = new CreditCardValidator();
353 
354         assertNull(ccv.validate(null));
355 
356         assertFalse(ccv.isValid(null));
357         assertFalse(ccv.isValid(""));
358         assertFalse(ccv.isValid("123456789012")); // too short
359         assertFalse(ccv.isValid("12345678901234567890")); // too long
360         assertFalse(ccv.isValid("4417123456789112"));
361         assertFalse(ccv.isValid("4417q23456w89113"));
362         assertTrue(ccv.isValid(VALID_VISA));
363         assertTrue(ccv.isValid(VALID_SHORT_VISA));
364         assertTrue(ccv.isValid(VALID_AMEX));
365         assertTrue(ccv.isValid(VALID_MASTERCARD));
366         assertTrue(ccv.isValid(VALID_DISCOVER));
367         assertTrue(ccv.isValid(VALID_DISCOVER65));
368 
369         assertFalse(ccv.isValid(ERROR_VISA));
370         assertFalse(ccv.isValid(ERROR_SHORT_VISA));
371         assertFalse(ccv.isValid(ERROR_AMEX));
372         assertFalse(ccv.isValid(ERROR_MASTERCARD));
373         assertFalse(ccv.isValid(ERROR_DISCOVER));
374         assertFalse(ccv.isValid(ERROR_DISCOVER65));
375 
376         // disallow Visa so it should fail even with good number
377         ccv = new CreditCardValidator(CreditCardValidator.AMEX);
378         assertFalse(ccv.isValid("4417123456789113"));
379     }
380 
381     /**
382      * Test the Mastercard Card option
383      */
384     @Test
385     void testMastercardOption() {
386         final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.MASTERCARD);
387         assertFalse(validator.isValid(ERROR_MASTERCARD), "Invalid");
388         assertNull(validator.validate(ERROR_MASTERCARD), "validate()");
389         assertEquals(VALID_MASTERCARD, validator.validate(VALID_MASTERCARD));
390 
391         assertFalse(validator.isValid(VALID_AMEX), "Amex");
392         assertFalse(validator.isValid(VALID_DINERS), "Diners");
393         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
394         assertTrue(validator.isValid(VALID_MASTERCARD), "Mastercard");
395         assertFalse(validator.isValid(VALID_VISA), "Visa");
396         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
397     }
398 
399     /**
400      * Test using separators
401      */
402     @Test
403     void testMastercardUsingSeparators() {
404 
405         final String masterCardRegExSep = "^(5[1-5]\\d{2})(?:[- ])?(\\d{4})(?:[- ])?(\\d{4})(?:[- ])?(\\d{4})$";
406         final CodeValidator validator = new CodeValidator(masterCardRegExSep, LuhnCheckDigit.LUHN_CHECK_DIGIT);
407         final RegexValidator regex = validator.getRegexValidator();
408 
409         // ****** Test Regular Expression ******
410         // length 16 and start with a "51-55"
411         assertEquals("5134567890123456", regex.validate("5134567890123456"), "Number");
412         assertEquals("5134567890123456", regex.validate("5134-5678-9012-3456"), "Hyphen");
413         assertEquals("5134567890123456", regex.validate("5134 5678 9012 3456"), "Space");
414         assertEquals("5134567890123456", regex.validate("5134-5678 9012-3456"), "MixedA");
415         assertEquals("5134567890123456", regex.validate("5134 5678-9012 3456"), "MixedB");
416 
417         assertFalse(regex.isValid("5134.5678.9012.3456"), "Invalid Separator A");
418         assertFalse(regex.isValid("5134_5678_9012_3456"), "Invalid Separator B");
419         assertFalse(regex.isValid("513-45678-9012-3456"), "Invalid Grouping A");
420         assertFalse(regex.isValid("5134-567-89012-3456"), "Invalid Grouping B");
421         assertFalse(regex.isValid("5134-5678-901-23456"), "Invalid Grouping C");
422 
423         // *********** Test Validator **********
424         assertEquals("5500000000000004", validator.validate("5500-0000-0000-0004"), "Valid-A");
425         assertEquals("5424000000000015", validator.validate("5424 0000 0000 0015"), "Valid-B");
426         assertEquals("5301250070000191", validator.validate("5301-250070000191"), "Valid-C");
427         assertEquals("5123456789012346", validator.validate("5123456789012346"), "Valid-D");
428     }
429 
430     /**
431      * Test the Mastercard Card validator
432      */
433     @Test
434     void testMastercardValidator() {
435 
436         final CodeValidator validator = CreditCardValidator.MASTERCARD_VALIDATOR;
437         final RegexValidator regex = validator.getRegexValidator();
438 
439         // ****** Test Regular Expression ******
440         // length 16 and start with a "51-55"
441         assertFalse(regex.isValid("513456789012"), "Length 12");
442         assertFalse(regex.isValid("5134567890123"), "Length 13");
443         assertFalse(regex.isValid("51345678901234"), "Length 14");
444         assertFalse(regex.isValid("513456789012345"), "Length 15");
445         assertTrue(regex.isValid("5134567890123456"), "Length 16");
446         assertFalse(regex.isValid("51345678901234567"), "Length 17");
447         assertFalse(regex.isValid("513456789012345678"), "Length 18");
448         assertFalse(regex.isValid("4134567890123456"), "Prefix 41");
449         assertFalse(regex.isValid("5034567890123456"), "Prefix 50");
450         assertTrue(regex.isValid("5134567890123456"), "Prefix 51");
451         assertTrue(regex.isValid("5234567890123456"), "Prefix 52");
452         assertTrue(regex.isValid("5334567890123456"), "Prefix 53");
453         assertTrue(regex.isValid("5434567890123456"), "Prefix 54");
454         assertTrue(regex.isValid("5534567890123456"), "Prefix 55");
455         assertFalse(regex.isValid("5634567890123456"), "Prefix 56");
456         assertFalse(regex.isValid("6134567890123456"), "Prefix 61");
457         assertFalse(regex.isValid("5134567x90123456"), "Invalid Char");
458 
459         // *********** Test Validator **********
460         assertTrue(regex.isValid(ERROR_MASTERCARD), "Valid regex");
461         assertFalse(validator.isValid(ERROR_MASTERCARD), "Invalid");
462         assertNull(validator.validate(ERROR_MASTERCARD), "validate()");
463         assertEquals(VALID_MASTERCARD, validator.validate(VALID_MASTERCARD));
464 
465         assertFalse(validator.isValid(VALID_AMEX), "Amex");
466         assertFalse(validator.isValid(VALID_DINERS), "Diners");
467         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
468         assertTrue(validator.isValid(VALID_MASTERCARD), "Mastercard");
469         assertFalse(validator.isValid(VALID_VISA), "Visa");
470         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
471 
472         assertTrue(validator.isValid("5500000000000004"), "Valid-A");
473         assertTrue(validator.isValid("5424000000000015"), "Valid-B");
474         assertTrue(validator.isValid("5301250070000191"), "Valid-C");
475         assertTrue(validator.isValid("5123456789012346"), "Valid-D");
476         assertTrue(validator.isValid("5555555555554444"), "Valid-E");
477 
478         final RegexValidator rev = validator.getRegexValidator();
479         final String pad = "0000000000";
480         assertFalse(rev.isValid("222099" + pad), "222099");
481         for (int i = 222100; i <= 272099; i++) {
482             final String j = Integer.toString(i) + pad;
483             assertTrue(rev.isValid(j), j);
484         }
485         assertFalse(rev.isValid("272100" + pad), "272100");
486     }
487 
488     @Test
489     void testRangeGenerator() {
490         final CreditCardValidator ccv = new CreditCardValidator(
491                 new CodeValidator[] { CreditCardValidator.AMEX_VALIDATOR, CreditCardValidator.VISA_VALIDATOR, CreditCardValidator.MASTERCARD_VALIDATOR,
492                         CreditCardValidator.DISCOVER_VALIDATOR, },
493                 // Add missing validator
494                 new CreditCardRange[] { new CreditCardRange("300", "305", 14, 14), // Diners
495                         new CreditCardRange("3095", null, 14, 14), // Diners
496                         new CreditCardRange("36", null, 14, 14), // Diners
497                         new CreditCardRange("38", "39", 14, 14), // Diners
498                 }
499         // we don't have any VPAY examples yet that aren't handled by VISA
500         );
501         for (final String s : VALID_CARDS) {
502             assertTrue(ccv.isValid(s), s);
503         }
504         for (final String s : ERROR_CARDS) {
505             assertFalse(ccv.isValid(s), s);
506         }
507     }
508 
509     @Test
510     void testRangeGeneratorNoLuhn() {
511         final CodeValidator cv = CreditCardValidator
512                 .createRangeValidator(new CreditCardRange[] { new CreditCardRange("1", null, 6, 7), new CreditCardRange("644", "65", 8, 8) }, null);
513         assertTrue(cv.isValid("1990000"));
514         assertTrue(cv.isValid("199000"));
515         assertFalse(cv.isValid("000000"));
516         assertFalse(cv.isValid("099999"));
517         assertFalse(cv.isValid("200000"));
518 
519         assertFalse(cv.isValid("64399999"));
520         assertTrue(cv.isValid("64400000"));
521         assertTrue(cv.isValid("64900000"));
522         assertTrue(cv.isValid("65000000"));
523         assertTrue(cv.isValid("65999999"));
524         assertFalse(cv.isValid("66000000"));
525     }
526 
527     @Test
528     void testValidLength() {
529         assertTrue(CreditCardValidator.validLength(14, new CreditCardRange("", "", 14, 14)));
530         assertFalse(CreditCardValidator.validLength(15, new CreditCardRange("", "", 14, 14)));
531         assertFalse(CreditCardValidator.validLength(13, new CreditCardRange("", "", 14, 14)));
532 
533         assertFalse(CreditCardValidator.validLength(14, new CreditCardRange("", "", 15, 17)));
534         assertTrue(CreditCardValidator.validLength(15, new CreditCardRange("", "", 15, 17)));
535         assertTrue(CreditCardValidator.validLength(16, new CreditCardRange("", "", 15, 17)));
536         assertTrue(CreditCardValidator.validLength(17, new CreditCardRange("", "", 15, 17)));
537         assertFalse(CreditCardValidator.validLength(18, new CreditCardRange("", "", 15, 17)));
538 
539         assertFalse(CreditCardValidator.validLength(14, new CreditCardRange("", "", new int[] { 15, 17 })));
540         assertTrue(CreditCardValidator.validLength(15, new CreditCardRange("", "", new int[] { 15, 17 })));
541         assertFalse(CreditCardValidator.validLength(16, new CreditCardRange("", "", new int[] { 15, 17 })));
542         assertTrue(CreditCardValidator.validLength(17, new CreditCardRange("", "", new int[] { 15, 17 })));
543         assertFalse(CreditCardValidator.validLength(18, new CreditCardRange("", "", new int[] { 15, 17 })));
544     }
545 
546     /**
547      * Test the Visa Card option
548      */
549     @Test
550     void testVisaOption() {
551         final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.VISA);
552         assertFalse(validator.isValid(ERROR_VISA), "Invalid");
553         assertFalse(validator.isValid(ERROR_SHORT_VISA), "Invalid-S");
554         assertNull(validator.validate(ERROR_VISA), "validate()");
555         assertEquals(VALID_VISA, validator.validate(VALID_VISA));
556         assertEquals(VALID_SHORT_VISA, validator.validate(VALID_SHORT_VISA));
557 
558         assertFalse(validator.isValid(VALID_AMEX), "Amex");
559         assertFalse(validator.isValid(VALID_DINERS), "Diners");
560         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
561         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
562         assertTrue(validator.isValid(VALID_VISA), "Visa");
563         assertTrue(validator.isValid(VALID_SHORT_VISA), "Visa Short");
564     }
565 
566     /**
567      * Test the Visa Card validator
568      */
569     @Test
570     void testVisaValidator() {
571 
572         final CodeValidator validator = CreditCardValidator.VISA_VALIDATOR;
573         final RegexValidator regex = validator.getRegexValidator();
574 
575         // ****** Test Regular Expression ******
576         // length 13 or 16, must start with a "4"
577         assertFalse(regex.isValid("423456789012"), "Length 12");
578         assertTrue(regex.isValid("4234567890123"), "Length 13");
579         assertFalse(regex.isValid("42345678901234"), "Length 14");
580         assertFalse(regex.isValid("423456789012345"), "Length 15");
581         assertTrue(regex.isValid("4234567890123456"), "Length 16");
582         assertFalse(regex.isValid("42345678901234567"), "Length 17");
583         assertFalse(regex.isValid("423456789012345678"), "Length 18");
584         assertFalse(regex.isValid("3234567890123"), "Invalid Pref-A");
585         assertFalse(regex.isValid("3234567890123456"), "Invalid Pref-B");
586         assertFalse(regex.isValid("4234567x90123"), "Invalid Char-A");
587         assertFalse(regex.isValid("4234567x90123456"), "Invalid Char-B");
588 
589         // *********** Test Validator **********
590         assertTrue(regex.isValid(ERROR_VISA), "Valid regex");
591         assertTrue(regex.isValid(ERROR_SHORT_VISA), "Valid regex-S");
592         assertFalse(validator.isValid(ERROR_VISA), "Invalid");
593         assertFalse(validator.isValid(ERROR_SHORT_VISA), "Invalid-S");
594         assertNull(validator.validate(ERROR_VISA), "validate()");
595         assertEquals(VALID_VISA, validator.validate(VALID_VISA));
596         assertEquals(VALID_SHORT_VISA, validator.validate(VALID_SHORT_VISA));
597 
598         assertFalse(validator.isValid(VALID_AMEX), "Amex");
599         assertFalse(validator.isValid(VALID_DINERS), "Diners");
600         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
601         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
602         assertTrue(validator.isValid(VALID_VISA), "Visa");
603         assertTrue(validator.isValid(VALID_SHORT_VISA), "Visa Short");
604 
605         assertTrue(validator.isValid("4111111111111111"), "Valid-A");
606         assertTrue(validator.isValid("4543059999999982"), "Valid-C");
607         assertTrue(validator.isValid("4462000000000003"), "Valid-B");
608         assertTrue(validator.isValid("4508750000000009"), "Valid-D"); // Electron
609         assertTrue(validator.isValid("4012888888881881"), "Valid-E");
610     }
611 
612     @Test
613     void testVPayOption() {
614         final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.VPAY);
615         assertTrue(validator.isValid(VALID_VPAY), "Valid");
616         assertTrue(validator.isValid(VALID_VPAY2), "Valid");
617         assertFalse(validator.isValid(ERROR_VPAY), "Invalid");
618         assertEquals(VALID_VPAY, validator.validate(VALID_VPAY));
619         assertEquals(VALID_VPAY2, validator.validate(VALID_VPAY2));
620 
621         assertFalse(validator.isValid(VALID_AMEX), "Amex");
622         assertFalse(validator.isValid(VALID_DINERS), "Diners");
623         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
624         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
625         assertTrue(validator.isValid(VALID_VISA), "Visa");
626         assertTrue(validator.isValid(VALID_SHORT_VISA), "Visa Short");
627     }
628 }