QREncoderTest.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. /*
  2. * Copyright 2008 ZXing authors
  3. */
  4. // SPDX-License-Identifier: Apache-2.0
  5. #include "BitArray.h"
  6. #include "BitArrayUtility.h"
  7. #include "BitMatrixIO.h"
  8. #include "CharacterSet.h"
  9. #include "TextDecoder.h"
  10. #include "Utf.h"
  11. #include "qrcode/QREncoder.h"
  12. #include "qrcode/QRCodecMode.h"
  13. #include "qrcode/QREncodeResult.h"
  14. #include "qrcode/QRErrorCorrectionLevel.h"
  15. #include "gtest/gtest.h"
  16. namespace ZXing {
  17. namespace QRCode {
  18. int GetAlphanumericCode(int code);
  19. CodecMode ChooseMode(const std::wstring& content, CharacterSet encoding);
  20. void AppendModeInfo(CodecMode mode, BitArray& bits);
  21. void AppendLengthInfo(int numLetters, const Version& version, CodecMode mode, BitArray& bits);
  22. void AppendNumericBytes(const std::wstring& content, BitArray& bits);
  23. void AppendAlphanumericBytes(const std::wstring& content, BitArray& bits);
  24. void Append8BitBytes(const std::wstring& content, CharacterSet encoding, BitArray& bits);
  25. void AppendKanjiBytes(const std::wstring& content, BitArray& bits);
  26. void AppendBytes(const std::wstring& content, CodecMode mode, CharacterSet encoding, BitArray& bits);
  27. void TerminateBits(int numDataBytes, BitArray& bits);
  28. void GetNumDataBytesAndNumECBytesForBlockID(int numTotalBytes, int numDataBytes, int numRSBlocks, int blockID, int& numDataBytesInBlock, int& numECBytesInBlock);
  29. void GenerateECBytes(const ByteArray& dataBytes, int numEcBytesInBlock, ByteArray& ecBytes);
  30. BitArray InterleaveWithECBytes(const BitArray& bits, int numTotalBytes, int numDataBytes, int numRSBlocks);
  31. }
  32. }
  33. using namespace ZXing;
  34. using namespace ZXing::QRCode;
  35. using namespace ZXing::Utility;
  36. namespace {
  37. std::wstring ShiftJISString(const std::vector<uint8_t>& bytes)
  38. {
  39. std::string str;
  40. TextDecoder::Append(str, bytes.data(), bytes.size(), CharacterSet::Shift_JIS);
  41. return FromUtf8(str);
  42. }
  43. std::string RemoveSpace(std::string s)
  44. {
  45. s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
  46. return s;
  47. }
  48. }
  49. TEST(QREncoderTest, GetAlphanumericCode)
  50. {
  51. // The first ten code points are numbers.
  52. for (int i = 0; i < 10; ++i) {
  53. EXPECT_EQ(i, GetAlphanumericCode('0' + i));
  54. }
  55. // The next 26 code points are capital alphabet letters.
  56. for (int i = 10; i < 36; ++i) {
  57. EXPECT_EQ(i, GetAlphanumericCode('A' + i - 10));
  58. }
  59. // Others are symbol letters
  60. EXPECT_EQ(36, GetAlphanumericCode(' '));
  61. EXPECT_EQ(37, GetAlphanumericCode('$'));
  62. EXPECT_EQ(38, GetAlphanumericCode('%'));
  63. EXPECT_EQ(39, GetAlphanumericCode('*'));
  64. EXPECT_EQ(40, GetAlphanumericCode('+'));
  65. EXPECT_EQ(41, GetAlphanumericCode('-'));
  66. EXPECT_EQ(42, GetAlphanumericCode('.'));
  67. EXPECT_EQ(43, GetAlphanumericCode('/'));
  68. EXPECT_EQ(44, GetAlphanumericCode(':'));
  69. // Should return -1 for other letters;
  70. EXPECT_EQ(-1, GetAlphanumericCode('a'));
  71. EXPECT_EQ(-1, GetAlphanumericCode('#'));
  72. EXPECT_EQ(-1, GetAlphanumericCode('\0'));
  73. }
  74. TEST(QREncoderTest, ChooseMode)
  75. {
  76. // Numeric mode.
  77. EXPECT_EQ(CodecMode::NUMERIC, ChooseMode(L"0", CharacterSet::Unknown));
  78. EXPECT_EQ(CodecMode::NUMERIC, ChooseMode(L"0123456789", CharacterSet::Unknown));
  79. // Alphanumeric mode.
  80. EXPECT_EQ(CodecMode::ALPHANUMERIC, ChooseMode(L"A", CharacterSet::Unknown));
  81. EXPECT_EQ(CodecMode::ALPHANUMERIC,
  82. ChooseMode(L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:", CharacterSet::Unknown));
  83. // 8-bit byte mode.
  84. EXPECT_EQ(CodecMode::BYTE, ChooseMode(L"a", CharacterSet::Unknown));
  85. EXPECT_EQ(CodecMode::BYTE, ChooseMode(L"#", CharacterSet::Unknown));
  86. EXPECT_EQ(CodecMode::BYTE, ChooseMode(L"", CharacterSet::Unknown));
  87. // Kanji mode. We used to use MODE_KANJI for these, but we stopped
  88. // doing that as we cannot distinguish Shift_JIS from other encodings
  89. // from data bytes alone. See also comments in qrcode_encoder.h.
  90. // AIUE in Hiragana in Shift_JIS
  91. EXPECT_EQ(CodecMode::BYTE,
  92. ChooseMode(ShiftJISString({0x8, 0xa, 0x8, 0xa, 0x8, 0xa, 0x8, 0xa6}), CharacterSet::Unknown));
  93. // Nihon in Kanji in Shift_JIS.
  94. EXPECT_EQ(CodecMode::BYTE, ChooseMode(ShiftJISString({0x9, 0xf, 0x9, 0x7b}), CharacterSet::Unknown));
  95. // Sou-Utsu-Byou in Kanji in Shift_JIS.
  96. EXPECT_EQ(CodecMode::BYTE, ChooseMode(ShiftJISString({0xe, 0x4, 0x9, 0x5, 0x9, 0x61}), CharacterSet::Unknown));
  97. }
  98. TEST(QREncoderTest, Encode)
  99. {
  100. auto qrCode = Encode(L"ABCDEF", ErrorCorrectionLevel::High, CharacterSet::Unknown, 0, false, -1);
  101. EXPECT_EQ(qrCode.mode, CodecMode::ALPHANUMERIC);
  102. EXPECT_EQ(qrCode.ecLevel, ErrorCorrectionLevel::High);
  103. ASSERT_NE(qrCode.version, nullptr);
  104. EXPECT_EQ(qrCode.version->versionNumber(), 1);
  105. EXPECT_EQ(qrCode.maskPattern, 4);
  106. EXPECT_EQ(ToString(qrCode.matrix, 'X', ' ', true),
  107. "X X X X X X X X X X X X X X X X \n"
  108. "X X X X X X X \n"
  109. "X X X X X X X X X X \n"
  110. "X X X X X X X X X X X X \n"
  111. "X X X X X X X X X X X X \n"
  112. "X X X X X X X \n"
  113. "X X X X X X X X X X X X X X X X X \n"
  114. " X X \n"
  115. " X X X X X X X X X X \n"
  116. " X X X X X X X X X X X X \n"
  117. "X X X X X X X X X X \n"
  118. "X X X X X X X X X \n"
  119. " X X X X X X X X X X X X X \n"
  120. " X X X X X X \n"
  121. "X X X X X X X X X X X X X \n"
  122. "X X X X X X X X X X \n"
  123. "X X X X X X X X X X X \n"
  124. "X X X X X X X X X X X \n"
  125. "X X X X X X X X X \n"
  126. "X X X X X X X \n"
  127. "X X X X X X X X X X X X \n");
  128. }
  129. TEST(QREncoderTest, EncodeWithVersion)
  130. {
  131. auto qrCode = Encode(L"ABCDEF", ErrorCorrectionLevel::High, CharacterSet::Unknown, 7, false, -1);
  132. ASSERT_NE(qrCode.version, nullptr);
  133. EXPECT_EQ(qrCode.version->versionNumber(), 7);
  134. }
  135. TEST(QREncoderTest, EncodeWithVersionTooSmall)
  136. {
  137. EXPECT_THROW(
  138. Encode(L"THISMESSAGEISTOOLONGFORAQRCODEVERSION3", ErrorCorrectionLevel::High, CharacterSet::Unknown, 3, false, -1)
  139. , std::invalid_argument);
  140. }
  141. TEST(QREncoderTest, SimpleUTF8ECI)
  142. {
  143. auto qrCode = Encode(L"hello", ErrorCorrectionLevel::High, CharacterSet::UTF8, 0, false, -1);
  144. EXPECT_EQ(qrCode.mode, CodecMode::BYTE);
  145. EXPECT_EQ(qrCode.ecLevel, ErrorCorrectionLevel::High);
  146. ASSERT_NE(qrCode.version, nullptr);
  147. EXPECT_EQ(qrCode.version->versionNumber(), 1);
  148. EXPECT_EQ(qrCode.maskPattern, 6);
  149. EXPECT_EQ(ToString(qrCode.matrix, 'X', ' ', true),
  150. "X X X X X X X X X X X X X X X X \n"
  151. "X X X X X X \n"
  152. "X X X X X X X X X X X X X \n"
  153. "X X X X X X X X X X X X \n"
  154. "X X X X X X X X X X X X \n"
  155. "X X X X X \n"
  156. "X X X X X X X X X X X X X X X X X \n"
  157. " X X X X \n"
  158. " X X X X X X X \n"
  159. " X X X X X X X X X \n"
  160. "X X X X X X X X X X X \n"
  161. " X X X X X X \n"
  162. " X X X X X X X X X X X X X X X \n"
  163. " X X X X X X X X X X X X \n"
  164. "X X X X X X X X X X \n"
  165. "X X X X X X \n"
  166. "X X X X X X X X X \n"
  167. "X X X X X X X X X X X X X \n"
  168. "X X X X X X X X X X X X \n"
  169. "X X X X X X \n"
  170. "X X X X X X X X X X X \n");
  171. }
  172. TEST(QREncoderTest, SimpleBINARYECI)
  173. {
  174. auto qrCode = Encode(L"\u00E9", ErrorCorrectionLevel::High, CharacterSet::BINARY, 0, false, -1);
  175. EXPECT_EQ(qrCode.mode, CodecMode::BYTE);
  176. EXPECT_EQ(qrCode.ecLevel, ErrorCorrectionLevel::High);
  177. ASSERT_NE(qrCode.version, nullptr);
  178. EXPECT_EQ(qrCode.version->versionNumber(), 1);
  179. EXPECT_EQ(qrCode.maskPattern, 6);
  180. EXPECT_EQ(ToString(qrCode.matrix, 'X', ' ', true),
  181. "X X X X X X X X X X X X X X X X X X \n"
  182. "X X X X X \n"
  183. "X X X X X X X X X X X X X \n"
  184. "X X X X X X X X X X X X X X X \n"
  185. "X X X X X X X X X X X \n"
  186. "X X X X X X \n"
  187. "X X X X X X X X X X X X X X X X X \n"
  188. " X X X \n"
  189. " X X X X X X X \n"
  190. "X X X X X X X X \n"
  191. "X X X X X X X X X X X X X X X \n"
  192. "X X X X X X X X X X X X \n"
  193. " X X X X X X X X X X \n"
  194. " X X X X X X X X \n"
  195. "X X X X X X X X X X X X X X X \n"
  196. "X X X X X X X \n"
  197. "X X X X X X X X X X X X X \n"
  198. "X X X X X X X X X X X X X \n"
  199. "X X X X X X X X X X \n"
  200. "X X X X X X X \n"
  201. "X X X X X X X X X X X X X \n");
  202. }
  203. TEST(QREncoderTest, EncodeKanjiMode)
  204. {
  205. auto qrCode = Encode(L"\u65e5\u672c", ErrorCorrectionLevel::Medium, CharacterSet::Shift_JIS, 0, false, -1);
  206. EXPECT_EQ(qrCode.mode, CodecMode::KANJI);
  207. EXPECT_EQ(qrCode.ecLevel, ErrorCorrectionLevel::Medium);
  208. ASSERT_NE(qrCode.version, nullptr);
  209. EXPECT_EQ(qrCode.version->versionNumber(), 1);
  210. EXPECT_EQ(qrCode.maskPattern, 0);
  211. EXPECT_EQ(ToString(qrCode.matrix, 'X', ' ', true),
  212. "X X X X X X X X X X X X X X X X \n"
  213. "X X X X X X \n"
  214. "X X X X X X X X X X X X X X \n"
  215. "X X X X X X X X X X X \n"
  216. "X X X X X X X X X X X X X X X \n"
  217. "X X X X X X X \n"
  218. "X X X X X X X X X X X X X X X X X \n"
  219. " X \n"
  220. "X X X X X X X X \n"
  221. "X X X X X X X X X X \n"
  222. " X X X X X X X X X X X X \n"
  223. "X X X X X X X X X X X \n"
  224. " X X X X X X X X X X X X \n"
  225. " X X X X X \n"
  226. "X X X X X X X X X X X \n"
  227. "X X X X X X X \n"
  228. "X X X X X X X X X X X \n"
  229. "X X X X X X X X X X \n"
  230. "X X X X X X X X X X X X X \n"
  231. "X X X X X X X X X \n"
  232. "X X X X X X X X X X X X X X \n");
  233. }
  234. TEST(QREncoderTest, EncodeShiftjisNumeric)
  235. {
  236. auto qrCode = Encode(L"0123", ErrorCorrectionLevel::Medium, CharacterSet::Shift_JIS, 0, false, -1);
  237. EXPECT_EQ(qrCode.mode, CodecMode::NUMERIC);
  238. EXPECT_EQ(qrCode.ecLevel, ErrorCorrectionLevel::Medium);
  239. ASSERT_NE(qrCode.version, nullptr);
  240. EXPECT_EQ(qrCode.version->versionNumber(), 1);
  241. EXPECT_EQ(qrCode.maskPattern, 2);
  242. EXPECT_EQ(ToString(qrCode.matrix, 'X', ' ', true),
  243. "X X X X X X X X X X X X X X X X X \n"
  244. "X X X X X X \n"
  245. "X X X X X X X X X X X \n"
  246. "X X X X X X X X X X X X X X \n"
  247. "X X X X X X X X X X X X X X \n"
  248. "X X X X X X X \n"
  249. "X X X X X X X X X X X X X X X X X \n"
  250. " X X X X X \n"
  251. "X X X X X X X X X X X X X X \n"
  252. "X X X X X X X X \n"
  253. " X X X X X X X X X X X X X X \n"
  254. "X X X X X X X X X \n"
  255. " X X X X X X X X \n"
  256. " X X X X X X X \n"
  257. "X X X X X X X X X X X \n"
  258. "X X X X X X X X X X \n"
  259. "X X X X X X X X X X \n"
  260. "X X X X X X X X X X X \n"
  261. "X X X X X X X X X X X X \n"
  262. "X X X X X X X \n"
  263. "X X X X X X X X X X X X X X \n");
  264. }
  265. TEST(QREncoderTest, EncodeGS1)
  266. {
  267. auto qrCode = Encode(L"100001%11171218", ErrorCorrectionLevel::High, CharacterSet::Unknown, 0, true, -1);
  268. EXPECT_EQ(qrCode.mode, CodecMode::ALPHANUMERIC);
  269. EXPECT_EQ(qrCode.ecLevel, ErrorCorrectionLevel::High);
  270. ASSERT_NE(qrCode.version, nullptr);
  271. EXPECT_EQ(qrCode.version->versionNumber(), 2);
  272. EXPECT_EQ(qrCode.maskPattern, 4);
  273. EXPECT_EQ(ToString(qrCode.matrix, 'X', ' ', true),
  274. "X X X X X X X X X X X X X X X X X X X X \n"
  275. "X X X X X X X X \n"
  276. "X X X X X X X X X X X X X X \n"
  277. "X X X X X X X X X X X X X X \n"
  278. "X X X X X X X X X X X X X X \n"
  279. "X X X X X X X X X X \n"
  280. "X X X X X X X X X X X X X X X X X X X \n"
  281. " X X X X X X \n"
  282. " X X X X X X X X X X X \n"
  283. " X X X X X X X X X X X X X X X \n"
  284. " X X X X X X X X X X X X X X \n"
  285. "X X X X X X X X X X X X X X X X X \n"
  286. " X X X X X X X X X X X X \n"
  287. "X X X X X X X X X X X \n"
  288. " X X X X X X X X X X X X X X X X \n"
  289. " X X X X X X X X X X \n"
  290. "X X X X X X X X X X X X X X \n"
  291. " X X X X X X X X \n"
  292. "X X X X X X X X X X X X X X X \n"
  293. "X X X X X X X X X X \n"
  294. "X X X X X X X X X X X X X X X \n"
  295. "X X X X X X X X X X X \n"
  296. "X X X X X X X X X X X X X X \n"
  297. "X X X X X X X X X X X X \n"
  298. "X X X X X X X X X X X X X X \n");
  299. }
  300. TEST(QREncoderTest, EncodeGS1ModeHeaderWithECI)
  301. {
  302. auto qrCode = Encode(L"hello", ErrorCorrectionLevel::High, CharacterSet::UTF8, 0, true, -1);
  303. EXPECT_EQ(qrCode.mode, CodecMode::BYTE);
  304. EXPECT_EQ(qrCode.ecLevel, ErrorCorrectionLevel::High);
  305. ASSERT_NE(qrCode.version, nullptr);
  306. EXPECT_EQ(qrCode.version->versionNumber(), 1);
  307. EXPECT_EQ(qrCode.maskPattern, 5);
  308. EXPECT_EQ(ToString(qrCode.matrix, 'X', ' ', true),
  309. "X X X X X X X X X X X X X X X X X \n"
  310. "X X X X X X \n"
  311. "X X X X X X X X X X X X X \n"
  312. "X X X X X X X X X X X X \n"
  313. "X X X X X X X X X X X X \n"
  314. "X X X X X X X X \n"
  315. "X X X X X X X X X X X X X X X X X \n"
  316. " X X X X \n"
  317. " X X X X X X X X \n"
  318. " X X X X X X X X X X X X X X \n"
  319. " X X X X X X X X X X X \n"
  320. "X X X X X X X X X X X X \n"
  321. "X X X X X X X X X X \n"
  322. " X X X X X X X X \n"
  323. "X X X X X X X X X X X X \n"
  324. "X X X X X X X X \n"
  325. "X X X X X X X X X X \n"
  326. "X X X X X X X X X X X X \n"
  327. "X X X X X X X X X X X \n"
  328. "X X X X X X X X X \n"
  329. "X X X X X X X X X X X X X X \n");
  330. }
  331. TEST(QREncoderTest, AppendModeInfo)
  332. {
  333. BitArray bits;
  334. AppendModeInfo(CodecMode::NUMERIC, bits);
  335. EXPECT_EQ(ToString(bits), "...X");
  336. }
  337. TEST(QREncoderTest, AppendLengthInfo)
  338. {
  339. BitArray bits;
  340. AppendLengthInfo(1, // 1 letter (1/1).
  341. *Version::Model2(1), CodecMode::NUMERIC, bits);
  342. EXPECT_EQ(ToString(bits), RemoveSpace("........ .X")); // 10 bits.
  343. bits = BitArray();
  344. AppendLengthInfo(2, // 2 letters (2/1).
  345. *Version::Model2(10), CodecMode::ALPHANUMERIC, bits);
  346. EXPECT_EQ(ToString(bits), RemoveSpace("........ .X.")); // 11 bits.
  347. bits = BitArray();
  348. AppendLengthInfo(255, // 255 letter (255/1).
  349. *Version::Model2(27), CodecMode::BYTE, bits);
  350. EXPECT_EQ(ToString(bits), RemoveSpace("........ XXXXXXXX")); // 16 bits.
  351. bits = BitArray();
  352. AppendLengthInfo(512, // 512 letters (1024/2).
  353. *Version::Model2(40), CodecMode::KANJI, bits);
  354. EXPECT_EQ(ToString(bits), RemoveSpace("..X..... ....")); // 12 bits.
  355. }
  356. TEST(QREncoderTest, AppendNumericBytes)
  357. {
  358. // 1 = 01 = 0001 in 4 bits.
  359. BitArray bits;
  360. AppendNumericBytes(L"1", bits);
  361. EXPECT_EQ(ToString(bits), RemoveSpace("...X"));
  362. // 12 = 0xc = 0001100 in 7 bits.
  363. bits = BitArray();
  364. AppendNumericBytes(L"12", bits);
  365. EXPECT_EQ(ToString(bits), RemoveSpace("...XX.."));
  366. // 123 = 0x7b = 0001111011 in 10 bits.
  367. bits = BitArray();
  368. AppendNumericBytes(L"123", bits);
  369. EXPECT_EQ(ToString(bits), RemoveSpace("...XXXX. XX"));
  370. // 1234 = "123" + "4" = 0001111011 + 0100
  371. bits = BitArray();
  372. AppendNumericBytes(L"1234", bits);
  373. EXPECT_EQ(ToString(bits), RemoveSpace("...XXXX. XX.X.."));
  374. // Empty.
  375. bits = BitArray();
  376. AppendNumericBytes(L"", bits);
  377. EXPECT_EQ(ToString(bits), RemoveSpace(""));
  378. }
  379. TEST(QREncoderTest, AppendAlphanumericBytes)
  380. {
  381. // A = 10 = 0xa = 001010 in 6 bits
  382. BitArray bits;
  383. AppendAlphanumericBytes(L"A", bits);
  384. EXPECT_EQ(ToString(bits), RemoveSpace("..X.X."));
  385. // AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits
  386. bits = BitArray();
  387. AppendAlphanumericBytes(L"AB", bits);
  388. EXPECT_EQ(ToString(bits), RemoveSpace("..XXX..X X.X"));
  389. // ABC = "AB" + "C" = 00111001101 + 001100
  390. bits = BitArray();
  391. AppendAlphanumericBytes(L"ABC", bits);
  392. EXPECT_EQ(ToString(bits), RemoveSpace("..XXX..X X.X..XX. ."));
  393. // Empty.
  394. bits = BitArray();
  395. AppendAlphanumericBytes(L"", bits);
  396. EXPECT_EQ(ToString(bits), RemoveSpace(""));
  397. // Invalid data.
  398. EXPECT_THROW(AppendAlphanumericBytes(L"abc", bits), std::invalid_argument);
  399. }
  400. TEST(QREncoderTest, Append8BitBytes)
  401. {
  402. // 0x61, 0x62, 0x63
  403. BitArray bits;
  404. Append8BitBytes(L"abc", CharacterSet::Unknown, bits);
  405. EXPECT_EQ(ToString(bits), RemoveSpace(".XX....X .XX...X. .XX...XX"));
  406. // Empty.
  407. bits = BitArray();
  408. Append8BitBytes(L"", CharacterSet::Unknown, bits);
  409. EXPECT_EQ(ToString(bits), RemoveSpace(""));
  410. }
  411. // Numbers are from page 21 of JISX0510:2004
  412. TEST(QREncoderTest, AppendKanjiBytes)
  413. {
  414. BitArray bits;
  415. AppendKanjiBytes(ShiftJISString({ 0x93, 0x5f }), bits);
  416. EXPECT_EQ(ToString(bits), RemoveSpace(".XX.XX.. XXXXX"));
  417. AppendKanjiBytes(ShiftJISString({ 0xe4, 0xaa }), bits);
  418. EXPECT_EQ(ToString(bits), RemoveSpace(".XX.XX.. XXXXXXX. X.X.X.X. X."));
  419. }
  420. TEST(QREncoderTest, AppendBytes)
  421. {
  422. // Should use appendNumericBytes.
  423. // 1 = 01 = 0001 in 4 bits.
  424. BitArray bits;
  425. AppendBytes(L"1", CodecMode::NUMERIC, CharacterSet::Unknown, bits);
  426. EXPECT_EQ(ToString(bits), RemoveSpace("...X"));
  427. // Should use appendAlphanumericBytes.
  428. // A = 10 = 0xa = 001010 in 6 bits
  429. bits = BitArray();
  430. AppendBytes(L"A", CodecMode::ALPHANUMERIC, CharacterSet::Unknown, bits);
  431. EXPECT_EQ(ToString(bits), RemoveSpace("..X.X."));
  432. // Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC.
  433. bits = BitArray();
  434. EXPECT_THROW(AppendBytes(L"a", CodecMode::ALPHANUMERIC, CharacterSet::Unknown, bits), std::invalid_argument);
  435. // Should use append8BitBytes.
  436. // 0x61, 0x62, 0x63
  437. bits = BitArray();
  438. AppendBytes(L"abc", CodecMode::BYTE, CharacterSet::Unknown, bits);
  439. EXPECT_EQ(ToString(bits), RemoveSpace(".XX....X .XX...X. .XX...XX"));
  440. // Anything can be encoded in QRCode.MODE_8BIT_BYTE.
  441. AppendBytes(L"\0", CodecMode::BYTE, CharacterSet::Unknown, bits);
  442. // Should use appendKanjiBytes.
  443. // 0x93, 0x5f
  444. bits = BitArray();
  445. AppendBytes(ShiftJISString({0x93, 0x5f}), CodecMode::KANJI, CharacterSet::Unknown, bits);
  446. EXPECT_EQ(ToString(bits), RemoveSpace(".XX.XX.. XXXXX"));
  447. }
  448. TEST(QREncoderTest, TerminateBits)
  449. {
  450. BitArray v;
  451. TerminateBits(0, v);
  452. EXPECT_EQ(ToString(v), RemoveSpace(""));
  453. v = BitArray();
  454. TerminateBits(1, v);
  455. EXPECT_EQ(ToString(v), RemoveSpace("........"));
  456. v = BitArray();
  457. v.appendBits(0, 3);
  458. TerminateBits(1, v);
  459. EXPECT_EQ(ToString(v), RemoveSpace("........"));
  460. v = BitArray();
  461. v.appendBits(0, 5);
  462. TerminateBits(1, v);
  463. EXPECT_EQ(ToString(v), RemoveSpace("........"));
  464. v = BitArray();
  465. v.appendBits(0, 8);
  466. TerminateBits(1, v);
  467. EXPECT_EQ(ToString(v), RemoveSpace("........"));
  468. v = BitArray();
  469. TerminateBits(2, v);
  470. EXPECT_EQ(ToString(v), RemoveSpace("........ XXX.XX.."));
  471. v = BitArray();
  472. v.appendBits(0, 1);
  473. TerminateBits(3, v);
  474. EXPECT_EQ(ToString(v), RemoveSpace("........ XXX.XX.. ...X...X"));
  475. }
  476. TEST(QREncoderTest, GetNumDataBytesAndNumECBytesForBlockID)
  477. {
  478. int numDataBytes;
  479. int numEcBytes;
  480. // Version 1-H.
  481. GetNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0, numDataBytes, numEcBytes);
  482. EXPECT_EQ(9, numDataBytes);
  483. EXPECT_EQ(17, numEcBytes);
  484. // Version 3-H. 2 blocks.
  485. GetNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 0, numDataBytes, numEcBytes);
  486. EXPECT_EQ(13, numDataBytes);
  487. EXPECT_EQ(22, numEcBytes);
  488. GetNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 1, numDataBytes, numEcBytes);
  489. EXPECT_EQ(13, numDataBytes);
  490. EXPECT_EQ(22, numEcBytes);
  491. // Version 7-H. (4 + 1) blocks.
  492. GetNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 0, numDataBytes, numEcBytes);
  493. EXPECT_EQ(13, numDataBytes);
  494. EXPECT_EQ(26, numEcBytes);
  495. GetNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 4, numDataBytes, numEcBytes);
  496. EXPECT_EQ(14, numDataBytes);
  497. EXPECT_EQ(26, numEcBytes);
  498. // Version 40-H. (20 + 61) blocks.
  499. GetNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 0, numDataBytes, numEcBytes);
  500. EXPECT_EQ(15, numDataBytes);
  501. EXPECT_EQ(30, numEcBytes);
  502. GetNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 20, numDataBytes, numEcBytes);
  503. EXPECT_EQ(16, numDataBytes);
  504. EXPECT_EQ(30, numEcBytes);
  505. GetNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 80, numDataBytes, numEcBytes);
  506. EXPECT_EQ(16, numDataBytes);
  507. EXPECT_EQ(30, numEcBytes);
  508. }
  509. // Numbers are from http://www.swetake.com/qr/qr3.html and
  510. // http://www.swetake.com/qr/qr9.html
  511. TEST(QREncoderTest, GenerateECBytes)
  512. {
  513. ByteArray ecBytes;
  514. GenerateECBytes({ 32, 65, 205, 69, 41, 220, 46, 128, 236 }, 17, ecBytes);
  515. ByteArray expected = { 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61 };
  516. EXPECT_EQ(ecBytes, expected);
  517. GenerateECBytes({ 67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214 }, 18, ecBytes);
  518. expected = { 175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187 };
  519. EXPECT_EQ(ecBytes, expected);
  520. // High-order zero coefficient case.
  521. GenerateECBytes({ 32, 49, 205, 69, 42, 20, 0, 236, 17 }, 17, ecBytes);
  522. expected = { 0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213 };
  523. EXPECT_EQ(ecBytes, expected);
  524. }
  525. TEST(QREncoderTest, InterleaveWithECBytes)
  526. {
  527. BitArray in;
  528. for (int dataByte : {32, 65, 205, 69, 41, 220, 46, 128, 236})
  529. in.appendBits(dataByte, 8);
  530. BitArray out = InterleaveWithECBytes(in, 26, 9, 1);
  531. std::vector<uint8_t> expected = {
  532. 32, 65, 205, 69, 41, 220, 46, 128, 236,
  533. 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61,
  534. }; // Error correction bytes in second block
  535. ASSERT_EQ(Size(expected), out.sizeInBytes());
  536. EXPECT_EQ(expected, out.toBytes());
  537. // Numbers are from http://www.swetake.com/qr/qr8.html
  538. in = BitArray();
  539. for (int dataByte :
  540. {67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214, 230, 247, 7, 23, 39, 55,
  541. 71, 87, 103, 119, 135, 151, 166, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214, 230,
  542. 247, 7, 23, 39, 55, 71, 87, 103, 119, 135, 151, 160, 236, 17, 236, 17, 236, 17, 236, 17})
  543. in.appendBits(dataByte, 8);
  544. out = InterleaveWithECBytes(in, 134, 62, 4);
  545. expected = {
  546. 67, 230, 54, 55, 70, 247, 70, 71, 22, 7, 86, 87, 38, 23, 102, 103, 54, 39, 118, 119, 70,
  547. 55, 134, 135, 86, 71, 150, 151, 102, 87, 166, 160, 118, 103, 182, 236, 134, 119, 198, 17, 150, 135,
  548. 214, 236, 166, 151, 230, 17, 182, 166, 247, 236, 198, 22, 7, 17, 214, 38, 23, 236, 39, 17,
  549. 175, 155, 245, 236, 80, 146, 56, 74, 155, 165, 133, 142, 64, 183, 132, 13, 178, 54, 132, 108, 45,
  550. 113, 53, 50, 214, 98, 193, 152, 233, 147, 50, 71, 65, 190, 82, 51, 209, 199, 171, 54, 12, 112,
  551. 57, 113, 155, 117, 211, 164, 117, 30, 158, 225, 31, 190, 242, 38, 140, 61, 179, 154, 214, 138, 147,
  552. 87, 27, 96, 77, 47, 187, 49, 156, 214,
  553. }; // Error correction bytes in second block
  554. EXPECT_EQ(Size(expected), out.sizeInBytes());
  555. EXPECT_EQ(expected, out.toBytes());
  556. }
  557. TEST(QREncoderTest, BugInBitVectorNumBytes)
  558. {
  559. // There was a bug in BitVector.sizeInBytes() that caused it to return a
  560. // smaller-by-one value (ex. 1465 instead of 1466) if the number of bits
  561. // in the vector is not 8-bit aligned. In QRCodeEncoder::InitQRCode(),
  562. // BitVector::sizeInBytes() is used for finding the smallest QR Code
  563. // version that can fit the given data. Hence there were corner cases
  564. // where we chose a wrong QR Code version that cannot fit the given
  565. // data. Note that the issue did not occur with MODE_8BIT_BYTE, as the
  566. // bits in the bit vector are always 8-bit aligned.
  567. //
  568. // Before the bug was fixed, the following test didn't pass, because:
  569. //
  570. // - MODE_NUMERIC is chosen as all bytes in the data are '0'
  571. // - The 3518-byte numeric data needs 1466 bytes
  572. // - 3518 / 3 * 10 + 7 = 11727 bits = 1465.875 bytes
  573. // - 3 numeric bytes are encoded in 10 bits, hence the first
  574. // 3516 bytes are encoded in 3516 / 3 * 10 = 11720 bits.
  575. // - 2 numeric bytes can be encoded in 7 bits, hence the last
  576. // 2 bytes are encoded in 7 bits.
  577. // - The version 27 QR Code with the EC level L has 1468 bytes for data.
  578. // - 1828 - 360 = 1468
  579. // - In InitQRCode(), 3 bytes are reserved for a header. Hence 1465 bytes
  580. // (1468 -3) are left for data.
  581. // - Because of the bug in BitVector::sizeInBytes(), InitQRCode() determines
  582. // the given data can fit in 1465 bytes, despite it needs 1466 bytes.
  583. // - Hence QRCodeEncoder.encode() failed and returned false.
  584. // - To be precise, it needs 11727 + 4 (getMode info) + 14 (length info) =
  585. // 11745 bits = 1468.125 bytes are needed (i.e. cannot fit in 1468
  586. // bytes).
  587. Encode(std::wstring(3518, L'0'), ErrorCorrectionLevel::Low, CharacterSet::Unknown, 0, false, -1);
  588. }