Skip to content

Commit 04513dd

Browse files
committed
Added test for hex encoding method
1 parent ebc913b commit 04513dd

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,4 +604,32 @@ public static String convertToUnhexExpression(byte[] bytes) {
604604
}
605605
return new String(hexChars, StandardCharsets.US_ASCII);
606606
}
607+
608+
/**
609+
* Decodes a hex string into a byte array.
610+
* Each pair of characters in the input is interpreted as a hexadecimal byte value.
611+
*
612+
* @param hexString hex-encoded string (must have even length)
613+
* @return decoded byte array, or empty array if input is null or empty
614+
* @throws IllegalArgumentException if the string has odd length or contains non-hex characters
615+
*/
616+
public static byte[] decodeHexString(String hexString) {
617+
if (hexString == null || hexString.isEmpty()) {
618+
return new byte[0];
619+
}
620+
int len = hexString.length();
621+
if (len % 2 != 0) {
622+
throw new IllegalArgumentException("Hex string must have even length, got " + len);
623+
}
624+
byte[] result = new byte[len / 2];
625+
for (int i = 0; i < result.length; i++) {
626+
int hi = Character.digit(hexString.charAt(i * 2), 16);
627+
int lo = Character.digit(hexString.charAt(i * 2 + 1), 16);
628+
if (hi == -1 || lo == -1) {
629+
throw new IllegalArgumentException("Invalid hex character at index " + (hi == -1 ? i * 2 : i * 2 + 1));
630+
}
631+
result[i] = (byte) ((hi << 4) | lo);
632+
}
633+
return result;
634+
}
607635
}

jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcUtilsTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
import org.testng.Assert;
77
import org.testng.annotations.*;
88

9+
import java.io.InputStream;
910
import java.math.BigDecimal;
1011
import java.sql.SQLException;
1112
import java.time.Instant;
1213
import java.time.ZoneId;
1314
import java.util.Arrays;
1415
import java.util.List;
16+
import java.util.zip.CRC32;
1517

1618
import static org.testng.Assert.assertEquals;
1719
import static org.testng.Assert.assertNull;
@@ -109,4 +111,35 @@ public void testAllDataTypesMapped() {
109111
Assert.assertNotNull(JdbcUtils.convertToJavaClass(dt), "Data type " + dt + " has no mapping to java class");
110112
}
111113
}
114+
115+
@Test(groups = {"unit"})
116+
public void testConvertToUnhexExpression() throws Exception {
117+
// Load binary file from test resources
118+
byte[] originalBytes;
119+
try (InputStream is = getClass().getResourceAsStream("/ch_logo.png")) {
120+
Assert.assertNotNull(is, "ch_logo.png not found in test resources");
121+
originalBytes = is.readAllBytes();
122+
}
123+
124+
// Calculate checksum of original bytes
125+
CRC32 originalChecksum = new CRC32();
126+
originalChecksum.update(originalBytes);
127+
long expectedChecksum = originalChecksum.getValue();
128+
129+
// Convert to unhex expression
130+
String unhexExpr = JdbcUtils.convertToUnhexExpression(originalBytes);
131+
Assert.assertTrue(unhexExpr.startsWith("unhex('"), "Expression should start with unhex('");
132+
Assert.assertTrue(unhexExpr.endsWith("')"), "Expression should end with ')");
133+
134+
// Extract hex string and decode back to bytes
135+
String hexString = unhexExpr.substring("unhex('".length(), unhexExpr.length() - "')".length());
136+
assertEquals(hexString.length(), originalBytes.length * 2, "Hex string length should be twice the byte array length");
137+
138+
byte[] decodedBytes = JdbcUtils.decodeHexString(hexString);
139+
140+
// Verify checksum of decoded bytes matches original
141+
CRC32 decodedChecksum = new CRC32();
142+
decodedChecksum.update(decodedBytes);
143+
assertEquals(decodedChecksum.getValue(), expectedChecksum, "Checksum of decoded bytes should match original");
144+
}
112145
}
1.3 KB
Loading

0 commit comments

Comments
 (0)