DMHighLevelEncodeTest.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. /*
  2. * Copyright 2017 Huy Cuong Nguyen
  3. * Copyright 2006 Jeremias Maerki.
  4. */
  5. // SPDX-License-Identifier: Apache-2.0
  6. #include "ByteArray.h"
  7. #include "CharacterSet.h"
  8. #include "ZXAlgorithms.h"
  9. #include "datamatrix/DMHighLevelEncoder.h"
  10. #include "datamatrix/DMSymbolInfo.h"
  11. #include "gtest/gtest.h"
  12. namespace ZXing {
  13. namespace DataMatrix {
  14. void OverrideSymbolSet(const SymbolInfo* symbols, size_t count);
  15. void UseDefaultSymbolSet();
  16. }
  17. }
  18. using namespace ZXing;
  19. //private static void useTestSymbols() {
  20. // SymbolInfo.overrideSymbolSet(TEST_SYMBOLS);
  21. //}
  22. //private static void resetSymbols() {
  23. // SymbolInfo.overrideSymbolSet(SymbolInfo.PROD_SYMBOLS);
  24. //}
  25. namespace {
  26. static DataMatrix::SymbolInfo TEST_SYMBOLS[] = {
  27. { false, 3, 5, 8, 8, 1 },
  28. { false, 5, 7, 10, 10, 1 },
  29. { true, 5, 7, 16, 6, 1 },
  30. { false, 8, 10, 12, 12, 1 },
  31. { true, 10, 11, 14, 6, 2 },
  32. { false, 13, 0, 0, 0, 1 },
  33. { false, 77, 0, 0, 0, 1 },
  34. //The last entries are fake entries to test special conditions with C40 encoding
  35. };
  36. /**
  37. * Convert a string of char codewords into a different string which lists each character
  38. * using its decimal value.
  39. *
  40. * @param codewords the codewords
  41. * @return the visualized codewords
  42. */
  43. static std::string Visualize(const ByteArray& codewords) {
  44. std::stringstream buf;
  45. for (int i = 0; i < Size(codewords); i++) {
  46. if (i > 0) {
  47. buf << ' ';
  48. }
  49. buf << (int)codewords[i];
  50. }
  51. return buf.str();
  52. }
  53. std::string Encode(const std::wstring& text) {
  54. return Visualize(DataMatrix::Encode(text));
  55. }
  56. std::wstring CreateBinaryMessage(int len) {
  57. std::wstring buf;
  58. buf.append(L"\xAB\xE4\xF6\xFC\xE9\xE0\xE1-");
  59. for (int i = 0; i < len - 9; i++) {
  60. buf.push_back(L'\xB7');
  61. }
  62. buf.push_back(L'\xBB');
  63. return buf;
  64. }
  65. }
  66. TEST(DMHighLevelEncodeTest, ASCIIEncodation)
  67. {
  68. std::string visualized = Encode(L"123456");
  69. EXPECT_EQ(visualized, "142 164 186");
  70. visualized = Encode(L"123456\xA3");
  71. EXPECT_EQ(visualized, "142 164 186 235 36");
  72. visualized = Encode(L"30Q324343430794<OQQ");
  73. EXPECT_EQ(visualized, "160 82 162 173 173 173 137 224 61 80 82 82");
  74. }
  75. TEST(DMHighLevelEncodeTest, C40EncodationBasic1)
  76. {
  77. std::string visualized = Encode(L"AIMAIMAIM");
  78. EXPECT_EQ(visualized, "230 91 11 91 11 91 11 254");
  79. //230 shifts to C40 encodation, 254 unlatches, "else" case
  80. }
  81. TEST(DMHighLevelEncodeTest, C40EncodationBasic2)
  82. {
  83. std::string visualized = Encode(L"AIMAIAB");
  84. EXPECT_EQ(visualized, "230 91 11 90 255 254 67 129");
  85. //"B" is normally encoded as "15" (one C40 value)
  86. //"else" case: "B" is encoded as ASCII
  87. visualized = Encode(L"AIMAIAb");
  88. EXPECT_EQ(visualized, "66 74 78 66 74 66 99 129"); //Encoded as ASCII
  89. //Alternative solution:
  90. //EXPECT_EQ(visualized, "230 91 11 90 255 254 99 129", visualized);
  91. //"b" is normally encoded as "Shift 3, 2" (two C40 values)
  92. //"else" case: "b" is encoded as ASCII
  93. visualized = Encode(L"AIMAIMAIM\xCB");
  94. EXPECT_EQ(visualized, "230 91 11 91 11 91 11 254 235 76");
  95. //Alternative solution:
  96. //EXPECT_EQ(visualized, "230 91 11 91 11 91 11 11 9 254", visualized);
  97. //Expl: 230 = shift to C40, "91 11" = "AIM",
  98. //"11 9" = "�" = "Shift 2, UpperShift, <char>
  99. //"else" case
  100. visualized = Encode(L"AIMAIMAIM\xEB");
  101. EXPECT_EQ(visualized, "230 91 11 91 11 91 11 254 235 108"); //Activate when additional rectangulars are available
  102. //Expl: 230 = shift to C40, "91 11" = "AIM",
  103. //"�" in C40 encodes to: 1 30 2 11 which doesn't fit into a triplet
  104. //"10 243" =
  105. //254 = unlatch, 235 = Upper Shift, 108 = � = 0xEB/235 - 128 + 1
  106. //"else" case
  107. }
  108. TEST(DMHighLevelEncodeTest, C40EncodationSpecExample)
  109. {
  110. //Example in Figure 1 in the spec
  111. std::string visualized = Encode(L"A1B2C3D4E5F6G7H8I9J0K1L2");
  112. EXPECT_EQ(visualized, "230 88 88 40 8 107 147 59 67 126 206 78 126 144 121 35 47 254");
  113. }
  114. TEST(DMHighLevelEncodeTest, C40EncodationSpecialCases1)
  115. {
  116. //Special tests avoiding ultra-long test strings because these tests are only used
  117. //with the 16x48 symbol (47 data codewords)
  118. DataMatrix::OverrideSymbolSet(TEST_SYMBOLS, Size(TEST_SYMBOLS));
  119. std::string visualized = Encode(L"AIMAIMAIMAIMAIMAIM");
  120. EXPECT_EQ(visualized, "230 91 11 91 11 91 11 91 11 91 11 91 11");
  121. //case "a": Unlatch is not required
  122. visualized = Encode(L"AIMAIMAIMAIMAIMAI");
  123. EXPECT_EQ(visualized, "230 91 11 91 11 91 11 91 11 91 11 90 241");
  124. // case "b": Add trailing shift 0 and Unlatch is not required
  125. visualized = Encode(L"AIMAIMAIMAIMAIMA");
  126. EXPECT_EQ(visualized, "230 91 11 91 11 91 11 91 11 91 11 254 66");
  127. // case "c": Unlatch and write last character in ASCII
  128. DataMatrix::UseDefaultSymbolSet();
  129. visualized = Encode(L"AIMAIMAIMAIMAIMAI");
  130. EXPECT_EQ(visualized, "230 91 11 91 11 91 11 91 11 91 11 254 66 74 129 237");
  131. visualized = Encode(L"AIMAIMAIMA");
  132. EXPECT_EQ(visualized, "230 91 11 91 11 91 11 66");
  133. // case "d": Skip Unlatch and write last character in ASCII
  134. }
  135. TEST(DMHighLevelEncodeTest, C40EncodationSpecialCases2) {
  136. std::string visualized = Encode(L"AIMAIMAIMAIMAIMAIMAI");
  137. EXPECT_EQ(visualized, "230 91 11 91 11 91 11 91 11 91 11 91 11 254 66 74");
  138. //available > 2, rest = 2 --> unlatch and encode as ASCII
  139. }
  140. TEST(DMHighLevelEncodeTest, TextEncodation)
  141. {
  142. std::string visualized = Encode(L"aimaimaim");
  143. EXPECT_EQ(visualized, "239 91 11 91 11 91 11 254");
  144. //239 shifts to Text encodation, 254 unlatches
  145. visualized = Encode(L"aimaimaim'");
  146. EXPECT_EQ(visualized, "239 91 11 91 11 91 11 254 40 129");
  147. // EXPECT_EQ(visualized, "239 91 11 91 11 91 11 7 49 254");
  148. // This is an alternative, but doesn't strictly follow the rules in the spec.
  149. visualized = Encode(L"aimaimaIm");
  150. EXPECT_EQ(visualized, "239 91 11 91 11 87 218 110");
  151. visualized = Encode(L"aimaimaimB");
  152. EXPECT_EQ(visualized, "239 91 11 91 11 91 11 254 67 129");
  153. visualized = Encode(L"aimaimaim{txt}\x04");
  154. EXPECT_EQ(visualized, "239 91 11 91 11 91 11 16 218 236 107 181 69 254 129 237");
  155. }
  156. TEST(DMHighLevelEncodeTest, X12Encodation)
  157. {
  158. // 238 shifts to X12 encodation, 254 unlatches
  159. std::string visualized = Encode(L"ABC>ABC123>AB");
  160. EXPECT_EQ(visualized, "238 89 233 14 192 100 207 44 31 67");
  161. visualized = Encode(L"ABC>ABC123>ABC");
  162. EXPECT_EQ(visualized, "238 89 233 14 192 100 207 44 31 254 67 68");
  163. visualized = Encode(L"ABC>ABC123>ABCD");
  164. EXPECT_EQ(visualized, "238 89 233 14 192 100 207 44 31 96 82 254");
  165. visualized = Encode(L"ABC>ABC123>ABCDE");
  166. EXPECT_EQ(visualized, "238 89 233 14 192 100 207 44 31 96 82 70");
  167. visualized = Encode(L"ABC>ABC123>ABCDEF");
  168. EXPECT_EQ(visualized, "238 89 233 14 192 100 207 44 31 96 82 254 70 71 129 237");
  169. }
  170. TEST(DMHighLevelEncodeTest, EDIFACTEncodation)
  171. {
  172. // 240 shifts to EDIFACT encodation
  173. std::string visualized = Encode(L".A.C1.3.DATA.123DATA.123DATA");
  174. EXPECT_EQ(visualized, "240 184 27 131 198 236 238 16 21 1 187 28 179 16 21 1 187 28 179 16 21 1");
  175. visualized = Encode(L".A.C1.3.X.X2..");
  176. EXPECT_EQ(visualized, "240 184 27 131 198 236 238 98 230 50 47 47");
  177. visualized = Encode(L".A.C1.3.X.X2.");
  178. EXPECT_EQ(visualized, "240 184 27 131 198 236 238 98 230 50 47 129");
  179. visualized = Encode(L".A.C1.3.X.X2");
  180. EXPECT_EQ(visualized, "240 184 27 131 198 236 238 98 230 50");
  181. visualized = Encode(L".A.C1.3.X.X");
  182. EXPECT_EQ(visualized, "240 184 27 131 198 236 238 98 230 31");
  183. visualized = Encode(L".A.C1.3.X.");
  184. EXPECT_EQ(visualized, "240 184 27 131 198 236 238 98 231 192");
  185. visualized = Encode(L".A.C1.3.X");
  186. EXPECT_EQ(visualized, "240 184 27 131 198 236 238 89");
  187. // Checking temporary unlatch from EDIFACT
  188. visualized = Encode(L".XXX.XXX.XXX.XXX.XXX.XXX.\xFCXX.XXX.XXX.XXX.XXX.XXX.XXX");
  189. EXPECT_EQ(visualized, "240 185 134 24 185 134 24 185 134 24 185 134 24 185 134 24 185 134 24"
  190. " 124 47 235 125 240" // <- this is the temporary unlatch
  191. " 97 139 152 97 139 152 97 139 152 97 139 152 97 139 152 97 139 152 89 89");
  192. }
  193. TEST(DMHighLevelEncodeTest, Base256Encodation)
  194. {
  195. // 231 shifts to Base256 encodation
  196. std::string visualized = Encode(L"\xAB\xE4\xF6\xFC\xE9\xBB");
  197. EXPECT_EQ(visualized, "231 44 108 59 226 126 1 104");
  198. visualized = Encode(L"\xAB\xE4\xF6\xFC\xE9\xE0\xBB");
  199. EXPECT_EQ(visualized, "231 51 108 59 226 126 1 141 254 129");
  200. visualized = Encode(L"\xAB\xE4\xF6\xFC\xE9\xE0\xE1\xBB");
  201. EXPECT_EQ(visualized, "231 44 108 59 226 126 1 141 36 147");
  202. visualized = Encode(L" 23\xA3"); // ASCII only (for reference)
  203. EXPECT_EQ(visualized, "33 153 235 36 129");
  204. visualized = Encode(L"\xAB\xE4\xF6\xFC\xE9\xBB 234"); // Mixed Base256 + ASCII
  205. EXPECT_EQ(visualized, "231 51 108 59 226 126 1 104 99 153 53 129");
  206. visualized = Encode(L"\xAB\xE4\xF6\xFC\xE9\xBB 23\xA3 1234567890123456789");
  207. EXPECT_EQ(visualized, "231 55 108 59 226 126 1 104 99 10 161 167 185 142 164 186 208"
  208. " 220 142 164 186 208 58 129 59 209 104 254 150 45");
  209. visualized = Encode(CreateBinaryMessage(20));
  210. EXPECT_EQ(visualized, "231 44 108 59 226 126 1 141 36 5 37 187 80 230 123 17 166 60 210 103 253 150");
  211. visualized = Encode(CreateBinaryMessage(19)); // padding necessary at the end
  212. EXPECT_EQ(visualized, "231 63 108 59 226 126 1 141 36 5 37 187 80 230 123 17 166 60 210 103 1 129");
  213. visualized = Encode(CreateBinaryMessage(276));
  214. std::string expectedStart = "231 38 219 2 208 120 20 150 35";
  215. std::string epxectedEnd = "146 40 194 129";
  216. EXPECT_EQ(visualized.substr(0, expectedStart.length()), expectedStart);
  217. EXPECT_EQ(visualized.substr(visualized.length() - epxectedEnd.length()), epxectedEnd);
  218. visualized = Encode(CreateBinaryMessage(277));
  219. expectedStart = "231 38 220 2 208 120 20 150 35";
  220. epxectedEnd = "146 40 190 87";
  221. EXPECT_EQ(visualized.substr(0, expectedStart.length()), expectedStart);
  222. EXPECT_EQ(visualized.substr(visualized.length() - epxectedEnd.length()), epxectedEnd);
  223. }
  224. TEST(DMHighLevelEncodeTest, UnlatchingFromC40)
  225. {
  226. std::string visualized = Encode(L"AIMAIMAIMAIMaimaimaim");
  227. EXPECT_EQ(visualized, "230 91 11 91 11 91 11 254 66 74 78 239 91 11 91 11 91 11");
  228. }
  229. TEST(DMHighLevelEncodeTest, UnlatchingFromText)
  230. {
  231. std::string visualized = Encode(L"aimaimaimaim12345678");
  232. EXPECT_EQ(visualized, "239 91 11 91 11 91 11 91 11 254 142 164 186 208 129 237");
  233. }
  234. TEST(DMHighLevelEncodeTest, tHelloWorld)
  235. {
  236. std::string visualized = Encode(L"Hello World!");
  237. EXPECT_EQ(visualized, "73 239 116 130 175 123 148 64 158 233 254 34");
  238. }
  239. TEST(DMHighLevelEncodeTest, Bug1664266)
  240. {
  241. // There was an exception and the encoder did not handle the unlatching from
  242. // EDIFACT encoding correctly
  243. std::string visualized = Encode(L"CREX-TAN:h");
  244. EXPECT_EQ(visualized, "240 13 33 88 181 64 78 124 59 105");
  245. visualized = Encode(L"CREX-TAN:hh");
  246. EXPECT_EQ(visualized, "240 13 33 88 181 64 78 124 59 105 105 129");
  247. visualized = Encode(L"CREX-TAN:hhh");
  248. EXPECT_EQ(visualized, "240 13 33 88 181 64 78 124 59 105 105 105");
  249. }
  250. TEST(DMHighLevelEncodeTest, X12Unlatch)
  251. {
  252. std::string visualized = Encode(L"*DTCP01");
  253. EXPECT_EQ(visualized, "238 9 10 104 141 254 50 129");
  254. }
  255. TEST(DMHighLevelEncodeTest, X12Unlatch2)
  256. {
  257. std::string visualized = Encode(L"*DTCP0");
  258. EXPECT_EQ(visualized, "238 9 10 104 141");
  259. }
  260. TEST(DMHighLevelEncodeTest, Bug3048549)
  261. {
  262. // There was an IllegalArgumentException for an illegal character here because
  263. // of an encoding problem of the character 0x0060 in Java source code.
  264. std::string visualized = Encode(L"fiykmj*Rh2`,e6");
  265. EXPECT_EQ(visualized, "239 122 87 154 40 7 171 115 207 12 130 71 155 254 129 237");
  266. }
  267. TEST(DMHighLevelEncodeTest, MacroCharacters)
  268. {
  269. std::string visualized = Encode(L"[)>\x1E""05\x1D""5555\x1C""6666\x1E\x04");
  270. //EXPECT_EQ(visualized, "92 42 63 31 135 30 185 185 29 196 196 31 5 129 87 237");
  271. EXPECT_EQ(visualized, "236 185 185 29 196 196 129 56");
  272. }
  273. TEST(DMHighLevelEncodeTest, EncodingWithStartAsX12AndLatchToEDIFACTInTheMiddle)
  274. {
  275. std::string visualized = Encode(L"*MEMANT-1F-MESTECH");
  276. EXPECT_EQ(visualized, "238 10 99 164 204 254 240 82 220 70 180 209 83 80 80 200");
  277. }
  278. TEST(DMHighLevelEncodeTest, EDIFACTWithEODBug)
  279. {
  280. std::string visualized = Visualize(
  281. DataMatrix::Encode(L"abc<->ABCDE", CharacterSet::ISO8859_1, DataMatrix::SymbolShape::SQUARE, -1, -1, -1, -1));
  282. // switch to EDIFACT on '<', uses 10 code words + 2 padding. Buggy code introduced invalid 254 after the 5
  283. EXPECT_EQ(visualized, "98 99 100 240 242 223 129 8 49 5 129 147");
  284. }
  285. // @Ignore
  286. // @Test
  287. // public void testDataURL() {
  288. //
  289. // byte[] data = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
  290. // 0x7E, 0x7F, (byte) 0x80, (byte) 0x81, (byte) 0x82};
  291. // String expected = encodeHighLevel(new String(data, StandardCharsets.ISO_8859_1));
  292. // String visualized = encodeHighLevel("url(data:text/plain;charset=iso-8859-1,"
  293. // + "%00%01%02%03%04%05%06%07%08%09%0A%7E%7F%80%81%82)");
  294. // assertEquals(expected, visualized);
  295. // assertEquals("1 2 3 4 5 6 7 8 9 10 11 231 153 173 67 218 112 7", visualized);
  296. //
  297. // visualized = encodeHighLevel("url(data:;base64,flRlc3R+)");
  298. // assertEquals("127 85 102 116 117 127 129 56", visualized);
  299. // }
  300. //
  301. // private static String encodeHighLevel(String msg) {
  302. // CharSequence encoded = HighLevelEncoder.encodeHighLevel(msg);
  303. // //DecodeHighLevel.decode(encoded);
  304. // return visualize(encoded);
  305. // }
  306. //
  307. // /**
  308. // * Convert a string of char codewords into a different string which lists each character
  309. // * using its decimal value.
  310. // *
  311. // * @param codewords the codewords
  312. // * @return the visualized codewords
  313. // */
  314. // static String visualize(CharSequence codewords) {
  315. // StringBuilder sb = new StringBuilder();
  316. // for (int i = 0; i < codewords.length(); i++) {
  317. // if (i > 0) {
  318. // sb.append(' ');
  319. // }
  320. // sb.append((int) codewords.charAt(i));
  321. // }
  322. // return sb.toString();
  323. // }
  324. //
  325. //}