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