寻求覆盖Base64全部64字符的测试串,用于JUnit验证两种Base64实现一致性
嗨,这个需求非常合理——要验证两种Base64实现对所有字符的处理逻辑一致,确实需要覆盖完整字符集的测试用例。我来帮你搞定这个问题:
为什么需要覆盖全64个字符?
标准Base64的字符集包含64个不同符号:A-Z、a-z、0-9、+和/(不同实现可能有URL安全变体,但sun.misc.BASE64和java.util.Base64的默认实现都是标准字符集)。每个符号对应一个6位的二进制值(0到63)。要确保两种实现完全兼容,就得让编码结果覆盖这所有64个字符,验证每个字符的编解码逻辑都一致。
如何构造覆盖全字符集的测试数据?
Base64是将每3个字节(24位)拆分成4个6位的组,每个组对应一个Base64字符。要覆盖所有64个字符,我们需要让编码后的结果包含所有64个6位组合,对应的输入数据需要是48字节(64个6位组 = 64*6 = 384位 = 48字节)。
下面是生成这个测试数据的Java代码,以及完整的兼容性测试逻辑:
1. 生成覆盖全字符集的测试数据
import java.util.Arrays; import java.util.Base64; public class Base64FullCharsetGenerator { public static void main(String[] args) { byte[] testData = generateFullCharsetTestData(); // 编码后会得到包含所有64个Base64字符的字符串 String encoded = Base64.getEncoder().encodeToString(testData); System.out.println("覆盖全字符集的Base64编码结果:"); System.out.println(encoded); // 验证解码正确性 byte[] decoded = Base64.getDecoder().decode(encoded); System.out.println("\n解码结果与原数据是否一致:" + Arrays.equals(testData, decoded)); } private static byte[] generateFullCharsetTestData() { byte[] testData = new byte[48]; int index = 0; // 遍历所有6位的可能值(0-63),依次填充到输入字节数组中 for (int i = 0; i < 64; i++) { if (index % 3 == 0) { // 填充第一个字节的高6位 testData[index] = (byte) (i << 2); } else if (index % 3 == 1) { // 补全第一个字节的低2位,填充第二个字节的高4位 testData[index-1] |= (byte) ((i >> 4) & 0x03); testData[index] = (byte) ((i << 4) & 0xF0); } else { // 补全第二个字节的低4位,填充第三个字节的所有位(高2位+低6位) testData[index-1] |= (byte) ((i >> 2) & 0x0F); testData[index] = (byte) ((i << 6) & 0xC0); testData[index] |= (byte) (i & 0x3F); index++; // 跳到下一组的第一个字节 } index++; } return testData; } }
2. 两种Base64实现的兼容性测试
import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import java.util.Arrays; import java.util.Base64; public class Base64CompatibilityTest { public static void main(String[] args) throws Exception { byte[] testData = generateFullCharsetTestData(); // --- sun.misc.BASE64 编码 --- BASE64Encoder sunEncoder = new BASE64Encoder(); String sunEncoded = sunEncoder.encode(testData); // 注意:sun的编码器默认每76字符加换行,需要去掉换行符和java.util的结果对齐 sunEncoded = sunEncoded.replaceAll("\\r?\\n", ""); // --- java.util.Base64 编码 --- String utilEncoded = Base64.getEncoder().encodeToString(testData); // 1. 对比编码结果是否一致 System.out.println("编码结果是否完全一致:" + sunEncoded.equals(utilEncoded)); // 2. 交叉解码验证 // sun编码结果用util解码 byte[] decodedByUtil = Base64.getDecoder().decode(sunEncoded); System.out.println("sun编码→util解码 与原数据一致:" + Arrays.equals(testData, decodedByUtil)); // util编码结果用sun解码 BASE64Decoder sunDecoder = new BASE64Decoder(); byte[] decodedBySun = sunDecoder.decodeBuffer(utilEncoded); System.out.println("util编码→sun解码 与原数据一致:" + Arrays.equals(testData, decodedBySun)); } private static byte[] generateFullCharsetTestData() { // 复用上面的生成逻辑 byte[] testData = new byte[48]; int index = 0; for (int i = 0; i < 64; i++) { if (index % 3 == 0) { testData[index] = (byte) (i << 2); } else if (index % 3 == 1) { testData[index-1] |= (byte) ((i >> 4) & 0x03); testData[index] = (byte) ((i << 4) & 0xF0); } else { testData[index-1] |= (byte) ((i >> 2) & 0x0F); testData[index] = (byte) ((i << 6) & 0xC0); testData[index] |= (byte) (i & 0x3F); index++; } index++; } return testData; } }
额外建议
除了全字符集测试,还可以补充几个边缘用例确保覆盖所有场景:
- 空字符串/空字节数组
- 1字节输入(编码后会带两个填充
=) - 2字节输入(编码后会带一个填充
=) - 包含特殊字节值(比如0x00、0xFF)的输入
内容的提问来源于stack exchange,提问作者Mira Welner
相关产品推荐
相关产品推荐

