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    *      http://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.assertTrue;
23  import static org.junit.jupiter.api.Assertions.fail;
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  public 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      public 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      public 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      public 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     public 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         try {
159             new CreditCardValidator((CodeValidator[]) null);
160             fail("Expected IllegalArgumentException");
161         } catch (final IllegalArgumentException iae) {
162             // expected result
163         }
164     }
165 
166     /**
167      * Test the Diners Card option
168      */
169     @Test
170     public void testDinersOption() {
171         final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.DINERS);
172         assertFalse(validator.isValid(ERROR_DINERS), "Invalid");
173         assertNull(validator.validate(ERROR_DINERS), "validate()");
174         assertEquals(VALID_DINERS, validator.validate(VALID_DINERS));
175 
176         assertFalse(validator.isValid(VALID_AMEX), "Amex");
177         assertTrue(validator.isValid(VALID_DINERS), "Diners");
178         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
179         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
180         assertFalse(validator.isValid(VALID_VISA), "Visa");
181         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
182     }
183 
184     /**
185      * Test the Diners Card validator
186      */
187     @Test
188     public void testDinersValidator() {
189 
190         final CodeValidator validator = CreditCardValidator.DINERS_VALIDATOR;
191         final RegexValidator regex = validator.getRegexValidator();
192 
193         // ****** Test Regular Expression ******
194         // length 14 and start with a "300-305" or "3095" or "36" or "38" or "39"
195         assertFalse(regex.isValid("300456789012"), "Length 12-300");
196         assertFalse(regex.isValid("363456789012"), "Length 12-36");
197         assertFalse(regex.isValid("3004567890123"), "Length 13-300");
198         assertFalse(regex.isValid("3634567890123"), "Length 13-36");
199         assertTrue(regex.isValid("30045678901234"), "Length 14-300");
200         assertTrue(regex.isValid("36345678901234"), "Length 14-36");
201         assertFalse(regex.isValid("300456789012345"), "Length 15-300");
202         assertFalse(regex.isValid("363456789012345"), "Length 15-36");
203         assertFalse(regex.isValid("3004567890123456"), "Length 16-300");
204         assertFalse(regex.isValid("3634567890123456"), "Length 16-36");
205         assertFalse(regex.isValid("30045678901234567"), "Length 17-300");
206         assertFalse(regex.isValid("36345678901234567"), "Length 17-36");
207         assertFalse(regex.isValid("300456789012345678"), "Length 18-300");
208         assertFalse(regex.isValid("363456789012345678"), "Length 18-36");
209 
210         assertTrue(regex.isValid("30045678901234"), "Prefix 300");
211         assertTrue(regex.isValid("30145678901234"), "Prefix 301");
212         assertTrue(regex.isValid("30245678901234"), "Prefix 302");
213         assertTrue(regex.isValid("30345678901234"), "Prefix 303");
214         assertTrue(regex.isValid("30445678901234"), "Prefix 304");
215         assertTrue(regex.isValid("30545678901234"), "Prefix 305");
216         assertFalse(regex.isValid("30645678901234"), "Prefix 306");
217         assertFalse(regex.isValid("30945678901234"), "Prefix 3094");
218         assertTrue(regex.isValid("30955678901234"), "Prefix 3095");
219         assertFalse(regex.isValid("30965678901234"), "Prefix 3096");
220         assertFalse(regex.isValid("35345678901234"), "Prefix 35");
221         assertTrue(regex.isValid("36345678901234"), "Prefix 36");
222         assertFalse(regex.isValid("37345678901234"), "Prefix 37");
223         assertTrue(regex.isValid("38345678901234"), "Prefix 38");
224         assertTrue(regex.isValid("39345678901234"), "Prefix 39");
225 
226         assertFalse(regex.isValid("3004567x901234"), "Invalid Char-A");
227         assertFalse(regex.isValid("3634567x901234"), "Invalid Char-B");
228 
229         // *********** Test Validator **********
230         assertTrue(regex.isValid(ERROR_DINERS), "Valid regex");
231         assertFalse(validator.isValid(ERROR_DINERS), "Invalid");
232         assertNull(validator.validate(ERROR_DINERS), "validate()");
233         assertEquals(VALID_DINERS, validator.validate(VALID_DINERS));
234 
235         assertFalse(validator.isValid(VALID_AMEX), "Amex");
236         assertTrue(validator.isValid(VALID_DINERS), "Diners");
237         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
238         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
239         assertFalse(validator.isValid(VALID_VISA), "Visa");
240         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
241 
242         assertTrue(validator.isValid("30000000000004"), "Valid-A");
243         assertTrue(validator.isValid("30123456789019"), "Valid-B");
244         assertTrue(validator.isValid("36432685260294"), "Valid-C");
245 
246     }
247 
248     /**
249      * Test the Discover Card option
250      */
251     @Test
252     public void testDiscoverOption() {
253         final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.DISCOVER);
254         assertFalse(validator.isValid(ERROR_DISCOVER), "Invalid");
255         assertFalse(validator.isValid(ERROR_DISCOVER65), "Invalid65");
256         assertNull(validator.validate(ERROR_DISCOVER), "validate()");
257         assertEquals(VALID_DISCOVER, validator.validate(VALID_DISCOVER));
258         assertEquals(VALID_DISCOVER65, validator.validate(VALID_DISCOVER65));
259 
260         assertFalse(validator.isValid(VALID_AMEX), "Amex");
261         assertFalse(validator.isValid(VALID_DINERS), "Diners");
262         assertTrue(validator.isValid(VALID_DISCOVER), "Discover");
263         assertTrue(validator.isValid(VALID_DISCOVER65), "Discover");
264         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
265         assertFalse(validator.isValid(VALID_VISA), "Visa");
266         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
267     }
268 
269     /**
270      * Test the Discover Card validator
271      */
272     @Test
273     public void testDiscoverValidator() {
274 
275         final CodeValidator validator = CreditCardValidator.DISCOVER_VALIDATOR;
276         final RegexValidator regex = validator.getRegexValidator();
277 
278         // ****** Test Regular Expression ******
279         // length 16 and start with either "6011" or or "64[4-9]" or "65"
280         assertFalse(regex.isValid("601156789012"), "Length 12-6011");
281         assertFalse(regex.isValid("653456789012"), "Length 12-65");
282         assertFalse(regex.isValid("6011567890123"), "Length 13-6011");
283         assertFalse(regex.isValid("6534567890123"), "Length 13-65");
284         assertFalse(regex.isValid("60115678901234"), "Length 14-6011");
285         assertFalse(regex.isValid("65345678901234"), "Length 14-65");
286         assertFalse(regex.isValid("601156789012345"), "Length 15-6011");
287         assertFalse(regex.isValid("653456789012345"), "Length 15-65");
288         assertTrue(regex.isValid("6011567890123456"), "Length 16-6011");
289         assertTrue(regex.isValid("6444567890123456"), "Length 16-644");
290         assertTrue(regex.isValid("6484567890123456"), "Length 16-648");
291         assertTrue(regex.isValid("6534567890123456"), "Length 16-65");
292         assertFalse(regex.isValid("65345678901234567"), "Length 17-65");
293         assertFalse(regex.isValid("601156789012345678"), "Length 18-6011");
294         assertFalse(regex.isValid("653456789012345678"), "Length 18-65");
295 
296         assertFalse(regex.isValid("6404567890123456"), "Prefix 640");
297         assertFalse(regex.isValid("6414567890123456"), "Prefix 641");
298         assertFalse(regex.isValid("6424567890123456"), "Prefix 642");
299         assertFalse(regex.isValid("6434567890123456"), "Prefix 643");
300         assertFalse(regex.isValid("6010567890123456"), "Prefix 6010");
301         assertFalse(regex.isValid("6012567890123456"), "Prefix 6012");
302         assertFalse(regex.isValid("6011567x90123456"), "Invalid Char");
303 
304         // *********** Test Validator **********
305         assertTrue(regex.isValid(ERROR_DISCOVER), "Valid regex");
306         assertTrue(regex.isValid(ERROR_DISCOVER65), "Valid regex65");
307         assertFalse(validator.isValid(ERROR_DISCOVER), "Invalid");
308         assertFalse(validator.isValid(ERROR_DISCOVER65), "Invalid65");
309         assertNull(validator.validate(ERROR_DISCOVER), "validate()");
310         assertEquals(VALID_DISCOVER, validator.validate(VALID_DISCOVER));
311         assertEquals(VALID_DISCOVER65, validator.validate(VALID_DISCOVER65));
312 
313         assertFalse(validator.isValid(VALID_AMEX), "Amex");
314         assertFalse(validator.isValid(VALID_DINERS), "Diners");
315         assertTrue(validator.isValid(VALID_DISCOVER), "Discover");
316         assertTrue(validator.isValid(VALID_DISCOVER65), "Discover");
317         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
318         assertFalse(validator.isValid(VALID_VISA), "Visa");
319         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
320 
321         assertTrue(validator.isValid("6011111111111117"), "Valid-A");
322         assertTrue(validator.isValid("6011000000000004"), "Valid-B");
323         assertTrue(validator.isValid("6011000000000012"), "Valid-C");
324 
325     }
326 
327     @Test
328     public void testDisjointRange() {
329         CreditCardValidator ccv = new CreditCardValidator(new CreditCardRange[] { new CreditCardRange("305", "4", new int[] { 13, 16 }), });
330         assertEquals(13, VALID_SHORT_VISA.length());
331         assertEquals(16, VALID_VISA.length());
332         assertEquals(14, VALID_DINERS.length());
333         assertTrue(ccv.isValid(VALID_SHORT_VISA));
334         assertTrue(ccv.isValid(VALID_VISA));
335         assertFalse(ccv.isValid(ERROR_SHORT_VISA));
336         assertFalse(ccv.isValid(ERROR_VISA));
337         assertFalse(ccv.isValid(VALID_DINERS));
338         ccv = new CreditCardValidator(new CreditCardRange[] {
339                 // add 14 as a valid length
340                 new CreditCardRange("305", "4", new int[] { 13, 14, 16 }), });
341         assertTrue(ccv.isValid(VALID_DINERS));
342     }
343 
344     @Test
345     public void testGeneric() {
346         final CreditCardValidator ccv = CreditCardValidator.genericCreditCardValidator();
347         for (final String s : VALID_CARDS) {
348             assertTrue(ccv.isValid(s), s);
349         }
350         for (final String s : ERROR_CARDS) {
351             assertFalse(ccv.isValid(s), s);
352         }
353     }
354 
355     @Test
356     public void testIsValid() {
357         CreditCardValidator ccv = new CreditCardValidator();
358 
359         assertNull(ccv.validate(null));
360 
361         assertFalse(ccv.isValid(null));
362         assertFalse(ccv.isValid(""));
363         assertFalse(ccv.isValid("123456789012")); // too short
364         assertFalse(ccv.isValid("12345678901234567890")); // too long
365         assertFalse(ccv.isValid("4417123456789112"));
366         assertFalse(ccv.isValid("4417q23456w89113"));
367         assertTrue(ccv.isValid(VALID_VISA));
368         assertTrue(ccv.isValid(VALID_SHORT_VISA));
369         assertTrue(ccv.isValid(VALID_AMEX));
370         assertTrue(ccv.isValid(VALID_MASTERCARD));
371         assertTrue(ccv.isValid(VALID_DISCOVER));
372         assertTrue(ccv.isValid(VALID_DISCOVER65));
373 
374         assertFalse(ccv.isValid(ERROR_VISA));
375         assertFalse(ccv.isValid(ERROR_SHORT_VISA));
376         assertFalse(ccv.isValid(ERROR_AMEX));
377         assertFalse(ccv.isValid(ERROR_MASTERCARD));
378         assertFalse(ccv.isValid(ERROR_DISCOVER));
379         assertFalse(ccv.isValid(ERROR_DISCOVER65));
380 
381         // disallow Visa so it should fail even with good number
382         ccv = new CreditCardValidator(CreditCardValidator.AMEX);
383         assertFalse(ccv.isValid("4417123456789113"));
384     }
385 
386     /**
387      * Test the Mastercard Card option
388      */
389     @Test
390     public void testMastercardOption() {
391         final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.MASTERCARD);
392         assertFalse(validator.isValid(ERROR_MASTERCARD), "Invalid");
393         assertNull(validator.validate(ERROR_MASTERCARD), "validate()");
394         assertEquals(VALID_MASTERCARD, validator.validate(VALID_MASTERCARD));
395 
396         assertFalse(validator.isValid(VALID_AMEX), "Amex");
397         assertFalse(validator.isValid(VALID_DINERS), "Diners");
398         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
399         assertTrue(validator.isValid(VALID_MASTERCARD), "Mastercard");
400         assertFalse(validator.isValid(VALID_VISA), "Visa");
401         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
402     }
403 
404     /**
405      * Test using separators
406      */
407     @Test
408     public void testMastercardUsingSeparators() {
409 
410         final String MASTERCARD_REGEX_SEP = "^(5[1-5]\\d{2})(?:[- ])?(\\d{4})(?:[- ])?(\\d{4})(?:[- ])?(\\d{4})$";
411         final CodeValidator validator = new CodeValidator(MASTERCARD_REGEX_SEP, LuhnCheckDigit.LUHN_CHECK_DIGIT);
412         final RegexValidator regex = validator.getRegexValidator();
413 
414         // ****** Test Regular Expression ******
415         // length 16 and start with a "51-55"
416         assertEquals("5134567890123456", regex.validate("5134567890123456"), "Number");
417         assertEquals("5134567890123456", regex.validate("5134-5678-9012-3456"), "Hyphen");
418         assertEquals("5134567890123456", regex.validate("5134 5678 9012 3456"), "Space");
419         assertEquals("5134567890123456", regex.validate("5134-5678 9012-3456"), "MixedA");
420         assertEquals("5134567890123456", regex.validate("5134 5678-9012 3456"), "MixedB");
421 
422         assertFalse(regex.isValid("5134.5678.9012.3456"), "Invalid Separator A");
423         assertFalse(regex.isValid("5134_5678_9012_3456"), "Invalid Separator B");
424         assertFalse(regex.isValid("513-45678-9012-3456"), "Invalid Grouping A");
425         assertFalse(regex.isValid("5134-567-89012-3456"), "Invalid Grouping B");
426         assertFalse(regex.isValid("5134-5678-901-23456"), "Invalid Grouping C");
427 
428         // *********** Test Validator **********
429         assertEquals("5500000000000004", validator.validate("5500-0000-0000-0004"), "Valid-A");
430         assertEquals("5424000000000015", validator.validate("5424 0000 0000 0015"), "Valid-B");
431         assertEquals("5301250070000191", validator.validate("5301-250070000191"), "Valid-C");
432         assertEquals("5123456789012346", validator.validate("5123456789012346"), "Valid-D");
433     }
434 
435     /**
436      * Test the Mastercard Card validator
437      */
438     @Test
439     public void testMastercardValidator() {
440 
441         final CodeValidator validator = CreditCardValidator.MASTERCARD_VALIDATOR;
442         final RegexValidator regex = validator.getRegexValidator();
443 
444         // ****** Test Regular Expression ******
445         // length 16 and start with a "51-55"
446         assertFalse(regex.isValid("513456789012"), "Length 12");
447         assertFalse(regex.isValid("5134567890123"), "Length 13");
448         assertFalse(regex.isValid("51345678901234"), "Length 14");
449         assertFalse(regex.isValid("513456789012345"), "Length 15");
450         assertTrue(regex.isValid("5134567890123456"), "Length 16");
451         assertFalse(regex.isValid("51345678901234567"), "Length 17");
452         assertFalse(regex.isValid("513456789012345678"), "Length 18");
453         assertFalse(regex.isValid("4134567890123456"), "Prefix 41");
454         assertFalse(regex.isValid("5034567890123456"), "Prefix 50");
455         assertTrue(regex.isValid("5134567890123456"), "Prefix 51");
456         assertTrue(regex.isValid("5234567890123456"), "Prefix 52");
457         assertTrue(regex.isValid("5334567890123456"), "Prefix 53");
458         assertTrue(regex.isValid("5434567890123456"), "Prefix 54");
459         assertTrue(regex.isValid("5534567890123456"), "Prefix 55");
460         assertFalse(regex.isValid("5634567890123456"), "Prefix 56");
461         assertFalse(regex.isValid("6134567890123456"), "Prefix 61");
462         assertFalse(regex.isValid("5134567x90123456"), "Invalid Char");
463 
464         // *********** Test Validator **********
465         assertTrue(regex.isValid(ERROR_MASTERCARD), "Valid regex");
466         assertFalse(validator.isValid(ERROR_MASTERCARD), "Invalid");
467         assertNull(validator.validate(ERROR_MASTERCARD), "validate()");
468         assertEquals(VALID_MASTERCARD, validator.validate(VALID_MASTERCARD));
469 
470         assertFalse(validator.isValid(VALID_AMEX), "Amex");
471         assertFalse(validator.isValid(VALID_DINERS), "Diners");
472         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
473         assertTrue(validator.isValid(VALID_MASTERCARD), "Mastercard");
474         assertFalse(validator.isValid(VALID_VISA), "Visa");
475         assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
476 
477         assertTrue(validator.isValid("5500000000000004"), "Valid-A");
478         assertTrue(validator.isValid("5424000000000015"), "Valid-B");
479         assertTrue(validator.isValid("5301250070000191"), "Valid-C");
480         assertTrue(validator.isValid("5123456789012346"), "Valid-D");
481         assertTrue(validator.isValid("5555555555554444"), "Valid-E");
482 
483         final RegexValidator rev = validator.getRegexValidator();
484         final String PAD = "0000000000";
485         assertFalse(rev.isValid("222099" + PAD), "222099");
486         for (int i = 222100; i <= 272099; i++) {
487             final String j = Integer.toString(i) + PAD;
488             assertTrue(rev.isValid(j), j);
489         }
490         assertFalse(rev.isValid("272100" + PAD), "272100");
491     }
492 
493     @Test
494     public void testRangeGenerator() {
495         final CreditCardValidator ccv = new CreditCardValidator(
496                 new CodeValidator[] { CreditCardValidator.AMEX_VALIDATOR, CreditCardValidator.VISA_VALIDATOR, CreditCardValidator.MASTERCARD_VALIDATOR,
497                         CreditCardValidator.DISCOVER_VALIDATOR, },
498                 // Add missing validator
499                 new CreditCardRange[] { new CreditCardRange("300", "305", 14, 14), // Diners
500                         new CreditCardRange("3095", null, 14, 14), // Diners
501                         new CreditCardRange("36", null, 14, 14), // Diners
502                         new CreditCardRange("38", "39", 14, 14), // Diners
503                 }
504         // we don't have any VPAY examples yet that aren't handled by VISA
505         );
506         for (final String s : VALID_CARDS) {
507             assertTrue(ccv.isValid(s), s);
508         }
509         for (final String s : ERROR_CARDS) {
510             assertFalse(ccv.isValid(s), s);
511         }
512     }
513 
514     @Test
515     public void testRangeGeneratorNoLuhn() {
516         final CodeValidator cv = CreditCardValidator
517                 .createRangeValidator(new CreditCardRange[] { new CreditCardRange("1", null, 6, 7), new CreditCardRange("644", "65", 8, 8) }, null);
518         assertTrue(cv.isValid("1990000"));
519         assertTrue(cv.isValid("199000"));
520         assertFalse(cv.isValid("000000"));
521         assertFalse(cv.isValid("099999"));
522         assertFalse(cv.isValid("200000"));
523 
524         assertFalse(cv.isValid("64399999"));
525         assertTrue(cv.isValid("64400000"));
526         assertTrue(cv.isValid("64900000"));
527         assertTrue(cv.isValid("65000000"));
528         assertTrue(cv.isValid("65999999"));
529         assertFalse(cv.isValid("66000000"));
530     }
531 
532     @Test
533     public void testValidLength() {
534         assertTrue(CreditCardValidator.validLength(14, new CreditCardRange("", "", 14, 14)));
535         assertFalse(CreditCardValidator.validLength(15, new CreditCardRange("", "", 14, 14)));
536         assertFalse(CreditCardValidator.validLength(13, new CreditCardRange("", "", 14, 14)));
537 
538         assertFalse(CreditCardValidator.validLength(14, new CreditCardRange("", "", 15, 17)));
539         assertTrue(CreditCardValidator.validLength(15, new CreditCardRange("", "", 15, 17)));
540         assertTrue(CreditCardValidator.validLength(16, new CreditCardRange("", "", 15, 17)));
541         assertTrue(CreditCardValidator.validLength(17, new CreditCardRange("", "", 15, 17)));
542         assertFalse(CreditCardValidator.validLength(18, new CreditCardRange("", "", 15, 17)));
543 
544         assertFalse(CreditCardValidator.validLength(14, new CreditCardRange("", "", new int[] { 15, 17 })));
545         assertTrue(CreditCardValidator.validLength(15, new CreditCardRange("", "", new int[] { 15, 17 })));
546         assertFalse(CreditCardValidator.validLength(16, new CreditCardRange("", "", new int[] { 15, 17 })));
547         assertTrue(CreditCardValidator.validLength(17, new CreditCardRange("", "", new int[] { 15, 17 })));
548         assertFalse(CreditCardValidator.validLength(18, new CreditCardRange("", "", new int[] { 15, 17 })));
549     }
550 
551     /**
552      * Test the Visa Card option
553      */
554     @Test
555     public void testVisaOption() {
556         final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.VISA);
557         assertFalse(validator.isValid(ERROR_VISA), "Invalid");
558         assertFalse(validator.isValid(ERROR_SHORT_VISA), "Invalid-S");
559         assertNull(validator.validate(ERROR_VISA), "validate()");
560         assertEquals(VALID_VISA, validator.validate(VALID_VISA));
561         assertEquals(VALID_SHORT_VISA, validator.validate(VALID_SHORT_VISA));
562 
563         assertFalse(validator.isValid(VALID_AMEX), "Amex");
564         assertFalse(validator.isValid(VALID_DINERS), "Diners");
565         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
566         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
567         assertTrue(validator.isValid(VALID_VISA), "Visa");
568         assertTrue(validator.isValid(VALID_SHORT_VISA), "Visa Short");
569     }
570 
571     /**
572      * Test the Visa Card validator
573      */
574     @Test
575     public void testVisaValidator() {
576 
577         final CodeValidator validator = CreditCardValidator.VISA_VALIDATOR;
578         final RegexValidator regex = validator.getRegexValidator();
579 
580         // ****** Test Regular Expression ******
581         // length 13 or 16, must start with a "4"
582         assertFalse(regex.isValid("423456789012"), "Length 12");
583         assertTrue(regex.isValid("4234567890123"), "Length 13");
584         assertFalse(regex.isValid("42345678901234"), "Length 14");
585         assertFalse(regex.isValid("423456789012345"), "Length 15");
586         assertTrue(regex.isValid("4234567890123456"), "Length 16");
587         assertFalse(regex.isValid("42345678901234567"), "Length 17");
588         assertFalse(regex.isValid("423456789012345678"), "Length 18");
589         assertFalse(regex.isValid("3234567890123"), "Invalid Pref-A");
590         assertFalse(regex.isValid("3234567890123456"), "Invalid Pref-B");
591         assertFalse(regex.isValid("4234567x90123"), "Invalid Char-A");
592         assertFalse(regex.isValid("4234567x90123456"), "Invalid Char-B");
593 
594         // *********** Test Validator **********
595         assertTrue(regex.isValid(ERROR_VISA), "Valid regex");
596         assertTrue(regex.isValid(ERROR_SHORT_VISA), "Valid regex-S");
597         assertFalse(validator.isValid(ERROR_VISA), "Invalid");
598         assertFalse(validator.isValid(ERROR_SHORT_VISA), "Invalid-S");
599         assertNull(validator.validate(ERROR_VISA), "validate()");
600         assertEquals(VALID_VISA, validator.validate(VALID_VISA));
601         assertEquals(VALID_SHORT_VISA, validator.validate(VALID_SHORT_VISA));
602 
603         assertFalse(validator.isValid(VALID_AMEX), "Amex");
604         assertFalse(validator.isValid(VALID_DINERS), "Diners");
605         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
606         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
607         assertTrue(validator.isValid(VALID_VISA), "Visa");
608         assertTrue(validator.isValid(VALID_SHORT_VISA), "Visa Short");
609 
610         assertTrue(validator.isValid("4111111111111111"), "Valid-A");
611         assertTrue(validator.isValid("4543059999999982"), "Valid-C");
612         assertTrue(validator.isValid("4462000000000003"), "Valid-B");
613         assertTrue(validator.isValid("4508750000000009"), "Valid-D"); // Electron
614         assertTrue(validator.isValid("4012888888881881"), "Valid-E");
615     }
616 
617     @Test
618     public void testVPayOption() {
619         final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.VPAY);
620         assertTrue(validator.isValid(VALID_VPAY), "Valid");
621         assertTrue(validator.isValid(VALID_VPAY2), "Valid");
622         assertFalse(validator.isValid(ERROR_VPAY), "Invalid");
623         assertEquals(VALID_VPAY, validator.validate(VALID_VPAY));
624         assertEquals(VALID_VPAY2, validator.validate(VALID_VPAY2));
625 
626         assertFalse(validator.isValid(VALID_AMEX), "Amex");
627         assertFalse(validator.isValid(VALID_DINERS), "Diners");
628         assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
629         assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
630         assertTrue(validator.isValid(VALID_VISA), "Visa");
631         assertTrue(validator.isValid(VALID_SHORT_VISA), "Visa Short");
632     }
633 }