diff options
Diffstat (limited to 'test/codes')
| -rw-r--r-- | test/codes/LinearTest.mc | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/test/codes/LinearTest.mc b/test/codes/LinearTest.mc new file mode 100644 index 0000000..ed42ccf --- /dev/null +++ b/test/codes/LinearTest.mc @@ -0,0 +1,146 @@ +// Author: cirakg & claude ai +// Summary: Tests for the linear barcode encoders: zxing-cpp reference rows, validation messages, and a dump for decoding. + +import Toybox.Lang; +import Toybox.Test; + +(:test) +module LinearFixtures { + + function moduleText(m as ByteArray) as String { + var s = ""; + for (var i = 0; i < m.size(); i++) { + s += m[i] == 1 ? "1" : "0"; + } + return s; + } + + // The error message for payload, or "" when it encodes. + function errorOf(symbology as Number, payload as String, options as Number) as String { + var r = Codes.encode(symbology, payload, options); + return r instanceof Codes.CodeError ? r.message : ""; + } + + function opts(check as Number) as Number { + return Codes.OPT_SHOW_TEXT | (check << Codes.OPT_CHECK_SHIFT) | 1; + } +} + +// README 12.4 check 1: identical modules to zxing-cpp for every row. +(:test) +function linearCodesMatchTheReference(logger as Test.Logger) as Boolean { + var rows = CodeVectors.LINEAR; + for (var i = 0; i < rows.size(); i++) { + var row = rows[i] as Array; + var symbology = row[0] as Number; + var payload = row[1] as String; + var result = Codes.encode(symbology, payload, row[2] as Number); + if (result instanceof Codes.CodeError) { + logger.error("row " + i + " (" + Codes.name(symbology) + " '" + payload + "'): " + result.message); + return false; + } + var got = LinearFixtures.moduleText(result.modules); + var expected = row[3] as String; + if (symbology == Codes.CODE128) { + // zxing-cpp 3 writes Code 128 through zint, whose optimal encoder + // breaks ties between equally short encodings differently (for + // example set C for a final digit pair). Both are optimal: the + // length must match, and the code is decoded by check_codes.py. + logger.debug("CODEDUMP " + symbology + " " + Bytes.toHex(Bytes.fromUtf8(result.text)) + " " + got); + if (got.length() != expected.length()) { + logger.error("row " + i + " (Code 128 '" + payload + "') has " + got.length() + " modules, zxing-cpp " + + expected.length()); + return false; + } + continue; + } + if (!got.equals(expected)) { + logger.error("row " + i + " (" + Codes.name(symbology) + " '" + payload + "') differs:\n got " + got + "\n exp " + expected); + return false; + } + } + logger.debug("CODES reference rows=" + rows.size()); + return true; +} + +(:test) +function linearCheckDigitModes(logger as Test.Logger) as Boolean { + var add = LinearFixtures.opts(Codes.CHECK_ADD_VERIFY); + var fix = LinearFixtures.opts(Codes.CHECK_FIX); + var off = LinearFixtures.opts(Codes.CHECK_OFF); + var added = Codes.encode(Codes.EAN13, "590123412345", add) as Codes.LinearCode; + var fixed = Codes.encode(Codes.EAN13, "5901234123450", fix) as Codes.LinearCode; + var kept = Codes.encode(Codes.EAN13, "5901234123450", off) as Codes.LinearCode; + var wrong = LinearFixtures.errorOf(Codes.EAN13, "5901234123450", add); + var offShort = LinearFixtures.errorOf(Codes.EAN13, "590123412345", off); + return added.text.equals("5901234123457") && added.note != null + && fixed.text.equals("5901234123457") && (fixed.note as String).find("was 0") != null + && kept.text.equals("5901234123450") + && wrong.find("check digit should be 7, got 0") != null && wrong.find("Fix if wrong") != null + && offShort.find("needs all 13 digits") != null; +} + +(:test) +function linearValidationMessages(logger as Test.Logger) as Boolean { + var o = LinearFixtures.opts(Codes.CHECK_ADD_VERIFY); + var off = LinearFixtures.opts(Codes.CHECK_OFF); + var cases = [ + [Codes.EAN13, "59012341234a", o, "digits only"], + [Codes.EAN13, "123", o, "needs 12 or 13 digits"], + [Codes.UPCA, "1234", o, "UPC-A needs 11 or 12"], + [Codes.EAN8, "12345678", o, "check digit should be"], + [Codes.UPCE, "2123456", o, "number system must be 0 or 1"], + [Codes.UPCE, "0502553", o, "not a valid zero suppression"], + [Codes.UPCE, "12345", o, "6, 7 or 8 digits"], + [Codes.ITF, "123", off, "even number of digits"], + [Codes.ITF, "1234", o, "odd number of digits"], + [Codes.CODE39, "abc", o, "isn't allowed"], + [Codes.CODE128, "Ünï", o, "printable ASCII"], + [Codes.CODE128, "", o, "needs some text"], + [Codes.CODABAR, "A123", o, "both ends or at neither"], + [Codes.CODABAR, "A1B2A", o, "isn't allowed there"], + [Codes.QR, "hello", o, "not supported yet"] + ]; + for (var i = 0; i < cases.size(); i++) { + var c = cases[i] as Array; + var message = LinearFixtures.errorOf(c[0] as Number, c[1] as String, c[2] as Number); + if (message.find(c[3] as String) == null) { + logger.error("case " + i + ": got '" + message + "'"); + return false; + } + } + var codabar = Codes.encode(Codes.CODABAR, "40156", o) as Codes.LinearCode; + return codabar.text.equals("A40156A") && codabar.note != null; +} + +// README 12.4 check 2: dumps encoder outputs for seeded random payloads; +// tools/check_codes.py decodes them with zxing-cpp after the test run. +(:test) +function linearDumpForDecoding(logger as Test.Logger) as Boolean { + var seed = 12345; + var count = 0; + var symbologies = [Codes.EAN13, Codes.EAN8, Codes.UPCA, Codes.UPCE, Codes.CODE128, Codes.CODE39, Codes.ITF, Codes.CODABAR]; + var o = LinearFixtures.opts(Codes.CHECK_ADD_VERIFY); + for (var i = 0; i < 160; i++) { + var symbology = symbologies[i % symbologies.size()] as Number; + var length = [12, 7, 11, 7, 10, 8, 10, 8][i % symbologies.size()] as Number; + var alphabet = ["0123456789", "0123456789", "0123456789", "0123456789", + "0123456789 AZaz!#$%&()*+,-./:;<=>?@", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", "0123456789", "0123456789-$:/.+"][i % symbologies.size()] as String; + var text = ""; + for (var k = 0; k < length; k++) { + seed = (seed * 1103515245 + 12345) & 0x7FFFFFFF; + var at = (seed >> 8) % alphabet.length(); + text += alphabet.substring(at, at + 1); + } + if (symbology == Codes.UPCE) { + text = "0" + text.substring(1, 7); + } + var result = Codes.encode(symbology, text, o); + if (result instanceof Codes.CodeError) { + continue; // invalid random UPC-E suppressions are expected + } + logger.debug("CODEDUMP " + symbology + " " + Bytes.toHex(Bytes.fromUtf8(result.text)) + " " + LinearFixtures.moduleText(result.modules)); + count++; + } + return count > 120; +} |
