diff --git a/datablock/src/main/java/tv/hd3g/datablock/DatablockChunkPayloadExtractorImpl.java b/datablock/src/main/java/tv/hd3g/datablock/DatablockChunkPayloadExtractorImpl.java index aed0e884..96d6a050 100644 --- a/datablock/src/main/java/tv/hd3g/datablock/DatablockChunkPayloadExtractorImpl.java +++ b/datablock/src/main/java/tv/hd3g/datablock/DatablockChunkPayloadExtractorImpl.java @@ -30,7 +30,7 @@ import java.util.Optional; import java.util.function.Function; -class DatablockChunkPayloadExtractorImpl implements DatablockChunkPayloadExtractor, IOTraits {// TODO tests +class DatablockChunkPayloadExtractorImpl implements DatablockChunkPayloadExtractor, IOTraits {// TODO tests via E2E private final FileChannel channel; private final long payloadPosition; @@ -42,7 +42,8 @@ class DatablockChunkPayloadExtractorImpl implements DatablockChunkPayloadExtract /** * Always call clean() after getCurrentChunkPayload() */ - DatablockChunkPayloadExtractorImpl(final FileChannel channel, final long payloadPosition, + DatablockChunkPayloadExtractorImpl(final FileChannel channel, + final long payloadPosition, final int payloadSize) { this.channel = Objects.requireNonNull(channel, "\"channel\" can't to be null"); this.payloadPosition = payloadPosition; diff --git a/datablock/src/main/java/tv/hd3g/datablock/DatablockDocument.java b/datablock/src/main/java/tv/hd3g/datablock/DatablockDocument.java index 00449eef..9d633339 100644 --- a/datablock/src/main/java/tv/hd3g/datablock/DatablockDocument.java +++ b/datablock/src/main/java/tv/hd3g/datablock/DatablockDocument.java @@ -20,25 +20,25 @@ import static tv.hd3g.datablock.DatablockDocumentHeader.DOCUMENT_HEADER_LEN; import java.io.IOException; -import java.io.OutputStream; import java.io.UncheckedIOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.function.Consumer; import java.util.function.Function; // TODO add technical readme // TODO add v1 + object storage + defrag // TODO add indexed list -public class DatablockDocument implements IOTraits {// TODO test +public class DatablockDocument implements IOTraits { + + public static final int CHUNK_SEPARATOR_SIZE = 1; private final FileChannel channel; private final ByteBuffer documentHeaderBuffer = ByteBuffer.allocate(DOCUMENT_HEADER_LEN); private final ByteBuffer chunkHeaderBuffer = ByteBuffer.allocate(CHUNK_HEADER_LEN); - private final ByteBuffer chunkSeparator = ByteBuffer.allocate(1); + private final ByteBuffer chunkSeparator = ByteBuffer.allocate(CHUNK_SEPARATOR_SIZE); public DatablockDocument(final FileChannel channel) throws IOException { this.channel = Objects.requireNonNull(channel, "\"channel\" can't to be null"); @@ -47,35 +47,19 @@ public DatablockDocument(final FileChannel channel) throws IOException { } } - public synchronized DatablockDocumentHeader readDocumentHeader() throws IOException { + public synchronized DatablockDocumentHeader getDocumentHeader() throws IOException { documentHeaderBuffer.clear(); checkedRead(channel, 0, documentHeaderBuffer); return new DatablockDocumentHeader(documentHeaderBuffer.flip().asReadOnlyBuffer()); } - /* - * TODO needed ? - * @return newDocumentVersion - */ - /*public synchronized int incrementDocumentVersion() throws IOException { - final var buffer = ByteBuffer.allocate(4 /** documentVersion * - ); - - checkedRead(channel, DOCUMENT_VERSION_POS, buffer); - buffer.flip(); - final var newDocumentVersion = buffer.getInt() + 1; - buffer.reset(); - buffer.putInt(newDocumentVersion); - buffer.flip(); - checkedWrite(channel, DOCUMENT_VERSION_POS, buffer); - return newDocumentVersion; - }*/ - - public synchronized void writeDocumentHeader(final DatablockDocumentHeader header) throws IOException { + public synchronized void putDocumentHeader(final DatablockDocumentHeader header) throws IOException { final var buffer = header.toByteBuffer(); checkedWrite(channel, 0, buffer); } + // FIXME + test APPEND FROM THE EOF ! + /** * @param chunkPayload No reset/flip will be done */ @@ -88,28 +72,21 @@ public synchronized void appendChunk(final byte[] fourCC, final var header = chunkHeader.toByteBuffer(); checkedWrite(channel, header); checkedWrite(channel, chunkPayload); - - chunkSeparator.clear(); - chunkSeparator.put(ZERO_BYTE); - chunkSeparator.flip(); - checkedWrite(channel, chunkSeparator); + writeChunkSeparator(); } public synchronized void appendChunk(final byte[] fourCC, final short version, final boolean archived, - final Consumer writer) throws IOException { + final OutputStreamConsumer writer) throws IOException { final var chunkHeader = new DatablockChunkHeader(fourCC, version, 0, archived); final var header = chunkHeader.toByteBuffer(); checkedWrite(channel, header); try (var outputStream = new DatablockOutputStreamChunk(channel)) { - writer.accept(outputStream); + writer.writeTo(outputStream); } finally { - chunkSeparator.clear(); - chunkSeparator.put(ZERO_BYTE); - chunkSeparator.flip(); - checkedWrite(channel, chunkSeparator); + writeChunkSeparator(); } } @@ -123,19 +100,22 @@ public synchronized DataBlockChunkIndexItem appendEmptyChunk(final byte[] fourCC final var payloadPosition = channel.position(); channel.position(payloadPosition + payloadSize); + writeChunkSeparator(); + return new DataBlockChunkIndexItem(chunkHeader, payloadPosition); + } + + private void writeChunkSeparator() throws IOException { chunkSeparator.clear(); chunkSeparator.put(ZERO_BYTE); chunkSeparator.flip(); checkedWrite(channel, chunkSeparator); - - return new DataBlockChunkIndexItem(chunkHeader, payloadPosition); } public synchronized void documentCrawl(final FoundedDataBlockDocumentChunk chunkCallback) throws IOException { channel.position(DOCUMENT_HEADER_LEN); - while (channel.position() + 1l < channel.size()) { + while (channel.position() <= channel.size()) { chunkHeaderBuffer.clear(); checkedRead(channel, chunkHeaderBuffer); final var header = new DatablockChunkHeader(chunkHeaderBuffer); @@ -173,8 +153,8 @@ public synchronized void documentRefactor(final FileChannel newDocument, newDocument.truncate(DOCUMENT_HEADER_LEN); newDocument.position(0); - final var actualHeader = readDocumentHeader(); - targetDocument.writeDocumentHeader(actualHeader.getIncrementedDocumentVersion()); + final var actualHeader = getDocumentHeader(); + targetDocument.putDocumentHeader(actualHeader.getIncrementedDocumentVersion()); final var actualPos = channel.position(); diff --git a/datablock/src/main/java/tv/hd3g/datablock/DatablockDocumentHeader.java b/datablock/src/main/java/tv/hd3g/datablock/DatablockDocumentHeader.java index 1babb1be..317f7509 100644 --- a/datablock/src/main/java/tv/hd3g/datablock/DatablockDocumentHeader.java +++ b/datablock/src/main/java/tv/hd3g/datablock/DatablockDocumentHeader.java @@ -25,7 +25,7 @@ @Getter @EqualsAndHashCode -public class DatablockDocumentHeader implements IOTraits {// TODO test + debug tools +public class DatablockDocumentHeader implements IOTraits {// TODO debug tools public static final int MAGIC_NUMBER_EXPECTED_SIZE = 8; public static final int DOCUMENT_TYPE_EXPECTED_SIZE = 8; @@ -36,11 +36,6 @@ public class DatablockDocumentHeader implements IOTraits {// TODO test + debug t + 4 /** documentVersion */ + BLANK_EXPECTED_SIZE; - public static final long DOCUMENT_VERSION_POS = MAGIC_NUMBER_EXPECTED_SIZE + - DOCUMENT_TYPE_EXPECTED_SIZE - + 2 /** typeVersion */ - ; - private final byte[] magicNumber; private final byte[] documentType; private final short typeVersion; @@ -94,7 +89,7 @@ ByteBuffer toByteBuffer() { header.putInt(documentVersion); header.put(new byte[BLANK_EXPECTED_SIZE]); header.flip(); - return header.asReadOnlyBuffer(); + return header; } @Override diff --git a/datablock/src/main/java/tv/hd3g/datablock/IOTraits.java b/datablock/src/main/java/tv/hd3g/datablock/IOTraits.java index 7594fab4..3eaf05c6 100644 --- a/datablock/src/main/java/tv/hd3g/datablock/IOTraits.java +++ b/datablock/src/main/java/tv/hd3g/datablock/IOTraits.java @@ -40,7 +40,8 @@ default void checkedWrite(final WritableByteChannel channel, final ByteBuffer bu default void checkedWrite(final FileChannel channel, final long position, final ByteBuffer buffer) throws IOException { - checkIOSize(channel.write(buffer, position), buffer.capacity()); + channel.position(position); + checkIOSize(channel.write(buffer), buffer.capacity()); } default void checkedRead(final ReadableByteChannel channel, final ByteBuffer buffer) throws IOException { @@ -50,7 +51,8 @@ default void checkedRead(final ReadableByteChannel channel, final ByteBuffer buf default void checkedRead(final FileChannel channel, final long position, final ByteBuffer buffer) throws IOException { - checkIOSize(channel.read(buffer, position), buffer.capacity()); + channel.position(position); + checkIOSize(channel.read(buffer), buffer.capacity()); } default void checkEndBlank(final ByteBuffer readFrom, final int blankExpectedSize) { diff --git a/datablock/src/main/java/tv/hd3g/datablock/OutputStreamConsumer.java b/datablock/src/main/java/tv/hd3g/datablock/OutputStreamConsumer.java new file mode 100644 index 00000000..8799155c --- /dev/null +++ b/datablock/src/main/java/tv/hd3g/datablock/OutputStreamConsumer.java @@ -0,0 +1,27 @@ +/* + * This file is part of datablock. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * Copyright (C) hdsdi3g for hd3g.tv 2024 + * + */ +package tv.hd3g.datablock; + +import java.io.IOException; +import java.io.OutputStream; + +@FunctionalInterface +public interface OutputStreamConsumer { + + void writeTo(OutputStream outputStream) throws IOException; + +} diff --git a/datablock/src/test/java/tv/hd3g/datablock/DatablockDocumentHeaderTest.java b/datablock/src/test/java/tv/hd3g/datablock/DatablockDocumentHeaderTest.java new file mode 100644 index 00000000..fe8dda39 --- /dev/null +++ b/datablock/src/test/java/tv/hd3g/datablock/DatablockDocumentHeaderTest.java @@ -0,0 +1,120 @@ +/* + * This file is part of datablock. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * Copyright (C) hdsdi3g for hd3g.tv 2024 + * + */ +package tv.hd3g.datablock; + +import static java.util.Arrays.fill; +import static org.apache.commons.codec.binary.Hex.encodeHexString; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static tv.hd3g.datablock.DatablockDocumentHeader.DOCUMENT_HEADER_LEN; + +import java.nio.ByteBuffer; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import tv.hd3g.commons.testtools.Fake; +import tv.hd3g.commons.testtools.MockToolsExtendsJunit; + +@ExtendWith(MockToolsExtendsJunit.class) +class DatablockDocumentHeaderTest { + + @Fake(min = 8, max = 8) + byte[] magicNumber; + @Fake(min = 8, max = 8) + byte[] documentType; + @Fake + short typeVersion; + @Fake + int documentVersion; + + DatablockDocumentHeader h; + + @BeforeEach + void init() { + h = new DatablockDocumentHeader(magicNumber, documentType, typeVersion, documentVersion); + checkConsts(h); + assertEquals(documentVersion, h.getDocumentVersion()); + } + + @Test + void testInvalidConstructDataSize_magicNumber() { + final var newMagicNumber = new byte[0]; + assertThrows(IllegalArgumentException.class, + () -> new DatablockDocumentHeader(newMagicNumber, documentType, typeVersion, documentVersion)); + } + + @Test + void testInvalidConstructDataSize_documentType() { + final var newDocumentType = new byte[0]; + assertThrows(IllegalArgumentException.class, + () -> new DatablockDocumentHeader(magicNumber, newDocumentType, typeVersion, documentVersion)); + } + + @Test + void testGetIncrementedDocumentVersion() { + final var incremented = h.getIncrementedDocumentVersion(); + checkConsts(incremented); + assertEquals(documentVersion + 1, incremented.getDocumentVersion()); + } + + @Test + void testImpExByteBuffer() { + final var bb = h.toByteBuffer(); + assertNotNull(bb); + assertEquals(0, bb.position()); + assertEquals(DOCUMENT_HEADER_LEN, bb.capacity()); + assertEquals(DOCUMENT_HEADER_LEN, bb.remaining()); + + h = new DatablockDocumentHeader(bb); + checkConsts(h); + assertEquals(documentVersion, h.getDocumentVersion()); + + assertEquals(DOCUMENT_HEADER_LEN, bb.position()); + assertEquals(0, bb.remaining()); + } + + @Test + void testImpByteBuffer_invalidData() { + final var content = new byte[DOCUMENT_HEADER_LEN]; + fill(content, (byte) 1); + final var bb = ByteBuffer.wrap(content); + + assertThrows(IllegalArgumentException.class, + () -> new DatablockDocumentHeader(bb)); + } + + @Test + void testToString() { + assertThat(h.toString()).contains( + encodeHexString(magicNumber), + encodeHexString(documentType), + String.valueOf(typeVersion), + String.valueOf(documentVersion)); + } + + private void checkConsts(final DatablockDocumentHeader compareTo) { + assertArrayEquals(magicNumber, compareTo.getMagicNumber()); + assertArrayEquals(documentType, compareTo.getDocumentType()); + assertEquals(typeVersion, compareTo.getTypeVersion()); + } + +} diff --git a/datablock/src/test/java/tv/hd3g/datablock/DatablockDocumentTest.java b/datablock/src/test/java/tv/hd3g/datablock/DatablockDocumentTest.java new file mode 100644 index 00000000..2c0c86f9 --- /dev/null +++ b/datablock/src/test/java/tv/hd3g/datablock/DatablockDocumentTest.java @@ -0,0 +1,175 @@ +/* + * This file is part of datablock. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * Copyright (C) hdsdi3g for hd3g.tv 2024 + * + */ +package tv.hd3g.datablock; + +import static java.nio.file.StandardOpenOption.CREATE; +import static java.nio.file.StandardOpenOption.READ; +import static java.nio.file.StandardOpenOption.WRITE; +import static org.apache.commons.io.FileUtils.readFileToByteArray; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static tv.hd3g.datablock.DatablockChunkHeader.CHUNK_HEADER_LEN; +import static tv.hd3g.datablock.DatablockChunkHeader.FOURCC_EXPECTED_SIZE; +import static tv.hd3g.datablock.DatablockDocument.CHUNK_SEPARATOR_SIZE; +import static tv.hd3g.datablock.DatablockDocumentHeader.DOCUMENT_HEADER_LEN; +import static tv.hd3g.datablock.IOTraits.ZERO_BYTE; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.util.Arrays; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import tv.hd3g.commons.testtools.Fake; +import tv.hd3g.commons.testtools.MockToolsExtendsJunit; + +@ExtendWith(MockToolsExtendsJunit.class) +class DatablockDocumentTest extends RealFileWork { + + @Fake(min = 8, max = 8) + byte[] magicNumber; + @Fake(min = 8, max = 8) + byte[] documentType; + @Fake + short typeVersion; + @Fake + int documentVersion; + + @Fake(min = FOURCC_EXPECTED_SIZE, max = FOURCC_EXPECTED_SIZE) + byte[] fourCC; + @Fake + short version; + @Fake + boolean archived; + + DatablockDocumentHeader ddh; + + DatablockDocument d; + + @BeforeEach + void init() throws Exception { + channel = FileChannel.open(file.toPath(), CREATE, READ, WRITE); + channel.truncate(0); + d = new DatablockDocument(channel); + ddh = new DatablockDocumentHeader(magicNumber, documentType, typeVersion, documentVersion); + } + + @Test + void testDatablockDocument_closed() throws IOException { + channel.close(); + assertThrows(IOException.class, () -> new DatablockDocument(channel)); + } + + @Test + void testGetDocumentHeader_emptyFile() { + assertThrows(IOException.class, () -> d.getDocumentHeader()); + } + + @Test + void testPutDocumentHeader() throws IOException { + assertEquals(0, file.length()); + assertEquals(0, channel.position()); + + d.putDocumentHeader(ddh); + + assertEquals(DOCUMENT_HEADER_LEN, file.length()); + assertEquals(DOCUMENT_HEADER_LEN, channel.position()); + } + + @Test + void testGetDocumentHeader() throws IOException { + d.putDocumentHeader(ddh); + d = new DatablockDocument(channel); + assertEquals(ddh, d.getDocumentHeader()); + assertEquals(DOCUMENT_HEADER_LEN, file.length()); + assertEquals(DOCUMENT_HEADER_LEN, channel.position()); + } + + @Test + void testAppendChunk_byteBuffer() throws IOException { + d.appendChunk(fourCC, version, archived, ByteBuffer.wrap(data)); + checkWritedChunk(); + } + + @Test + void testAppendChunk_outputStream() throws IOException { + d.appendChunk(fourCC, version, archived, writer -> writer.write(data)); + checkWritedChunk(); + } + + @Test + void testAppendEmptyChunk() throws IOException { + Arrays.fill(data, ZERO_BYTE); + d.appendEmptyChunk(fourCC, version, archived, data.length); + checkWritedChunk(); + } + + @Test + void testDocumentCrawl() { + // XXX + } + + @Test + void testGetDocumentMap() { + // XXX + + } + + @Test + void testDocumentRefactor() { + // XXX + + } + + // XXX createChunkPayloadExtractor don't need to test: tested internally (see coverage) + + private void checkWritedChunk() throws IOException { + assertEquals(CHUNK_HEADER_LEN + data.length + CHUNK_SEPARATOR_SIZE, file.length()); + assertEquals(file.length(), channel.position()); + + channel.position(0); + final var realData = readFileToByteArray(file); + + assertTrue(Arrays.equals( + data, 0, data.length, + realData, CHUNK_HEADER_LEN, CHUNK_HEADER_LEN + data.length)); + + final var chunkHeaderByteBuffer = ByteBuffer.wrap(realData, 0, CHUNK_HEADER_LEN); + final var h = new DatablockChunkHeader(chunkHeaderByteBuffer); + + assertThat(h.getFourCC()).containsExactly(fourCC); + assertEquals(version, h.getVersion()); + assertEquals(data.length, h.getPayloadSize()); + assertEquals(archived, h.isArchived()); + assertFalse(h.isDeleted()); + final var now = System.currentTimeMillis(); + assertThat(h.getCreatedDate()).isBetween(now - 1000, now); + + final var zeros = new byte[CHUNK_SEPARATOR_SIZE]; + assertTrue(Arrays.equals( + zeros, 0, zeros.length, + realData, CHUNK_HEADER_LEN + data.length, (int) file.length())); + + } + +} diff --git a/datablock/src/test/java/tv/hd3g/datablock/DatablockInputStreamChunkTest.java b/datablock/src/test/java/tv/hd3g/datablock/DatablockInputStreamChunkTest.java index 7529fbba..5726acdf 100644 --- a/datablock/src/test/java/tv/hd3g/datablock/DatablockInputStreamChunkTest.java +++ b/datablock/src/test/java/tv/hd3g/datablock/DatablockInputStreamChunkTest.java @@ -18,60 +18,29 @@ import static java.nio.file.StandardOpenOption.READ; import static java.util.Arrays.fill; -import static org.apache.commons.io.FileUtils.delete; -import static org.apache.commons.io.FileUtils.forceMkdir; import static org.apache.commons.io.FileUtils.writeByteArrayToFile; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.nio.channels.FileChannel; import java.util.Arrays; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import net.datafaker.Faker; +class DatablockInputStreamChunkTest extends RealFileWork { -class DatablockInputStreamChunkTest { - - static Faker faker = net.datafaker.Faker.instance(); - static byte[] data; - static File file; - - @BeforeAll - static void prepare() throws Exception { - final var dir = new File("target/test-temp"); - forceMkdir(dir); - - data = faker.random().nextRandomBytes(faker.random().nextInt(1000, 10000)); - file = File.createTempFile( - DatablockInputStreamChunkTest.class.getSimpleName(), - ".bin", - dir); - writeByteArrayToFile(file, data); - } - - @AfterAll - static void close() throws IOException { - if (file != null) { - delete(file); - } - } - - FileChannel channel; int payloadPosition; int payloadSize; DatablockInputStreamChunk c; @BeforeEach void init() throws Exception { + writeByteArrayToFile(file, data); + channel = FileChannel.open(file.toPath(), READ); payloadPosition = faker.random().nextInt(data.length / 12, data.length / 10); final var from = data.length / 20; @@ -83,11 +52,6 @@ void init() throws Exception { assertEquals(payloadSize, c.available()); } - @AfterEach - void end() throws Exception { - channel.close(); - } - @Test void testRead() throws IOException { for (var pos = 0; pos < payloadSize; pos++) { diff --git a/datablock/src/test/java/tv/hd3g/datablock/IOTraitsTest.java b/datablock/src/test/java/tv/hd3g/datablock/IOTraitsTest.java index bed57a33..8be1c6cc 100644 --- a/datablock/src/test/java/tv/hd3g/datablock/IOTraitsTest.java +++ b/datablock/src/test/java/tv/hd3g/datablock/IOTraitsTest.java @@ -77,9 +77,10 @@ void testCheckedWriteWritableByteChannelByteBuffer() throws IOException { void testCheckedWriteFileChannelLongByteBuffer() throws IOException { readFrom = ByteBuffer.allocate(operation); - when(fileChannel.write(readFrom, pos)).thenReturn(operation); + when(fileChannel.write(readFrom)).thenReturn(operation); t.checkedWrite(fileChannel, pos, readFrom); - verify(fileChannel, times(1)).write(readFrom, pos); + verify(fileChannel, times(1)).position(pos); + verify(fileChannel, times(1)).write(readFrom); } @Test @@ -95,9 +96,10 @@ void testCheckedReadReadableByteChannelByteBuffer() throws IOException { void testCheckedReadFileChannelLongByteBuffer() throws IOException { readFrom = ByteBuffer.allocate(operation); - when(fileChannel.read(readFrom, pos)).thenReturn(operation); + when(fileChannel.read(readFrom)).thenReturn(operation); t.checkedRead(fileChannel, pos, readFrom); - verify(fileChannel, times(1)).read(readFrom, pos); + verify(fileChannel, times(1)).position(pos); + verify(fileChannel, times(1)).read(readFrom); } @Test diff --git a/datablock/src/test/java/tv/hd3g/datablock/RealFileWork.java b/datablock/src/test/java/tv/hd3g/datablock/RealFileWork.java new file mode 100644 index 00000000..165c2fc0 --- /dev/null +++ b/datablock/src/test/java/tv/hd3g/datablock/RealFileWork.java @@ -0,0 +1,70 @@ +/* + * This file is part of datablock. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * Copyright (C) hdsdi3g for hd3g.tv 2024 + * + */ +package tv.hd3g.datablock; + +import static org.apache.commons.io.FileUtils.delete; +import static org.apache.commons.io.FileUtils.forceMkdir; + +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; + +import net.datafaker.Faker; + +public class RealFileWork { + + static Faker faker = net.datafaker.Faker.instance(); + static byte[] data; + static File file; + + @BeforeAll + static void prepare() throws Exception { + final var dir = new File("target/test-temp"); + forceMkdir(dir); + + data = faker.random().nextRandomBytes(faker.random().nextInt(1000, 10000)); + file = File.createTempFile( + DatablockInputStreamChunkTest.class.getSimpleName(), + ".bin", + dir); + } + + @AfterAll + static void close() throws IOException { + if (file != null) { + delete(file); + } + } + + FileChannel channel; + + @AfterEach + void end() throws Exception { + if (channel == null) { + return; + } + try { + channel.close(); + } catch (final IOException e) { + } + } + +}