diff --git a/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoderTestAdapter.java b/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoderTestAdapter.java new file mode 100644 index 000000000..ac6092a52 --- /dev/null +++ b/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoderTestAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright 2022 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.pdf417.encoder; + +import com.google.zxing.WriterException; + +import java.nio.charset.Charset; + +/** + * Test adapter for PDF417HighLevelEncoder to be called solely from unit tests. + */ + +public final class PDF417HighLevelEncoderTestAdapter { + + private PDF417HighLevelEncoderTestAdapter() { + } + + public static String encodeHighLevel(String msg, Compaction compaction, Charset encoding) throws WriterException { + return PDF417HighLevelEncoder.encodeHighLevel(msg, compaction, encoding); + } +} diff --git a/core/src/test/java/com/google/zxing/pdf417/decoder/PDF417DecoderTestCase.java b/core/src/test/java/com/google/zxing/pdf417/decoder/PDF417DecoderTestCase.java index 50cc9e48f..5f6ac8c08 100644 --- a/core/src/test/java/com/google/zxing/pdf417/decoder/PDF417DecoderTestCase.java +++ b/core/src/test/java/com/google/zxing/pdf417/decoder/PDF417DecoderTestCase.java @@ -17,10 +17,16 @@ package com.google.zxing.pdf417.decoder; import com.google.zxing.FormatException; +import com.google.zxing.WriterException; import com.google.zxing.pdf417.PDF417ResultMetadata; import com.google.zxing.common.DecoderResult; +import com.google.zxing.pdf417.encoder.Compaction; +import com.google.zxing.pdf417.encoder.PDF417HighLevelEncoderTestAdapter; + import org.junit.Assert; import org.junit.Test; +import java.nio.charset.StandardCharsets; +import java.util.Random; /** * Tests {@link DecodedBitStreamParser}. @@ -175,4 +181,161 @@ public class PDF417DecoderTestCase extends Assert { DecodedBitStreamParser.decode(sampleCodes, "0"); } + @Test + public void testUppercase() throws WriterException, FormatException { + //encodeDecode("", 0); + performEncodeTest('A', new int[] { 3, 4, 5, 6, 4, 4, 5, 5}); + } + + @Test + public void testNumeric() throws WriterException, FormatException { + performEncodeTest('1', new int[] { 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10}); + } + + @Test + public void testByte() throws WriterException, FormatException { + performEncodeTest('\u00c4', new int[] { 3, 4, 5, 6, 7, 7, 8}); + } + + @Test + public void testUppercaseLowercaseMix1() throws WriterException, FormatException { + encodeDecode("aA", 4); + encodeDecode("aAa", 5); + encodeDecode("Aa", 4); + encodeDecode("Aaa", 5); + encodeDecode("AaA", 5); + encodeDecode("AaaA", 6); + encodeDecode("Aaaa", 6); + encodeDecode("AaAaA", 5); + encodeDecode("AaaAaaA", 6); + encodeDecode("AaaAAaaA", 7); + } + + @Test + public void testPunctuation() throws WriterException, FormatException { + performEncodeTest(';', new int[] { 3, 4, 5, 6, 6, 7, 8}); + encodeDecode(";;;;;;;;;;;;;;;;", 17); + } + + @Test + public void testUppercaseLowercaseMix2() throws WriterException, FormatException { + performPermutationTest(new char[] {'A', 'a'}, 10, 8972); + } + + @Test + public void testUppercaseNumericMix() throws WriterException, FormatException { + performPermutationTest(new char[] {'A', '1'}, 14, 192510); + } + + @Test + public void testUppercaseMixedMix() throws WriterException, FormatException { + performPermutationTest(new char[] {'A', '1', ' ', ';'}, 7, 106060); + } + + @Test + public void testUppercasePunctuationMix() throws WriterException, FormatException { + performPermutationTest(new char[] {'A', ';'}, 10, 8967); + } + + @Test + public void testUppercaseByteMix() throws WriterException, FormatException { + performPermutationTest(new char[] {'A', '\u00c4'}, 10, 11222); + } + + @Test + public void testLowercaseByteMix() throws WriterException, FormatException { + performPermutationTest(new char[] {'a', '\u00c4'}, 10, 11233); + } + + public void testUppercaseLowercaseNumericMix() throws WriterException, FormatException { + performPermutationTest(new char[] {'A', 'a', '1'}, 7, 15491); + } + + @Test + public void testUppercaseLowercasePunctuationMix() throws WriterException, FormatException { + performPermutationTest(new char[] {'A', 'a', ';'}, 7, 15491); + } + + @Test + public void testUppercaseLowercaseByteMix() throws WriterException, FormatException { + performPermutationTest(new char[] {'A', 'a', '\u00c4'}, 7, 17288); + } + + @Test + public void testLowercasePunctuationByteMix() throws WriterException, FormatException { + performPermutationTest(new char[] {'a', ';', '\u00c4'}, 7, 17427); + } + + @Test + public void testUppercaseLowercaseNumericPunctuationMix() throws WriterException, FormatException { + performPermutationTest(new char[] {'A', 'a', '1', ';'}, 7, 120479); + } + + @Test + public void testBinaryData() throws WriterException, FormatException { + byte[] bytes = new byte[500]; + Random random = new Random(0); + int total = 0; + for (int i = 0; i < 10000; i++) { + random.nextBytes(bytes); + total += encodeDecode(new String(bytes, StandardCharsets.ISO_8859_1)); + } + assertEquals(4190044, total); + } + + private static void encodeDecode(String input, int expectedLength) throws WriterException, FormatException { + assertEquals(expectedLength, encodeDecode(input)); + } + + private static int encodeDecode(String input) throws WriterException, FormatException { + String s = PDF417HighLevelEncoderTestAdapter.encodeHighLevel(input, Compaction.AUTO, null); + int[] codewords = new int[s.length() + 1]; + codewords[0] = codewords.length; + for (int i = 1; i < codewords.length; i++) { + codewords[i] = s.charAt(i - 1); + } + DecoderResult result = DecodedBitStreamParser.decode(codewords, "0"); + + assertEquals(input, result.getText()); + return codewords.length; + } + + private static int getEndIndex(int length, char[] chars) { + double decimalLength = Math.log10(chars.length); + return (int) Math.ceil(Math.pow(10, decimalLength * length)); + } + + private static String generatePermutation(int index, int length, char[] chars) { + int N = chars.length; + String baseNNumber = Integer.toString(index, N); + while (baseNNumber.length() < length) { + baseNNumber = "0" + baseNNumber; + } + String prefix = ""; + for (int i = 0; i < baseNNumber.length(); i++) { + prefix += chars[baseNNumber.charAt(i) - '0']; + } + return prefix; + } + + private static void performPermutationTest(char[] chars, int length, int expectedTotal) throws WriterException, + FormatException { + int endIndex = getEndIndex(length, chars); + int total = 0; + for (int i = 0; i < endIndex; i++) { + total += encodeDecode(generatePermutation(i, length, chars)); + } + assertEquals(expectedTotal, total); + } + + private static void performEncodeTest(char c, int[] expectedLengths) throws WriterException, FormatException { + for (int i = 0; i < expectedLengths.length; i++) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j <= i; j++) { + sb.append(c); + } + encodeDecode(sb.toString(), expectedLengths[i]); + } + } + }