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