Big rename of variables and method to have more standard Java names
[zxing.git] / core / test / src / com / google / zxing / qrcode / encoder / EncoderTestCase.java
1 /*
2  * Copyright 2008 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.qrcode.encoder;
18
19 import com.google.zxing.common.ByteArray;
20 import com.google.zxing.WriterException;
21 import junit.framework.TestCase;
22
23 /**
24  * @author satorux@google.com (Satoru Takabayashi) - creator
25  * @author mysen@google.com (Chris Mysen) - ported from C++
26  */
27 public final class EncoderTestCase extends TestCase {
28
29   public void testGetAlphanumericCode() throws WriterException {
30     // The first ten code points are numbers.
31     for (int i = 0; i < 10; ++i) {
32       assertEquals(i, Encoder.getAlphanumericCode('0' + i));
33     }
34
35     // The next 26 code points are capital alphabet letters.
36     for (int i = 10; i < 36; ++i) {
37       assertEquals(i, Encoder.getAlphanumericCode('A' + i - 10));
38     }
39
40     // Others are symbol letters
41     assertEquals(36, Encoder.getAlphanumericCode(' '));
42     assertEquals(37, Encoder.getAlphanumericCode('$'));
43     assertEquals(38, Encoder.getAlphanumericCode('%'));
44     assertEquals(39, Encoder.getAlphanumericCode('*'));
45     assertEquals(40, Encoder.getAlphanumericCode('+'));
46     assertEquals(41, Encoder.getAlphanumericCode('-'));
47     assertEquals(42, Encoder.getAlphanumericCode('.'));
48     assertEquals(43, Encoder.getAlphanumericCode('/'));
49     assertEquals(44, Encoder.getAlphanumericCode(':'));
50
51     // Should return -1 for other letters;
52     assertEquals(-1, Encoder.getAlphanumericCode('a'));
53     assertEquals(-1, Encoder.getAlphanumericCode('#'));
54     assertEquals(-1, Encoder.getAlphanumericCode('\0'));
55   }
56
57   public void testChooseMode() throws WriterException {
58     // Numeric mode.
59     assertEquals(QRCode.MODE_NUMERIC, Encoder.chooseMode(new ByteArray("0")));
60     assertEquals(QRCode.MODE_NUMERIC, Encoder.chooseMode(new ByteArray("0123456789")));
61     // Alphanumeric mode.
62     assertEquals(QRCode.MODE_ALPHANUMERIC, Encoder.chooseMode(new ByteArray("A")));
63     assertEquals(QRCode.MODE_ALPHANUMERIC,
64         Encoder.chooseMode(new ByteArray("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:")));
65     // 8-bit byte mode.
66     assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray("a")));
67     assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray("#")));
68     assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray("")));
69     // Kanji mode.  We used to use MODE_KANJI for these, but we stopped
70     // doing that as we cannot distinguish Shift_JIS from other encodings
71     // from data bytes alone.  See also comments in qrcode_encoder.h.
72
73     // AIUE in Hiragana in Shift_JIS
74     byte[] dat1 = {0x8,0xa,0x8,0xa,0x8,0xa,0x8,(byte)0xa6};
75     assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray(dat1)));
76
77     // Nihon in Kanji in Shift_JIS.
78     byte[] dat2 = {0x9,0xf,0x9,0x7b};
79     assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray(dat2)));
80
81     // Sou-Utsu-Byou in Kanji in Shift_JIS.
82     byte[] dat3 = {0xe,0x4,0x9,0x5,0x9,0x61};
83     assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray(dat3)));
84   }
85
86   public void testEncode() throws WriterException {
87     QRCode qrCode = new QRCode();
88     Encoder.encode(new ByteArray("ABCDEF"), QRCode.EC_LEVEL_H, qrCode);
89     // The following is a valid QR Code that can be read by cell phones.
90     String expected =
91       "<<\n" +
92       " mode: ALPHANUMERIC\n" +
93       " ecLevel: H\n" +
94       " version: 1\n" +
95       " matrixWidth: 21\n" +
96       " maskPattern: 0\n" +
97       " numTotalBytes: 26\n" +
98       " numDataBytes: 9\n" +
99       " numECBytes: 17\n" +
100       " numRSBlocks: 1\n" +
101       " matrix:\n" +
102       " 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1\n" +
103       " 1 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 1\n" +
104       " 1 0 1 1 1 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 1\n" +
105       " 1 0 1 1 1 0 1 0 1 1 1 0 1 0 1 0 1 1 1 0 1\n" +
106       " 1 0 1 1 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1\n" +
107       " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1\n" +
108       " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n" +
109       " 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0\n" +
110       " 0 0 1 0 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1\n" +
111       " 1 0 1 1 1 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0\n" +
112       " 0 0 1 1 0 0 1 0 1 0 0 0 1 0 1 0 1 0 1 1 0\n" +
113       " 1 1 0 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0\n" +
114       " 0 0 1 1 0 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0\n" +
115       " 0 0 0 0 0 0 0 0 1 0 0 1 1 1 0 1 0 1 0 0 0\n" +
116       " 1 1 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0 1\n" +
117       " 1 0 0 0 0 0 1 0 1 1 1 1 0 1 0 1 1 1 1 0 1\n" +
118       " 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 1 0 0 0 0 1\n" +
119       " 1 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 1 0\n" +
120       " 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 1 1 1 0 1\n" +
121       " 1 0 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 0 1 1\n" +
122       " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 1 0 1\n" +
123       ">>\n";
124     assertEquals(expected, qrCode.toString());
125   }
126
127   public void testAppendModeInfo() throws WriterException {
128     BitVector bits = new BitVector();
129     Encoder.appendModeInfo(QRCode.MODE_NUMERIC, bits);
130     assertEquals("0001", bits.toString());
131   }
132
133   public void testAppendLengthInfo() throws WriterException {
134     {
135       BitVector bits = new BitVector();
136       Encoder.appendLengthInfo(1,  // 1 letter (1/1).
137                                                   1,  // version 1.
138                                                   QRCode.MODE_NUMERIC,
139                                                   bits);
140       assertEquals("0000000001", bits.toString());  // 10 bits.
141     }
142     {
143       BitVector bits = new BitVector();
144       Encoder.appendLengthInfo(2,  // 2 letters (2/1).
145                                                   10,  // version 10.
146                                                   QRCode.MODE_ALPHANUMERIC,
147                                                   bits);
148       assertEquals("00000000010", bits.toString());  // 11 bits.
149     }
150     {
151       BitVector bits = new BitVector();
152       Encoder.appendLengthInfo(255,  // 255 letter (255/1).
153                                                   27,  // version 27.
154                                                   QRCode.MODE_8BIT_BYTE,
155                                                   bits);
156       assertEquals("0000000011111111", bits.toString());  // 16 bits.
157     }
158     {
159       BitVector bits = new BitVector();
160       Encoder.appendLengthInfo(1024,  // 512 letters (1024/2).
161                                                   40,  // version 40.
162                                                   QRCode.MODE_KANJI,
163                                                   bits);
164       assertEquals("001000000000", bits.toString());  // 12 bits.
165     }
166   }
167
168   public void testAppendBytes() throws WriterException {
169     {
170       // Should use appendNumericBytes.
171       // 1 = 01 = 0001 in 4 bits.
172       BitVector bits = new BitVector();
173       Encoder.appendBytes(new ByteArray("1"), QRCode.MODE_NUMERIC, bits);
174       assertEquals("0001" , bits.toString());
175       // 'A' cannot be encoded in MODE_NUMERIC.
176       try {
177         Encoder.appendBytes(new ByteArray("A"), QRCode.MODE_NUMERIC, bits);
178         fail("Should have thrown exception");
179       } catch (WriterException we) {
180         // good
181       }
182     }
183     {
184       // Should use appendAlphanumericBytes.
185       // A = 10 = 0xa = 001010 in 6 bits
186       BitVector bits = new BitVector();
187       Encoder.appendBytes(new ByteArray("A"), QRCode.MODE_ALPHANUMERIC, bits);
188       assertEquals("001010" , bits.toString());
189       // Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC.
190       try {
191         Encoder.appendBytes(new ByteArray("a"), QRCode.MODE_ALPHANUMERIC, bits);
192       } catch (WriterException we) {
193         // good
194       }
195     }
196     {
197       // Should use append8BitBytes.
198       // 0x61, 0x62, 0x63
199       BitVector bits = new BitVector();
200       Encoder.appendBytes(new ByteArray("abc"), QRCode.MODE_8BIT_BYTE, bits);
201       assertEquals("01100001" + "01100010" + "01100011", bits.toString());
202       // Anything can be encoded in QRCode.MODE_8BIT_BYTE.
203       byte[] bytes = {0x00};
204       Encoder.appendBytes(new ByteArray(bytes), QRCode.MODE_8BIT_BYTE, bits);
205     }
206     {
207       // Should use appendKanjiBytes.
208       // 0x93, 0x5f
209       BitVector bits = new BitVector();
210       byte[] bytes = {(byte)0x93,0x5f};
211       Encoder.appendBytes(new ByteArray(bytes), QRCode.MODE_KANJI, bits);
212       assertEquals("0110110011111", bits.toString());
213       // ASCII characters can not be encoded in QRCode.MODE_KANJI.
214
215       try {
216         Encoder.appendBytes(new ByteArray("a"), QRCode.MODE_KANJI, bits);
217       } catch (WriterException we) {
218         // good
219       }
220     }
221   }
222
223   public void testInit() {
224     // TODO: should be implemented.
225   }
226
227   public void testTerminateBits() throws WriterException {
228     {
229       BitVector v = new BitVector();
230       Encoder.terminateBits(0, v);
231       assertEquals("", v.toString());
232     }
233     {
234       BitVector v = new BitVector();
235       Encoder.terminateBits(1, v);
236       assertEquals("00000000", v.toString());
237     }
238     {
239       BitVector v = new BitVector();
240       v.appendBits(0, 3);  // Append 000
241       Encoder.terminateBits(1, v);
242       assertEquals("00000000", v.toString());
243     }
244     {
245       BitVector v = new BitVector();
246       v.appendBits(0, 5);  // Append 00000
247       Encoder.terminateBits(1, v);
248       assertEquals("00000000", v.toString());
249     }
250     {
251       BitVector v = new BitVector();
252       v.appendBits(0, 8);  // Append 00000000
253       Encoder.terminateBits(1, v);
254       assertEquals("00000000", v.toString());
255     }
256     {
257       BitVector v = new BitVector();
258       Encoder.terminateBits(2, v);
259       assertEquals("0000000011101100", v.toString());
260     }
261     {
262       BitVector v = new BitVector();
263       v.appendBits(0, 1);  // Append 0
264       Encoder.terminateBits(3, v);
265       assertEquals("000000001110110000010001", v.toString());
266     }
267   }
268
269   public void testGetNumDataBytesAndNumECBytesForBlockID() throws WriterException {
270     int[] numDataBytes = new int[1];
271     int[] numEcBytes = new int[1];
272     // Version 1-H.
273     Encoder.getNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0, numDataBytes, numEcBytes);
274     assertEquals(9, numDataBytes[0]);
275     assertEquals(17, numEcBytes[0]);
276
277     // Version 3-H.  2 blocks.
278     Encoder.getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 0, numDataBytes, numEcBytes);
279     assertEquals(13, numDataBytes[0]);
280     assertEquals(22, numEcBytes[0]);
281     Encoder.getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 1, numDataBytes, numEcBytes);
282     assertEquals(13, numDataBytes[0]);
283     assertEquals(22, numEcBytes[0]);
284
285     // Version 7-H. (4 + 1) blocks.
286     Encoder.getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 0, numDataBytes, numEcBytes);
287     assertEquals(13, numDataBytes[0]);
288     assertEquals(26, numEcBytes[0]);
289     Encoder.getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 4, numDataBytes, numEcBytes);
290     assertEquals(14, numDataBytes[0]);
291     assertEquals(26, numEcBytes[0]);
292
293     // Version 40-H. (20 + 61) blocks.
294     Encoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 0, numDataBytes, numEcBytes);
295     assertEquals(15, numDataBytes[0]);
296     assertEquals(30, numEcBytes[0]);
297     Encoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 20, numDataBytes, numEcBytes);
298     assertEquals(16, numDataBytes[0]);
299     assertEquals(30, numEcBytes[0]);
300     Encoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 80, numDataBytes, numEcBytes);
301     assertEquals(16, numDataBytes[0]);
302     assertEquals(30, numEcBytes[0]);
303   }
304
305   public void testInterleaveWithECBytes() throws WriterException {
306     {
307       final byte[] dataBytes = {32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236};
308       BitVector in = new BitVector();
309       for (byte dataByte: dataBytes) {
310         in.appendBits(dataByte, 8);
311       }
312       BitVector out = new BitVector();
313       Encoder.interleaveWithECBytes(in, 26, 9, 1, out);
314       final byte[] expected = {
315           // Data bytes.
316           32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236,
317           // Error correction bytes.
318           42, (byte)159, 74, (byte)221, (byte)244, (byte)169, (byte)239, (byte)150, (byte)138, 70,
319           (byte)237, 85, (byte)224, 96, 74, (byte)219, 61,
320       };
321       assertEquals(expected.length, out.sizeInBytes());
322       final byte[] outArray = out.getArray();
323       // Can't use Arrays.equals(), because outArray may be longer than out.sizeInBytes()
324       for (int x = 0; x < expected.length; x++) {
325         assertEquals(expected[x], outArray[x]);
326       }
327     }
328     // Numbers are from http://www.swetake.com/qr/qr8.html
329     {
330       final byte[] dataBytes = {
331           67, 70, 22, 38, 54, 70, 86, 102, 118, (byte)134, (byte)150, (byte)166, (byte)182,
332           (byte)198, (byte)214, (byte)230, (byte)247, 7, 23, 39, 55, 71, 87, 103, 119, (byte)135,
333           (byte)151, (byte)166, 22, 38, 54, 70, 86, 102, 118, (byte)134, (byte)150, (byte)166,
334           (byte)182, (byte)198, (byte)214, (byte)230, (byte)247, 7, 23, 39, 55, 71, 87, 103, 119,
335           (byte)135, (byte)151, (byte)160, (byte)236, 17, (byte)236, 17, (byte)236, 17, (byte)236,
336           17
337       };
338       BitVector in = new BitVector();
339       for (byte dataByte: dataBytes) {
340         in.appendBits(dataByte, 8);
341       }
342       BitVector out = new BitVector();
343       Encoder.interleaveWithECBytes(in, 134, 62, 4, out);
344       final byte[] expected = {
345           // Data bytes.
346           67, (byte)230, 54, 55, 70, (byte)247, 70, 71, 22, 7, 86, 87, 38, 23, 102, 103, 54, 39,
347           118, 119, 70, 55, (byte)134, (byte)135, 86, 71, (byte)150, (byte)151, 102, 87, (byte)166,
348           (byte)160, 118, 103, (byte)182, (byte)236, (byte)134, 119, (byte)198, 17, (byte)150,
349           (byte)135, (byte)214, (byte)236, (byte)166, (byte)151, (byte)230, 17, (byte)182,
350           (byte)166, (byte)247, (byte)236, (byte)198, 22, 7, 17, (byte)214, 38, 23, (byte)236, 39,
351           17,
352           // Error correction bytes.
353           (byte)175, (byte)155, (byte)245, (byte)236, 80, (byte)146, 56, 74, (byte)155, (byte)165,
354           (byte)133, (byte)142, 64, (byte)183, (byte)132, 13, (byte)178, 54, (byte)132, 108, 45,
355           113, 53, 50, (byte)214, 98, (byte)193, (byte)152, (byte)233, (byte)147, 50, 71, 65,
356           (byte)190, 82, 51, (byte)209, (byte)199, (byte)171, 54, 12, 112, 57, 113, (byte)155, 117,
357           (byte)211, (byte)164, 117, 30, (byte)158, (byte)225, 31, (byte)190, (byte)242, 38,
358           (byte)140, 61, (byte)179, (byte)154, (byte)214, (byte)138, (byte)147, 87, 27, 96, 77, 47,
359           (byte)187, 49, (byte)156, (byte)214,
360       };
361       assertEquals(expected.length, out.sizeInBytes());
362       final byte[] outArray = out.getArray();
363       for (int x = 0; x < expected.length; x++) {
364         assertEquals(expected[x], outArray[x]);
365       }
366     }
367   }
368
369   public void testAppendNumericBytes() throws WriterException {
370     {
371       // 1 = 01 = 0001 in 4 bits.
372       BitVector bits = new BitVector();
373       Encoder.appendNumericBytes(new ByteArray("1"), bits);
374       assertEquals("0001" , bits.toString());
375     }
376     {
377       // 12 = 0xc = 0001100 in 7 bits.
378       BitVector bits = new BitVector();
379       Encoder.appendNumericBytes(new ByteArray("12"), bits);
380       assertEquals("0001100" , bits.toString());
381     }
382     {
383       // 123 = 0x7b = 0001111011 in 10 bits.
384       BitVector bits = new BitVector();
385       Encoder.appendNumericBytes(new ByteArray("123"), bits);
386       assertEquals("0001111011" , bits.toString());
387     }
388     {
389       // 1234 = "123" + "4" = 0001111011 + 0100
390       BitVector bits = new BitVector();
391       Encoder.appendNumericBytes(new ByteArray("1234"), bits);
392       assertEquals("0001111011" + "0100" , bits.toString());
393     }
394     {
395       // Empty.
396       BitVector bits = new BitVector();
397       Encoder.appendNumericBytes(new ByteArray(""), bits);
398       assertEquals("" , bits.toString());
399     }
400     {
401       // Invalid data.
402       BitVector bits = new BitVector();
403       try {
404         Encoder.appendNumericBytes(new ByteArray("abc"), bits);
405       } catch (WriterException we) {
406         // good
407       }
408     }
409   }
410
411   public void testAppendAlphanumericBytes() throws WriterException {
412     {
413       // A = 10 = 0xa = 001010 in 6 bits
414       BitVector bits = new BitVector();
415       Encoder.appendAlphanumericBytes(new ByteArray("A"), bits);
416       assertEquals("001010" , bits.toString());
417     }
418     {
419       // AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits
420       BitVector bits = new BitVector();
421       Encoder.appendAlphanumericBytes(new ByteArray("AB"), bits);
422       assertEquals("00111001101", bits.toString());
423     }
424     {
425       // ABC = "AB" + "C" = 00111001101 + 001100
426       BitVector bits = new BitVector();
427       Encoder.appendAlphanumericBytes(new ByteArray("ABC"), bits);
428       assertEquals("00111001101" + "001100" , bits.toString());
429     }
430     {
431       // Empty.
432       BitVector bits = new BitVector();
433       Encoder.appendAlphanumericBytes(new ByteArray(""), bits);
434       assertEquals("" , bits.toString());
435     }
436     {
437       // Invalid data.
438       BitVector bits = new BitVector();
439       try {
440         Encoder.appendAlphanumericBytes(new ByteArray("abc"), bits);
441       } catch (WriterException we) {
442         // good
443       }
444     }
445   }
446
447   public void testAppend8BitBytes() throws WriterException {
448     {
449       // 0x61, 0x62, 0x63
450       BitVector bits = new BitVector();
451       Encoder.append8BitBytes(new ByteArray("abc"), bits);
452       assertEquals("01100001" + "01100010" + "01100011", bits.toString());
453     }
454     {
455       // Empty.
456       BitVector bits = new BitVector();
457       Encoder.append8BitBytes(new ByteArray(""), bits);
458       assertEquals("", bits.toString());
459     }
460   }
461
462   // Numbers are from page 21 of JISX0510:2004
463   public void testAppendKanjiBytes() throws WriterException {
464     {
465       BitVector bits = new BitVector();
466       byte[] dat1 = {(byte)0x93,0x5f};
467       Encoder.appendKanjiBytes(new ByteArray(dat1), bits);
468       assertEquals("0110110011111", bits.toString());
469       byte[] dat2 = {(byte)0xe4,(byte)0xaa};
470       Encoder.appendKanjiBytes(new ByteArray(dat2), bits);
471       assertEquals("0110110011111" + "1101010101010", bits.toString());
472     }
473   }
474
475   // JAVAPORT: Uncomment and fix up with new Reed Solomon objects
476 //  static boolean ComparePoly(final int[] expected, final int size, final GF_Poly poly) {
477 //    if (size != poly.degree() + 1) {
478 //      return false;
479 //    }
480 //    for (int i = 0; i < size; ++i) {
481 //      // "expected" is ordered in a reverse order.  We reverse the coeff
482 //      // index for comparison.
483 //      final int coeff = GaloisField.GetField(8).Log(
484 //          poly.coeff(size - i - 1));
485 //      if (expected[i] != coeff) {
486 //        Debug.LOG_ERROR("values don't match at " + i + ": " +
487 //            expected[i] + " vs. " + coeff);
488 //        return false;
489 //      }
490 //    }
491 //    return true;
492 //  }
493 //
494 //  // Numbers are from Appendix A of JISX0510 2004 (p.59).
495 //  public void testGetECPoly() {
496 //    {
497 //      final GF_Poly poly = Encoder.GetECPoly(7);
498 //      final int[] expected = {0, 87, 229, 146, 149, 238, 102, 21};
499 //      assertTrue(ComparePoly(expected, expected.length, poly));
500 //    }
501 //    {
502 //      final GF_Poly poly = Encoder.GetECPoly(17);
503 //      final int[] expected = {
504 //          0, 43, 139, 206, 78, 43, 239, 123, 206, 214, 147, 24, 99, 150,
505 //          39, 243, 163, 136
506 //      };
507 //      assertTrue(ComparePoly(expected, expected.length, poly));
508 //    }
509 //    {
510 //      final GF_Poly poly = Encoder.GetECPoly(34);
511 //      final int[] expected = {
512 //          0, 111, 77, 146, 94, 26, 21, 108, 19,
513 //          105, 94, 113, 193, 86, 140, 163, 125,
514 //          58,
515 //          158, 229, 239, 218, 103, 56, 70, 114,
516 //          61, 183, 129, 167, 13, 98, 62, 129, 51
517 //      };
518 //      assertTrue(ComparePoly(expected, expected.length, poly));
519 //    }
520 //    {
521 //      final GF_Poly poly = Encoder.GetECPoly(68);
522 //      final int[] expected = {
523 //          0, 247, 159, 223, 33, 224, 93, 77, 70,
524 //          90, 160, 32, 254, 43, 150, 84, 101,
525 //          190,
526 //          205, 133, 52, 60, 202, 165, 220, 203,
527 //          151, 93, 84, 15, 84, 253, 173, 160,
528 //          89, 227, 52, 199, 97, 95, 231, 52,
529 //          177, 41, 125, 137, 241, 166, 225, 118,
530 //          2, 54,
531 //          32, 82, 215, 175, 198, 43, 238, 235,
532 //          27, 101, 184, 127, 3, 5, 8, 163, 238
533 //      };
534 //      assertTrue(ComparePoly(expected, expected.length, poly));
535 //    }
536 //  }
537
538   // Numbers are from http://www.swetake.com/qr/qr3.html and
539   // http://www.swetake.com/qr/qr9.html
540   public void testGenerateECBytes() {
541     {
542       final byte[] dataBytes = {32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236};
543       ByteArray ecBytes = Encoder.generateECBytes(new ByteArray(dataBytes), 17);
544       final int[] expected = {
545           42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61
546       };
547       assertEquals(expected.length, ecBytes.size());
548       for (int x = 0; x < expected.length; x++) {
549         assertEquals(expected[x], ecBytes.at(x));
550       }
551     }
552     {
553       final byte[] dataBytes = {67, 70, 22, 38, 54, 70, 86, 102, 118,
554           (byte)134, (byte)150, (byte)166, (byte)182, (byte)198, (byte)214};
555       ByteArray ecBytes = Encoder.generateECBytes(new ByteArray(dataBytes), 18);
556       final int[] expected = {
557           175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187
558       };
559       assertEquals(expected.length, ecBytes.size());
560       for (int x = 0; x < expected.length; x++) {
561         assertEquals(expected[x], ecBytes.at(x));
562       }
563     }
564     {
565       // High-order zero cofficient case.
566       final byte[] dataBytes = {32, 49, (byte)205, 69, 42, 20, 0, (byte)236, 17};
567       ByteArray ecBytes = Encoder.generateECBytes(new ByteArray(dataBytes), 17);
568       final int[] expected = {
569           0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213
570       };
571       assertEquals(expected.length, ecBytes.size());
572       for (int x = 0; x < expected.length; x++) {
573         assertEquals(expected[x], ecBytes.at(x));
574       }
575     }
576   }
577
578   public void testIsValidKanji() {
579     assertTrue(Encoder.isValidKanji(0x82, 0xa0));  // Hiragana "A".
580     assertTrue(Encoder.isValidKanji(0x93, 0xfa));  // Nichi in Kanji.
581     assertTrue(Encoder.isValidKanji(0x8a, 0xbf));  // Kan in Kanji.
582     assertTrue(Encoder.isValidKanji(0xe7, 0x4e));  // Sou in Kanji.
583     assertTrue(Encoder.isValidKanji(0xea, 0xa2));  // Haruka in Kanji.
584
585     assertFalse(Encoder.isValidKanji('0', '1'));
586     assertFalse(Encoder.isValidKanji(0x82, 0x7f));
587     assertFalse(Encoder.isValidKanji(0xa0, 0xa0));
588   }
589
590   public void testIsValidKanjiSequence() {
591     // AIUEO in Katakana
592     byte[] dat1 = {
593         (byte)0x83, 0x41, (byte)0x83, 0x43, (byte)0x83, 0x45, (byte)0x83, 0x47, (byte)0x83, 0x49
594     };
595     assertTrue(Encoder.isValidKanjiSequence(new ByteArray(dat1)));
596     // 012345 in multi-byte letters.
597     byte[] dat2 = {
598         (byte)0x82, 0x4f, (byte)0x82, 0x50, (byte)0x82, 0x51, (byte)0x82, 0x52, (byte)0x82, 0x53,
599         (byte)0x82, 0x54
600     };
601     assertTrue(Encoder.isValidKanjiSequence(new ByteArray(dat2)));
602     // Yoroshiku in Kanji.
603     byte[] dat3 = {
604         (byte)0x96, (byte)0xe9, (byte)0x98, 0x49, (byte)0x8e, (byte)0x80, (byte)0x8b, (byte)0xea
605     };
606     assertTrue(Encoder.isValidKanjiSequence(new ByteArray(dat3)));
607     assertFalse(Encoder.isValidKanjiSequence(new ByteArray("0123")));
608     assertFalse(Encoder.isValidKanjiSequence(new ByteArray("ABC")));
609   }
610
611   public void testBugInBitVectorNumBytes() throws WriterException {
612     // There was a bug in BitVector.sizeInBytes() that caused it to return a
613     // smaller-by-one value (ex. 1465 instead of 1466) if the number of bits
614     // in the vector is not 8-bit aligned.  In QRCodeEncoder::InitQRCode(),
615     // BitVector::sizeInBytes() is used for finding the smallest QR Code
616     // version that can fit the given data.  Hence there were corner cases
617     // where we chose a wrong QR Code version that cannot fit the given
618     // data.  Note that the issue did not occur with MODE_8BIT_BYTE, as the
619     // bits in the bit vector are always 8-bit aligned.
620     //
621     // Before the bug was fixed, the following test didn't pass, because:
622     //
623     // - MODE_NUMERIC is chosen as all bytes in the data are '0'
624     // - The 3518-byte numeric data needs 1466 bytes
625     //   - 3518 / 3 * 10 + 7 = 11727 bits = 1465.875 bytes
626     //   - 3 numeric bytes are encoded in 10 bits, hence the first
627     //     3516 bytes are encoded in 3516 / 3 * 10 = 11720 bits.
628     //   - 2 numeric bytes can be encoded in 7 bits, hence the last
629     //     2 bytes are encoded in 7 bits.
630     // - The version 27 QR Code with the EC level L has 1468 bytes for data.
631     //   - 1828 - 360 = 1468
632     // - In InitQRCode(), 3 bytes are reserved for a header.  Hence 1465 bytes
633     //   (1468 -3) are left for data.
634     // - Because of the bug in BitVector::sizeInBytes(), InitQRCode() determines
635     //   the given data can fit in 1465 bytes, despite it needs 1466 bytes.
636     // - Hence QRCodeEncoder.encode() failed and returned false.
637     //   - To be precise, it needs 11727 + 4 (getMode info) + 14 (length info) =
638     //     11745 bits = 1468.125 bytes are needed (i.e. cannot fit in 1468
639     //     bytes).
640     final int arraySize = 3518;
641     byte[] dataBytes = new byte[arraySize];
642     for (int x = 0; x < arraySize; x++) {
643       dataBytes[x] = '0';
644     }
645     QRCode qrCode = new QRCode();
646     Encoder.encode(new ByteArray(dataBytes), QRCode.EC_LEVEL_L, qrCode);
647   }
648 }