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