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.checkdigit;
18
19 import static org.junit.jupiter.api.Assertions.assertFalse;
20 import static org.junit.jupiter.api.Assertions.assertTrue;
21
22 import java.io.BufferedReader;
23 import java.io.InputStreamReader;
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import org.junit.jupiter.api.BeforeEach;
28 import org.junit.jupiter.api.Test;
29
30 /**
31 * IBAN Check Digit Test.
32 */
33 class IBANCheckDigitTest extends AbstractCheckDigitTest {
34
35 IBANCheckDigitTest() {
36 checkDigitLth = 2;
37 }
38
39 /**
40 * Returns the check digit (i.e. last character) for a code.
41 *
42 * @param code The code
43 * @return The check digit
44 */
45 @Override
46 protected String checkDigit(final String code) {
47 if (code == null || code.length() <= checkDigitLth) {
48 return "";
49 }
50 return code.substring(2, 4);
51 }
52
53 /**
54 * Returns an array of codes with invalid check digits.
55 *
56 * @param codes Codes with valid check digits
57 * @return Codes with invalid check digits
58 */
59 @Override
60 protected String[] createInvalidCodes(final String[] codes) {
61 final List<String> list = new ArrayList<>();
62
63 // create invalid check digit values
64 for (final String code2 : codes) {
65 final String code = removeCheckDigit(code2);
66 final String check = checkDigit(code2);
67 for (int j = 2; j <= 98; j++) { // check digits can be from 02-98 (00 and 01 are not possible)
68 final String curr = j > 9 ? "" + j : "0" + j;
69 if (!curr.equals(check)) {
70 list.add(code.substring(0, 2) + curr + code.substring(4));
71 }
72 }
73 }
74
75 return list.toArray(new String[0]);
76 }
77
78 /**
79 * Returns a code with the Check Digits (i.e. characters 3&4) set to "00".
80 *
81 * @param code The code
82 * @return The code with the zeroed check digits
83 */
84 @Override
85 protected String removeCheckDigit(final String code) {
86 return code.substring(0, 2) + "00" + code.substring(4);
87 }
88
89 /**
90 * Sets up routine & valid codes.
91 */
92 @BeforeEach
93 protected void setUp() {
94 routine = IBANCheckDigit.IBAN_CHECK_DIGIT;
95 valid = new String[] { "AD1200012030200359100100", // Andorra
96 "AE070331234567890123456", // United Arab Emirates
97 "AL47212110090000000235698741", // Albania
98 "AT611904300234573201", // Austria
99 "AZ21NABZ00000000137010001944", // Azerbaijan
100 "BA391290079401028494", // Bosnia and Herzegovina
101 "BE62510007547061", // Belgium
102 "BE68539007547034", // Belgium
103 "BG80BNBG96611020345678", // Bulgaria
104 "BH67BMAG00001299123456", // Bahrain
105 "BI4210000100010000332045181", // Burundi
106 "BR1800000000141455123924100C2", // Brazil
107 "BY13NBRB3600900000002Z00AB00", // Belarus
108 "CH3900700115201849173", // Switzerland
109 "CH9300762011623852957", // Switzerland
110 "CR05015202001026284066", // Costa Rica
111 "CY17002001280000001200527600", // Cyprus
112 "CZ6508000000192000145399", // Czechoslovakia
113 "DE89370400440532013000", // Germany
114 "DJ2110002010010409943020008", // Djibouti
115 "DK5000400440116243", // Denmark
116 "DO28BAGR00000001212453611324", // Dominican Republic
117 "EE382200221020145685", // Estonia
118 "ES8023100001180000012345", // Spain
119 "FI2112345600000785", // Finland
120 "FO6264600001631634", // Denmark (Faroes)
121 "FR1420041010050500013M02606", // France
122 "GB29NWBK60161331926819", // UK
123 "GI75NWBK000000007099453", // Gibraltar
124 "GL8964710001000206", // Denmark (Greenland)
125 "GR1601101250000000012300695", // Greece
126 "GT82TRAJ01020000001210029690", // Guatemala
127 "HR1210010051863000160", // Croatia
128 "HU42117730161111101800000000", // Hungary
129 "IE29AIBK93115212345678", // Ireland
130 "IL620108000000099999999", // Israel
131 "IQ98NBIQ850123456789012", // Iraq
132 "IS140159260076545510730339", // Iceland
133 "IT60X0542811101000000123456", // Italy
134 "JO94CBJO0010000000000131000302", // Jordan
135 "KW81CBKU0000000000001234560101", // Kuwait
136 "KZ86125KZT5004100100", // Kazakhstan
137 "LB62099900000001001901229114", // Lebanon
138 "LC55HEMM000100010012001200023015", // Saint Lucia
139 "LI21088100002324013AA", // Liechtenstein (Principality of)
140 "LT121000011101001000", // Lithuania
141 "LU280019400644750000", // Luxembourg
142 "LV80BANK0000435195001", // Latvia
143 "MC5811222000010123456789030", // Monaco
144 "MD24AG000225100013104168", // Moldova
145 "ME25505000012345678951", // Montenegro
146 "MK07250120000058984", // Macedonia, Former Yugoslav Republic of
147 "MR1300020001010000123456753", // Mauritania
148 "MT84MALT011000012345MTLCAST001S", // Malta
149 "MU17BOMM0101101030300200000MUR", // Mauritius
150 "NL39RABO0300065264", // Netherlands
151 "NL91ABNA0417164300", // Netherlands
152 "NO9386011117947", // Norway
153 "PK36SCBL0000001123456702", // Pakistan
154 "PL27114020040000300201355387", // Poland
155 "PL60102010260000042270201111", // Poland
156 "PS92PALS000000000400123456702", // Palestine, State of
157 "PT50000201231234567890154", // Portugal
158 "QA58DOHB00001234567890ABCDEFG", // Qatar
159 "RO49AAAA1B31007593840000", // Romania
160 "RS35260005601001611379", // Serbia
161 "RU0204452560040702810412345678901", // Russia
162 "SA0380000000608010167519", // Saudi Arabia
163 "SC18SSCB11010000000000001497USD", // Seychelles
164 "SD8811123456789012", // Sudan
165 "SE3550000000054910000003", // Sweden
166 "SD2129010501234001", // Sudan
167 "SI56191000000123438", // Slovenia
168 "SK3112000000198742637541", // Slovak Republic
169 "SM86U0322509800000000270100", // San Marino
170 "ST68000100010051845310112", // Sao Tome and Principe
171 "SV62CENR00000000000000700025", // El Salvador
172 "TL380080012345678910157", // Timor-Leste
173 "TN5910006035183598478831", // Tunisia
174 "TR330006100519786457841326", // Turkey
175 "UA213223130000026007233566001", // Ukraine
176 "VA59001123000012345678", // Vatican City State
177 "VG96VPVG0000012345678901", // Virgin Islands, British
178 "XK051212012345678906", // Republic of Kosovo
179
180 // Codes AA and ZZ will never be used as ISO countries nor in IBANs
181 // add some dummy calculated codes to test the limits
182 // Current minimum length is Norway = 15
183 // Current maximum length is Malta = 31
184 // These codes will fail online checkers which validate the IBAN format
185 // 234567890123456789012345678901
186 "AA0200000000053", "AA9700000000089", "AA9800000000071", "ZZ02ZZZZZZZZZZZZZZZZZZZZZZZZZ04", "ZZ97ZZZZZZZZZZZZZZZZZZZZZZZZZ40",
187 "ZZ98ZZZZZZZZZZZZZZZZZZZZZZZZZ22", };
188 /*
189 * sources https://intranet.birmingham.ac.uk/finance/documents/public/IBAN.pdf
190 * http://www.paymentscouncil.org.uk/resources_and_publications/ibans_in_europe/
191 */
192 invalid = new String[] { "510007+47061BE63", "IE01AIBK93118702569045", "AA0000000000089", "AA9900000000053", };
193 zeroSum = null;
194 missingMessage = "Invalid Code length=0";
195
196 }
197
198 @Test
199 void testOther() throws Exception {
200 try (BufferedReader rdr = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream("IBANtests.txt"), "ASCII"))) {
201 String line;
202 while ((line = rdr.readLine()) != null) {
203 if (!line.startsWith("#") && !line.isEmpty()) {
204 if (line.startsWith("-")) {
205 line = line.substring(1);
206 assertFalse(routine.isValid(line.replace(" ", "")), line);
207 } else {
208 assertTrue(routine.isValid(line.replace(" ", "")), line);
209 }
210 }
211 }
212 }
213 }
214
215 /**
216 * Test zero sum
217 */
218 @Override
219 @Test
220 void testZeroSum() {
221 // ignore, don't run this test
222
223 // example code used to create dummy IBANs
224 // try {
225 // for(int i=0; i<97;i++) {
226 // String check = String.format("ZZ00ZZZZZZZZZZZZZZZZZZZZZZZZZ%02d", new Object[]{Integer.valueOf(i)});
227 // String chk = routine.calculate(check);
228 // if (chk.equals("97")||chk.equals("98")||chk.equals("02")) {
229 // System.out.println(check+ " "+chk);
230 // }
231 // }
232 // } catch (CheckDigitException e) {
233 // e.printStackTrace();
234 // }
235 }
236 }