1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.validator.routines.checkdigit;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.ByteArrayOutputStream;
21 import java.io.ObjectInputStream;
22 import java.io.ObjectOutputStream;
23 import java.util.List;
24 import java.util.ArrayList;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import junit.framework.TestCase;
30
31
32
33
34
35
36
37 public abstract class AbstractCheckDigitTest extends TestCase {
38
39
40 protected Log log = LogFactory.getLog(getClass());
41
42
43 protected int checkDigitLth = 1;
44
45
46 protected CheckDigit routine;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 protected String[] valid;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 protected String[] invalid = new String[] {"12345678A"};
79
80
81 protected String zeroSum = "0000000000";
82
83
84 protected String missingMessage = "Code is missing";
85
86
87
88
89
90 public AbstractCheckDigitTest(String name) {
91 super(name);
92 }
93
94
95
96
97 @Override
98 protected void tearDown() throws Exception {
99 super.tearDown();
100 valid = null;
101 routine = null;
102 }
103
104
105
106
107 public void testIsValidTrue() {
108 if (log.isDebugEnabled()) {
109 log.debug("testIsValidTrue() for " + routine.getClass().getName());
110 }
111
112
113 for (int i = 0; i < valid.length; i++) {
114 if (log.isDebugEnabled()) {
115 log.debug(" " + i + " Testing Valid Code=[" + valid[i] + "]");
116 }
117 assertTrue("valid[" + i +"]: " + valid[i], routine.isValid(valid[i]));
118 }
119 }
120
121
122
123
124 public void testIsValidFalse() {
125 if (log.isDebugEnabled()) {
126 log.debug("testIsValidFalse() for " + routine.getClass().getName());
127 }
128
129
130 for (int i = 0; i < invalid.length; i++) {
131 if (log.isDebugEnabled()) {
132 log.debug(" " + i + " Testing Invalid Code=[" + invalid[i] + "]");
133 }
134 assertFalse("invalid[" + i +"]: " + invalid[i], routine.isValid(invalid[i]));
135 }
136
137
138 String[] invalidCheckDigits = createInvalidCodes(valid);
139 for (int i = 0; i < invalidCheckDigits.length; i++) {
140 if (log.isDebugEnabled()) {
141 log.debug(" " + i + " Testing Invalid Check Digit, Code=[" + invalidCheckDigits[i] + "]");
142 }
143 assertFalse("invalid check digit[" + i +"]: " + invalidCheckDigits[i], routine.isValid(invalidCheckDigits[i]));
144 }
145 }
146
147
148
149
150 public void testCalculateValid() {
151 if (log.isDebugEnabled()) {
152 log.debug("testCalculateValid() for " + routine.getClass().getName());
153 }
154
155
156 for (int i = 0; i < valid.length; i++) {
157 String code = removeCheckDigit(valid[i]);
158 String expected = checkDigit(valid[i]);
159 try {
160 if (log.isDebugEnabled()) {
161 log.debug(" " + i + " Testing Valid Check Digit, Code=[" + code + "] expected=[" + expected + "]");
162 }
163 assertEquals("valid[" + i +"]: " + valid[i], expected, routine.calculate(code));
164 } catch (Exception e) {
165 fail("valid[" + i +"]=" + valid[i] + " threw " + e);
166 }
167 }
168
169 }
170
171
172
173
174 public void testCalculateInvalid() {
175
176 if (log.isDebugEnabled()) {
177 log.debug("testCalculateInvalid() for " + routine.getClass().getName());
178 }
179
180
181 for (int i = 0; i < invalid.length; i++) {
182 try {
183 final String code = invalid[i];
184 if (log.isDebugEnabled()) {
185 log.debug(" " + i + " Testing Invalid Check Digit, Code=[" + code + "]");
186 }
187 String expected = checkDigit(code);
188 String actual = routine.calculate(removeCheckDigit(code));
189
190 if (expected.equals(actual)) {
191 fail("Expected mismatch for " + code + " expected " + expected + " actual " + actual);
192 }
193 } catch (CheckDigitException e) {
194
195
196
197
198 assertTrue("Invalid Character[" +i +"]=" + e.getMessage(), e.getMessage().startsWith("Invalid "));
199
200 }
201 }
202 }
203
204
205
206
207 public void testMissingCode() {
208
209
210 assertFalse("isValid() Null", routine.isValid(null));
211
212
213 assertFalse("isValid() Zero Length", routine.isValid(""));
214
215
216
217 assertFalse("isValid() Length 1", routine.isValid("9"));
218
219
220 try {
221 routine.calculate(null);
222 fail("calculate() Null - expected exception");
223 } catch (Exception e) {
224 assertEquals("calculate() Null", missingMessage, e.getMessage());
225 }
226
227
228 try {
229 routine.calculate("");
230 fail("calculate() Zero Length - expected exception");
231 } catch (Exception e) {
232 assertEquals("calculate() Zero Length", missingMessage, e.getMessage());
233 }
234 }
235
236
237
238
239 public void testZeroSum() {
240
241 assertFalse("isValid() Zero Sum", routine.isValid(zeroSum));
242
243 try {
244 routine.calculate(zeroSum);
245 fail("Zero Sum - expected exception");
246 } catch (Exception e) {
247 assertEquals("isValid() Zero Sum", "Invalid code, sum is zero", e.getMessage());
248 }
249
250 }
251
252
253
254
255 public void testSerialization() {
256
257 ByteArrayOutputStream baos = new ByteArrayOutputStream();
258 try {
259 ObjectOutputStream oos = new ObjectOutputStream(baos);
260 oos.writeObject(routine);
261 oos.flush();
262 oos.close();
263 } catch (Exception e) {
264 fail(routine.getClass().getName() + " error during serialization: " + e);
265 }
266
267
268 Object result = null;
269 try {
270 ByteArrayInputStream bais =
271 new ByteArrayInputStream(baos.toByteArray());
272 ObjectInputStream ois = new ObjectInputStream(bais);
273 result = ois.readObject();
274 bais.close();
275 } catch (Exception e) {
276 fail(routine.getClass().getName() + " error during deserialization: " + e);
277 }
278 assertNotNull(result);
279 }
280
281 private static final String POSSIBLE_CHECK_DIGITS = "0123456789 ABCDEFHIJKLMNOPQRSTUVWXYZ\tabcdefghijklmnopqrstuvwxyz!@£$%^&*()_+";
282
283
284
285
286
287
288
289 protected String[] createInvalidCodes(String[] codes) {
290 List<String> list = new ArrayList<String>();
291
292
293 for (String fullCode : codes) {
294 String code = removeCheckDigit(fullCode);
295 String check = checkDigit(fullCode);
296 for (int j = 0; j < POSSIBLE_CHECK_DIGITS.length(); j++) {
297 String curr = POSSIBLE_CHECK_DIGITS.substring(j, j + 1);
298 if (!curr.equals(check)) {
299 list.add(code + curr);
300 }
301 }
302 }
303
304 return list.toArray(new String[list.size()]);
305 }
306
307
308
309
310
311
312
313 protected String removeCheckDigit(String code) {
314 if (code == null || code.length() <= checkDigitLth) {
315 return null;
316 }
317 return code.substring(0, code.length() - checkDigitLth);
318 }
319
320
321
322
323
324
325
326 protected String checkDigit(String code) {
327 if (code == null || code.length() <= checkDigitLth) {
328 return "";
329 }
330 int start = code.length() - checkDigitLth;
331 return code.substring(start);
332 }
333
334 }