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 junit.framework.TestCase;
24 * @author satorux@google.com (Satoru Takabayashi) - creator
25 * @author mysen@google.com (Chris Mysen) - ported from C++
27 public final class EncoderTestCase extends TestCase {
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));
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));
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(':'));
51 // Should return -1 for other letters;
52 assertEquals(-1, Encoder.getAlphanumericCode('a'));
53 assertEquals(-1, Encoder.getAlphanumericCode('#'));
54 assertEquals(-1, Encoder.getAlphanumericCode('\0'));
57 public void testChooseMode() throws WriterException {
59 assertEquals(QRCode.MODE_NUMERIC, Encoder.chooseMode(new ByteArray("0")));
60 assertEquals(QRCode.MODE_NUMERIC, Encoder.chooseMode(new ByteArray("0123456789")));
62 assertEquals(QRCode.MODE_ALPHANUMERIC, Encoder.chooseMode(new ByteArray("A")));
63 assertEquals(QRCode.MODE_ALPHANUMERIC,
64 Encoder.chooseMode(new ByteArray("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:")));
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.
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)));
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)));
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)));
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.
92 " mode: ALPHANUMERIC\n" +
95 " matrixWidth: 21\n" +
97 " numTotalBytes: 26\n" +
98 " numDataBytes: 9\n" +
100 " numRSBlocks: 1\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" +
124 assertEquals(expected, qrCode.toString());
127 public void testAppendModeInfo() throws WriterException {
128 BitVector bits = new BitVector();
129 Encoder.appendModeInfo(QRCode.MODE_NUMERIC, bits);
130 assertEquals("0001", bits.toString());
133 public void testAppendLengthInfo() throws WriterException {
135 BitVector bits = new BitVector();
136 Encoder.appendLengthInfo(1, // 1 letter (1/1).
140 assertEquals("0000000001", bits.toString()); // 10 bits.
143 BitVector bits = new BitVector();
144 Encoder.appendLengthInfo(2, // 2 letters (2/1).
146 QRCode.MODE_ALPHANUMERIC,
148 assertEquals("00000000010", bits.toString()); // 11 bits.
151 BitVector bits = new BitVector();
152 Encoder.appendLengthInfo(255, // 255 letter (255/1).
154 QRCode.MODE_8BIT_BYTE,
156 assertEquals("0000000011111111", bits.toString()); // 16 bits.
159 BitVector bits = new BitVector();
160 Encoder.appendLengthInfo(1024, // 512 letters (1024/2).
164 assertEquals("001000000000", bits.toString()); // 12 bits.
168 public void testAppendBytes() throws WriterException {
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.
177 Encoder.appendBytes(new ByteArray("A"), QRCode.MODE_NUMERIC, bits);
178 fail("Should have thrown exception");
179 } catch (WriterException we) {
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.
191 Encoder.appendBytes(new ByteArray("a"), QRCode.MODE_ALPHANUMERIC, bits);
192 } catch (WriterException we) {
197 // Should use append8BitBytes.
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);
207 // Should use appendKanjiBytes.
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.
216 Encoder.appendBytes(new ByteArray("a"), QRCode.MODE_KANJI, bits);
217 } catch (WriterException we) {
223 public void testInit() {
224 // TODO: should be implemented.
227 public void testTerminateBits() throws WriterException {
229 BitVector v = new BitVector();
230 Encoder.terminateBits(0, v);
231 assertEquals("", v.toString());
234 BitVector v = new BitVector();
235 Encoder.terminateBits(1, v);
236 assertEquals("00000000", v.toString());
239 BitVector v = new BitVector();
240 v.appendBits(0, 3); // Append 000
241 Encoder.terminateBits(1, v);
242 assertEquals("00000000", v.toString());
245 BitVector v = new BitVector();
246 v.appendBits(0, 5); // Append 00000
247 Encoder.terminateBits(1, v);
248 assertEquals("00000000", v.toString());
251 BitVector v = new BitVector();
252 v.appendBits(0, 8); // Append 00000000
253 Encoder.terminateBits(1, v);
254 assertEquals("00000000", v.toString());
257 BitVector v = new BitVector();
258 Encoder.terminateBits(2, v);
259 assertEquals("0000000011101100", v.toString());
262 BitVector v = new BitVector();
263 v.appendBits(0, 1); // Append 0
264 Encoder.terminateBits(3, v);
265 assertEquals("000000001110110000010001", v.toString());
269 public void testGetNumDataBytesAndNumECBytesForBlockID() throws WriterException {
270 int[] numDataBytes = new int[1];
271 int[] numEcBytes = new int[1];
273 Encoder.getNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0, numDataBytes, numEcBytes);
274 assertEquals(9, numDataBytes[0]);
275 assertEquals(17, numEcBytes[0]);
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]);
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]);
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]);
305 public void testInterleaveWithECBytes() throws WriterException {
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);
312 BitVector out = new BitVector();
313 Encoder.interleaveWithECBytes(in, 26, 9, 1, out);
314 final byte[] expected = {
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,
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]);
328 // Numbers are from http://www.swetake.com/qr/qr8.html
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,
338 BitVector in = new BitVector();
339 for (byte dataByte: dataBytes) {
340 in.appendBits(dataByte, 8);
342 BitVector out = new BitVector();
343 Encoder.interleaveWithECBytes(in, 134, 62, 4, out);
344 final byte[] expected = {
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,
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,
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]);
369 public void testAppendNumericBytes() throws WriterException {
371 // 1 = 01 = 0001 in 4 bits.
372 BitVector bits = new BitVector();
373 Encoder.appendNumericBytes(new ByteArray("1"), bits);
374 assertEquals("0001" , bits.toString());
377 // 12 = 0xc = 0001100 in 7 bits.
378 BitVector bits = new BitVector();
379 Encoder.appendNumericBytes(new ByteArray("12"), bits);
380 assertEquals("0001100" , bits.toString());
383 // 123 = 0x7b = 0001111011 in 10 bits.
384 BitVector bits = new BitVector();
385 Encoder.appendNumericBytes(new ByteArray("123"), bits);
386 assertEquals("0001111011" , bits.toString());
389 // 1234 = "123" + "4" = 0001111011 + 0100
390 BitVector bits = new BitVector();
391 Encoder.appendNumericBytes(new ByteArray("1234"), bits);
392 assertEquals("0001111011" + "0100" , bits.toString());
396 BitVector bits = new BitVector();
397 Encoder.appendNumericBytes(new ByteArray(""), bits);
398 assertEquals("" , bits.toString());
402 BitVector bits = new BitVector();
404 Encoder.appendNumericBytes(new ByteArray("abc"), bits);
405 } catch (WriterException we) {
411 public void testAppendAlphanumericBytes() throws WriterException {
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());
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());
425 // ABC = "AB" + "C" = 00111001101 + 001100
426 BitVector bits = new BitVector();
427 Encoder.appendAlphanumericBytes(new ByteArray("ABC"), bits);
428 assertEquals("00111001101" + "001100" , bits.toString());
432 BitVector bits = new BitVector();
433 Encoder.appendAlphanumericBytes(new ByteArray(""), bits);
434 assertEquals("" , bits.toString());
438 BitVector bits = new BitVector();
440 Encoder.appendAlphanumericBytes(new ByteArray("abc"), bits);
441 } catch (WriterException we) {
447 public void testAppend8BitBytes() throws WriterException {
450 BitVector bits = new BitVector();
451 Encoder.append8BitBytes(new ByteArray("abc"), bits);
452 assertEquals("01100001" + "01100010" + "01100011", bits.toString());
456 BitVector bits = new BitVector();
457 Encoder.append8BitBytes(new ByteArray(""), bits);
458 assertEquals("", bits.toString());
462 // Numbers are from page 21 of JISX0510:2004
463 public void testAppendKanjiBytes() throws WriterException {
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());
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) {
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);
494 // // Numbers are from Appendix A of JISX0510 2004 (p.59).
495 // public void testGetECPoly() {
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));
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,
507 // assertTrue(ComparePoly(expected, expected.length, poly));
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,
515 // 158, 229, 239, 218, 103, 56, 70, 114,
516 // 61, 183, 129, 167, 13, 98, 62, 129, 51
518 // assertTrue(ComparePoly(expected, expected.length, poly));
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,
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,
531 // 32, 82, 215, 175, 198, 43, 238, 235,
532 // 27, 101, 184, 127, 3, 5, 8, 163, 238
534 // assertTrue(ComparePoly(expected, expected.length, poly));
538 // Numbers are from http://www.swetake.com/qr/qr3.html and
539 // http://www.swetake.com/qr/qr9.html
540 public void testGenerateECBytes() {
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
547 assertEquals(expected.length, ecBytes.size());
548 for (int x = 0; x < expected.length; x++) {
549 assertEquals(expected[x], ecBytes.at(x));
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
559 assertEquals(expected.length, ecBytes.size());
560 for (int x = 0; x < expected.length; x++) {
561 assertEquals(expected[x], ecBytes.at(x));
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
571 assertEquals(expected.length, ecBytes.size());
572 for (int x = 0; x < expected.length; x++) {
573 assertEquals(expected[x], ecBytes.at(x));
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.
585 assertFalse(Encoder.isValidKanji('0', '1'));
586 assertFalse(Encoder.isValidKanji(0x82, 0x7f));
587 assertFalse(Encoder.isValidKanji(0xa0, 0xa0));
590 public void testIsValidKanjiSequence() {
593 (byte)0x83, 0x41, (byte)0x83, 0x43, (byte)0x83, 0x45, (byte)0x83, 0x47, (byte)0x83, 0x49
595 assertTrue(Encoder.isValidKanjiSequence(new ByteArray(dat1)));
596 // 012345 in multi-byte letters.
598 (byte)0x82, 0x4f, (byte)0x82, 0x50, (byte)0x82, 0x51, (byte)0x82, 0x52, (byte)0x82, 0x53,
601 assertTrue(Encoder.isValidKanjiSequence(new ByteArray(dat2)));
602 // Yoroshiku in Kanji.
604 (byte)0x96, (byte)0xe9, (byte)0x98, 0x49, (byte)0x8e, (byte)0x80, (byte)0x8b, (byte)0xea
606 assertTrue(Encoder.isValidKanjiSequence(new ByteArray(dat3)));
607 assertFalse(Encoder.isValidKanjiSequence(new ByteArray("0123")));
608 assertFalse(Encoder.isValidKanjiSequence(new ByteArray("ABC")));
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.
621 // Before the bug was fixed, the following test didn't pass, because:
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
640 final int arraySize = 3518;
641 byte[] dataBytes = new byte[arraySize];
642 for (int x = 0; x < arraySize; x++) {
645 QRCode qrCode = new QRCode();
646 Encoder.encode(new ByteArray(dataBytes), QRCode.EC_LEVEL_L, qrCode);