ValueStoreWalReaderParseJsonNoStartObjectTest.java
/*******************************************************************************
* Copyright (c) 2025 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.sail.nativerdf.wal;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
/**
* Covers the parseJson branch where the first token is not START_OBJECT, by writing a frame with a single newline as
* JSON payload. The reader should ignore the frame and proceed without errors.
*/
class ValueStoreWalReaderParseJsonNoStartObjectTest {
@TempDir
Path tempDir;
@Test
void frameNotStartingWithStartObjectIsIgnored() throws Exception {
Path walDir = tempDir.resolve(ValueStoreWalConfig.DEFAULT_DIRECTORY_NAME);
Files.createDirectories(walDir);
Path seg = walDir.resolve("wal-1.v1");
ByteArrayOutputStream out = new ByteArrayOutputStream();
// Valid header frame (minimal '{}') with correct CRC
byte[] hdr = new byte[] { '{', '}' };
out.write(lenLE(hdr.length));
out.write(hdr);
out.write(intLE(crc32c(hdr)));
// Non-object JSON: just a newline (0x0A)
out.write(lenLE(1));
out.write(new byte[] { '\n' });
out.write(intLE(crc32c(new byte[] { '\n' })));
Files.write(seg, out.toByteArray());
ValueStoreWalConfig cfg = ValueStoreWalConfig.builder().walDirectory(walDir).storeUuid("s").build();
try (ValueStoreWalReader reader = ValueStoreWalReader.open(cfg)) {
ValueStoreWalReader.ScanResult res = reader.scan();
assertThat(res.records()).isEmpty();
assertThat(res.complete()).isTrue();
}
}
private static byte[] lenLE(int v) {
ByteBuffer b = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(v);
b.flip();
byte[] a = new byte[4];
b.get(a);
return a;
}
private static int crc32c(byte[] data) {
java.util.zip.CRC32C c = new java.util.zip.CRC32C();
c.update(data, 0, data.length);
return (int) c.getValue();
}
private static byte[] intLE(int v) {
return lenLE(v);
}
}