AZEncodeDecodeTest.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. * Copyright 2017 Huy Cuong Nguyen
  3. * Copyright 2013 ZXing authors
  4. */
  5. // SPDX-License-Identifier: Apache-2.0
  6. #include "BitMatrix.h"
  7. #include "CharacterSet.h"
  8. #include "DecoderResult.h"
  9. #include "PseudoRandom.h"
  10. #include "TextEncoder.h"
  11. #include "aztec/AZDecoder.h"
  12. #include "aztec/AZDetector.h"
  13. #include "aztec/AZDetectorResult.h"
  14. #include "aztec/AZEncoder.h"
  15. #include "aztec/AZWriter.h"
  16. #include <algorithm>
  17. #include <utility>
  18. namespace testing {
  19. namespace internal {
  20. bool operator==(const std::string& a, const std::wstring& b) {
  21. return a.length() == b.length() && std::equal(a.begin(), a.end(), b.begin());
  22. }
  23. }
  24. }
  25. #include "gtest/gtest.h"
  26. using namespace ZXing;
  27. namespace {
  28. // Shorthand to call Decode()
  29. static DecoderResult parse(BitMatrix&& bits, bool compact, int nbDatablocks, int nbLayers)
  30. {
  31. return Aztec::Decode({{std::move(bits), {}}, compact, nbDatablocks, nbLayers, false /*readerInit*/, false /*isMirrored*/, 0 /*runeValue*/});
  32. }
  33. void TestEncodeDecode(const std::string& data, bool compact, int layers) {
  34. Aztec::EncodeResult aztec = Aztec::Encoder::Encode(data, 25, Aztec::Encoder::DEFAULT_AZTEC_LAYERS);
  35. ASSERT_EQ(aztec.compact, compact) << "Unexpected symbol format (compact)";
  36. ASSERT_EQ(aztec.layers, layers) << "Unexpected nr. of layers";
  37. DecoderResult res = parse(aztec.matrix.copy(), aztec.compact, aztec.codeWords, aztec.layers);
  38. ASSERT_EQ(res.isValid(), true);
  39. EXPECT_EQ(data, res.text());
  40. // Check error correction by introducing a few minor errors
  41. PseudoRandom random(0x12345678);
  42. BitMatrix matrix = aztec.matrix.copy();
  43. auto x = random.next(0, matrix.width() - 1);
  44. auto y = random.next(0, 1);
  45. matrix.flip(x, y);
  46. x = random.next(0, matrix.width() - 1);
  47. y = matrix.height() - 2 + random.next(0, 1);
  48. matrix.flip(x, y);
  49. x = random.next(0, 1);
  50. y = random.next(0, matrix.height() - 1);
  51. matrix.flip(x, y);
  52. x = matrix.width() - 2 + random.next(0, 1);
  53. y = random.next(0, matrix.height() - 1);
  54. matrix.flip(x, y);
  55. res = parse(std::move(matrix), aztec.compact, aztec.codeWords, aztec.layers);
  56. ASSERT_EQ(res.isValid(), true);
  57. EXPECT_EQ(data, res.text());
  58. }
  59. void TestWriter(const std::wstring& data, CharacterSet charset, int eccPercent, bool compact, int layers) {
  60. // 1. Perform an encode-decode round-trip because it can be lossy.
  61. // 2. Aztec Decoder currently always decodes the data with a LATIN-1 charset:
  62. std::string textBytes = TextEncoder::FromUnicode(data, charset);
  63. Aztec::Writer writer;
  64. writer.setEncoding(charset);
  65. writer.setEccPercent(eccPercent);
  66. BitMatrix matrix = writer.encode(data, 0, 0);
  67. Aztec::EncodeResult aztec = Aztec::Encoder::Encode(textBytes, eccPercent, Aztec::Encoder::DEFAULT_AZTEC_LAYERS);
  68. EXPECT_EQ(aztec.compact, compact) << "Unexpected symbol format (compact)";
  69. EXPECT_EQ(aztec.layers, layers) << "Unexpected nr. of layers";
  70. EXPECT_EQ(aztec.matrix, matrix);
  71. DecoderResult res = parse(matrix.copy(), aztec.compact, aztec.codeWords, aztec.layers);
  72. EXPECT_EQ(res.isValid(), true);
  73. EXPECT_EQ(res.content().bytes, ByteArray(textBytes));
  74. // Check error correction by introducing up to eccPercent/2 errors
  75. int ecWords = aztec.codeWords * eccPercent / 100 / 2;
  76. PseudoRandom random(0x12345678);
  77. for (int i = 0; i < ecWords; i++) {
  78. // don't touch the core
  79. int x = random.next(0, 1) == 1 ?
  80. random.next(0, aztec.layers * 2 - 1)
  81. : matrix.width() - 1 - random.next(0, aztec.layers * 2 - 1);
  82. int y = random.next(0, 1) == 1 ?
  83. random.next(0, aztec.layers * 2 - 1)
  84. : matrix.height() - 1 - random.next(0, aztec.layers * 2 - 1);
  85. matrix.flip(x, y);
  86. }
  87. res = parse(std::move(matrix), aztec.compact, aztec.codeWords, aztec.layers);
  88. EXPECT_EQ(res.isValid(), true);
  89. EXPECT_EQ(res.content().bytes, ByteArray(textBytes));
  90. }
  91. }
  92. TEST(AZEncodeDecodeTest, EncodeDecode1)
  93. {
  94. TestEncodeDecode("Abc123!", true, 1);
  95. }
  96. TEST(AZEncodeDecodeTest, EncodeDecode2)
  97. {
  98. TestEncodeDecode("Lorem ipsum. http://test/", true, 2);
  99. }
  100. TEST(AZEncodeDecodeTest, EncodeDecode3)
  101. {
  102. TestEncodeDecode("AAAANAAAANAAAANAAAANAAAANAAAANAAAANAAAANAAAANAAAAN", true, 3);
  103. }
  104. TEST(AZEncodeDecodeTest, EncodeDecode4)
  105. {
  106. TestEncodeDecode("http://test/~!@#*^%&)__ ;:'\"[]{}\\|-+-=`1029384", true, 4);
  107. }
  108. TEST(AZEncodeDecodeTest, EncodeDecode5)
  109. {
  110. TestEncodeDecode("http://test/~!@#*^%&)__ ;:'\"[]{}\\|-+-=`1029384756<>/?abc"
  111. "Four score and seven our forefathers brought forth", false, 5);
  112. }
  113. TEST(AZEncodeDecodeTest, EncodeDecode10)
  114. {
  115. TestEncodeDecode("In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus quis diam"
  116. " cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec laoreet rutrum"
  117. " est, nec convallis mauris condimentum sit amet. Phasellus gravida, justo et congue"
  118. " auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec lorem. Nulla"
  119. " ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar nisi, id"
  120. " elementum sapien dolor et diam.", false, 10);
  121. }
  122. TEST(AZEncodeDecodeTest, EncodeDecode23)
  123. {
  124. TestEncodeDecode("In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus quis diam"
  125. " cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec laoreet rutrum"
  126. " est, nec convallis mauris condimentum sit amet. Phasellus gravida, justo et congue"
  127. " auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec lorem. Nulla"
  128. " ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar nisi, id"
  129. " elementum sapien dolor et diam. Donec ac nunc sodales elit placerat eleifend."
  130. " Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra fringilla, risus"
  131. " justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo diam, lobortis eu"
  132. " tristique ac, p.In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus"
  133. " quis diam cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec"
  134. " laoreet rutrum est, nec convallis mauris condimentum sit amet. Phasellus gravida,"
  135. " justo et congue auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec"
  136. " lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar"
  137. " nisi, id elementum sapien dolor et diam. Donec ac nunc sodales elit placerat"
  138. " eleifend. Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra"
  139. " fringilla, risus justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo"
  140. " diam, lobortis eu tristique ac, p. In ut magna vel mauris malesuada dictum. Nulla"
  141. " ullamcorper metus quis diam cursus facilisis. Sed mollis quam id justo rutrum"
  142. " sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum sit amet."
  143. " Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat, eget hendrerit"
  144. " felis turpis nec lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo"
  145. " erat pulvinar nisi, id elementum sapien dolor et diam.", false, 23);
  146. }
  147. TEST(AZEncodeDecodeTest, EncodeDecode31)
  148. {
  149. TestEncodeDecode("In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus quis diam"
  150. " cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec laoreet rutrum"
  151. " est, nec convallis mauris condimentum sit amet. Phasellus gravida, justo et congue"
  152. " auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec lorem. Nulla"
  153. " ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar nisi, id"
  154. " elementum sapien dolor et diam. Donec ac nunc sodales elit placerat eleifend."
  155. " Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra fringilla, risus"
  156. " justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo diam, lobortis eu"
  157. " tristique ac, p.In ut magna vel mauris malesuada dictum. Nulla ullamcorper metus"
  158. " quis diam cursus facilisis. Sed mollis quam id justo rutrum sagittis. Donec"
  159. " laoreet rutrum est, nec convallis mauris condimentum sit amet. Phasellus gravida,"
  160. " justo et congue auctor, nisi ipsum viverra erat, eget hendrerit felis turpis nec"
  161. " lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo erat pulvinar"
  162. " nisi, id elementum sapien dolor et diam. Donec ac nunc sodales elit placerat"
  163. " eleifend. Sed ornare luctus ornare. Vestibulum vehicula, massa at pharetra"
  164. " fringilla, risus justo faucibus erat, nec porttitor nibh tellus sed est. Ut justo"
  165. " diam, lobortis eu tristique ac, p. In ut magna vel mauris malesuada dictum. Nulla"
  166. " ullamcorper metus quis diam cursus facilisis. Sed mollis quam id justo rutrum"
  167. " sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum sit amet."
  168. " Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat, eget hendrerit"
  169. " felis turpis nec lorem. Nulla ultrices, elit pellentesque aliquet laoreet, justo"
  170. " erat pulvinar nisi, id elementum sapien dolor et diam. Donec ac nunc sodales elit"
  171. " placerat eleifend. Sed ornare luctus ornare. Vestibulum vehicula, massa at"
  172. " pharetra fringilla, risus justo faucibus erat, nec porttitor nibh tellus sed est."
  173. " Ut justo diam, lobortis eu tristique ac, p.In ut magna vel mauris malesuada"
  174. " dictum. Nulla ullamcorper metus quis diam cursus facilisis. Sed mollis quam id"
  175. " justo rutrum sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum"
  176. " sit amet. Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat,"
  177. " eget hendrerit felis turpis nec lorem. Nulla ultrices, elit pellentesque aliquet"
  178. " laoreet, justo erat pulvinar nisi, id elementum sapien dolor et diam. Donec ac"
  179. " nunc sodales elit placerat eleifend. Sed ornare luctus ornare. Vestibulum vehicula,"
  180. " massa at pharetra fringilla, risus justo faucibus erat, nec porttitor nibh tellus"
  181. " sed est. Ut justo diam, lobortis eu tris. In ut magna vel mauris malesuada dictum."
  182. " Nulla ullamcorper metus quis diam cursus facilisis. Sed mollis quam id justo rutrum"
  183. " sagittis. Donec laoreet rutrum est, nec convallis mauris condimentum sit amet."
  184. " Phasellus gravida, justo et congue auctor, nisi ipsum viverra erat, eget"
  185. " hendrerit felis turpis nec lorem.", false, 31);
  186. }
  187. TEST(AZEncodeDecodeTest, AztecWriter)
  188. {
  189. //TestWriter(L"\x20AC 1 sample data.", CharacterSet::ISO8859_1, 25, true, 2);
  190. //TestWriter(L"\x20AC 1 sample data.", CharacterSet::ISO8859_15, 25, true, 2);
  191. TestWriter(L"\x20AC 1 sample data.", CharacterSet::UTF8, 25, true, 2);
  192. TestWriter(L"\x20AC 1 sample data.", CharacterSet::UTF8, 100, true, 3);
  193. TestWriter(L"\x20AC 1 sample data.", CharacterSet::UTF8, 300, true, 4);
  194. TestWriter(L"\x20AC 1 sample data.", CharacterSet::UTF8, 500, false, 5);
  195. // Test AztecWriter defaults
  196. std::wstring data = L"In ut magna vel mauris malesuada";
  197. BitMatrix matrix = Aztec::Writer().encode(data, 0, 0);
  198. Aztec::EncodeResult aztec =
  199. Aztec::Encoder::Encode(TextEncoder::FromUnicode(data, CharacterSet::ISO8859_1),
  200. Aztec::Encoder::DEFAULT_EC_PERCENT, Aztec::Encoder::DEFAULT_AZTEC_LAYERS);
  201. EXPECT_EQ(matrix, aztec.matrix);
  202. }
  203. TEST(AZEncodeDecodeTest, RunePure)
  204. {
  205. for(uint8_t word = 0; word < 255; word++) {
  206. std::string data(1, word);
  207. Aztec::EncodeResult aztec =
  208. Aztec::Encoder::Encode(data, 0, Aztec::Encoder::AZTEC_RUNE_LAYERS);
  209. auto result = Aztec::Detect(aztec.matrix, true, false);
  210. EXPECT_TRUE(result.isValid());
  211. EXPECT_EQ(result.nbDatablocks(), 0);
  212. EXPECT_EQ(result.runeValue(), word);
  213. }
  214. }