You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sd...@apache.org on 2022/10/18 08:15:06 UTC

[ignite-3] 01/01: IGNITE-17923 Remove PartitionStorage and its tests

This is an automated email from the ASF dual-hosted git repository.

sdanilov pushed a commit to branch ignite-17923
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 376a57f67106f1fa570e2e0001f475be9c97156d
Author: Semyon Danilov <sa...@yandex.ru>
AuthorDate: Tue Oct 18 12:14:55 2022 +0400

    IGNITE-17923 Remove PartitionStorage and its tests
---
 .../ignite/internal/storage/PartitionStorage.java  | 162 -----
 .../internal/storage/engine/TableStorage.java      |  22 -
 .../storage/AbstractPartitionStorageTest.java      | 723 ---------------------
 3 files changed, 907 deletions(-)

diff --git a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/PartitionStorage.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/PartitionStorage.java
deleted file mode 100644
index 783092b369..0000000000
--- a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/PartitionStorage.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.ignite.internal.storage;
-
-import java.nio.file.Path;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.function.Predicate;
-import org.apache.ignite.internal.util.Cursor;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Interface providing methods to read, remove and update keys in storage. Any locking is unnecessary as this storage is used within RAFT
- * groups where all write operations are serialized.
- *
- * @deprecated Replaced with {@link MvPartitionStorage}.
- */
-@Deprecated
-public interface PartitionStorage extends AutoCloseable {
-    /**
-     * Returns the partition id.
-     *
-     * @return Partition id.
-     */
-    int partitionId();
-
-    /**
-     * Reads a DataRow for a given key.
-     *
-     * @param key Search row.
-     * @return Data row or {@code null} if no data has been found.
-     * @throws StorageException If failed to read the data or the storage is already stopped.
-     */
-    @Nullable
-    DataRow read(SearchRow key) throws StorageException;
-
-    /**
-     * Reads {@link DataRow}s for a given collection of keys.
-     *
-     * @param keys Search rows.
-     * @return Data rows.
-     * @throws StorageException If failed to read the data or the storage is already stopped.
-     */
-    Collection<DataRow> readAll(List<? extends SearchRow> keys) throws StorageException;
-
-    /**
-     * Writes a DataRow into the storage.
-     *
-     * @param row Data row.
-     * @throws StorageException If failed to write the data or the storage is already stopped.
-     */
-    void write(DataRow row) throws StorageException;
-
-    /**
-     * Writes a collection of {@link DataRow}s into the storage.
-     *
-     * @param rows Data rows.
-     * @throws StorageException If failed to write the data or the storage is already stopped.
-     */
-    void writeAll(List<? extends DataRow> rows) throws StorageException;
-
-    /**
-     * Inserts a collection of {@link DataRow}s into the storage and returns a collection of rows that can't be inserted due to their keys
-     * being already present in the storage.
-     *
-     * @param rows Data rows.
-     * @return Collection of rows that could not be inserted.
-     * @throws StorageException If failed to write the data or the storage is already stopped.
-     */
-    Collection<DataRow> insertAll(List<? extends DataRow> rows) throws StorageException;
-
-    /**
-     * Removes a DataRow associated with a given Key.
-     *
-     * @param key Search row.
-     * @throws StorageException If failed to remove the data or the storage is already stopped.
-     */
-    void remove(SearchRow key) throws StorageException;
-
-    /**
-     * Removes {@link DataRow}s mapped by given keys.
-     *
-     * @param keys Search rows.
-     * @return List of skipped data rows.
-     * @throws StorageException If failed to remove the data or the storage is already stopped.
-     */
-    Collection<SearchRow> removeAll(List<? extends SearchRow> keys) throws StorageException;
-
-    /**
-     * Removes {@link DataRow}s mapped by given keys and containing given values.
-     *
-     * @param keyValues Data rows.
-     * @return List of skipped data rows.
-     * @throws StorageException If failed to remove the data or the storage is already stopped.
-     */
-    Collection<DataRow> removeAllExact(List<? extends DataRow> keyValues) throws StorageException;
-
-    /**
-     * Executes an update with custom logic implemented by storage.UpdateClosure interface.
-     *
-     * @param key Search key.
-     * @param clo Invoke closure.
-     * @param <T> Closure invocation's result type.
-     * @throws StorageException If failed to read data or storage is already stopped.
-     */
-    @Nullable <T> T invoke(SearchRow key, InvokeClosure<T> clo) throws StorageException;
-
-    /**
-     * Creates cursor over the storage data.
-     *
-     * @param filter Filter for the scan query.
-     * @return Cursor with filtered data.
-     * @throws StorageException If failed to read data or storage is already stopped.
-     */
-    Cursor<DataRow> scan(Predicate<SearchRow> filter) throws StorageException;
-
-    /**
-     * Creates a snapshot of the storage's current state in the specified directory.
-     *
-     * @param snapshotPath Directory to store a snapshot.
-     * @return Future representing pending completion of the operation.
-     */
-    CompletableFuture<Void> snapshot(Path snapshotPath);
-
-    /**
-     * Restores a state of the storage which was previously captured with a {@link #snapshot(Path)}.
-     *
-     * @param snapshotPath Path to the snapshot's directory.
-     */
-    void restoreSnapshot(Path snapshotPath);
-
-    /**
-     * Removes all data from this storage and frees all associated resources.
-     *
-     * @throws StorageException If failed to destroy the data or storage is already stopped.
-     */
-    void destroy() throws StorageException;
-
-    /**
-     * Returns rows count belongs to current storage.
-     *
-     * @return Rows count.
-     * @throws StorageException If failed to obtain size.
-     */
-    long rowsCount();
-}
diff --git a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/TableStorage.java b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/TableStorage.java
index 84f041ead2..d31b3a23f8 100644
--- a/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/TableStorage.java
+++ b/modules/storage-api/src/main/java/org/apache/ignite/internal/storage/engine/TableStorage.java
@@ -18,9 +18,7 @@
 package org.apache.ignite.internal.storage.engine;
 
 import org.apache.ignite.internal.schema.configuration.TableConfiguration;
-import org.apache.ignite.internal.storage.PartitionStorage;
 import org.apache.ignite.internal.storage.StorageException;
-import org.jetbrains.annotations.Nullable;
 
 /**
  * Table storage that contains meta, partitions and SQL indexes.
@@ -29,26 +27,6 @@ import org.jetbrains.annotations.Nullable;
  */
 @Deprecated
 public interface TableStorage {
-    /**
-     * Retrieves or creates a partition for the current table. Not expected to be called concurrently with the same partition id.
-     *
-     * @param partId Partition id.
-     * @return Partition storage.
-     * @throws IllegalArgumentException If partition id is out of bounds.
-     * @throws StorageException         If an error has occurred during the partition creation.
-     */
-    PartitionStorage getOrCreatePartition(int partId) throws StorageException;
-
-    /**
-     * Returns the partition storage or {@code null} if the requested storage doesn't exist.
-     *
-     * @param partId Partition id.
-     * @return Partition storage or {@code null}.
-     * @throws IllegalArgumentException If partition id is out of bounds.
-     */
-    @Nullable
-    PartitionStorage getPartition(int partId);
-
     /**
      * Destroys a partition if it exists.
      *
diff --git a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractPartitionStorageTest.java b/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractPartitionStorageTest.java
deleted file mode 100644
index a97d3720e0..0000000000
--- a/modules/storage-api/src/testFixtures/java/org/apache/ignite/internal/storage/AbstractPartitionStorageTest.java
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.ignite.internal.storage;
-
-import static java.util.Collections.emptyList;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-import org.apache.ignite.internal.storage.basic.DeleteExactInvokeClosure;
-import org.apache.ignite.internal.storage.basic.GetAndRemoveInvokeClosure;
-import org.apache.ignite.internal.storage.basic.GetAndReplaceInvokeClosure;
-import org.apache.ignite.internal.storage.basic.InsertInvokeClosure;
-import org.apache.ignite.internal.storage.basic.ReplaceExactInvokeClosure;
-import org.apache.ignite.internal.storage.basic.SimpleDataRow;
-import org.apache.ignite.internal.storage.basic.SimpleReadInvokeClosure;
-import org.apache.ignite.internal.storage.basic.SimpleRemoveInvokeClosure;
-import org.apache.ignite.internal.storage.basic.SimpleWriteInvokeClosure;
-import org.apache.ignite.internal.testframework.WorkDirectory;
-import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
-import org.apache.ignite.internal.util.Cursor;
-import org.jetbrains.annotations.NotNull;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-
-/**
- * Abstract test that covers basic scenarios of the storage API.
- */
-@ExtendWith(WorkDirectoryExtension.class)
-public abstract class AbstractPartitionStorageTest {
-    /** Test key. */
-    protected static final String KEY = "key";
-
-    /** Test value. */
-    protected static final String VALUE = "value";
-
-    /** Storage instance. */
-    protected PartitionStorage storage;
-
-    /**
-     * Tests that read / write / remove work consistently on the same key.
-     */
-    @Test
-    public void readWriteRemove() {
-        SearchRow searchRow = searchRow(KEY);
-
-        assertNull(storage.read(searchRow));
-
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        storage.write(dataRow);
-
-        assertArrayEquals(dataRow.value().array(), storage.read(searchRow).value().array());
-
-        storage.remove(searchRow);
-
-        assertNull(storage.read(searchRow));
-    }
-
-    /**
-     * Tests that invoke method works consistently with default read / write / remove closures implementations on the same key.
-     */
-    @Test
-    public void invoke() {
-        SearchRow searchRow = searchRow(KEY);
-
-        SimpleReadInvokeClosure readClosure = new SimpleReadInvokeClosure();
-
-        storage.invoke(searchRow, readClosure);
-
-        assertNull(readClosure.row());
-
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        storage.invoke(searchRow, new SimpleWriteInvokeClosure(dataRow));
-
-        storage.invoke(searchRow, readClosure);
-
-        assertArrayEquals(dataRow.value().array(), readClosure.row().value().array());
-
-        storage.invoke(searchRow, new SimpleRemoveInvokeClosure());
-
-        storage.invoke(searchRow, readClosure);
-
-        assertNull(readClosure.row());
-    }
-
-    /**
-     * Tests that scan operation works properly without filter.
-     *
-     * @throws Exception If failed.
-     */
-    @Test
-    public void scanSimple() throws Exception {
-        List<DataRow> list = toList(storage.scan(key -> true));
-
-        assertEquals(emptyList(), list);
-
-        DataRow dataRow1 = dataRow("key1", "value1");
-
-        storage.write(dataRow1);
-
-        assertEquals(1, storage.rowsCount());
-
-        list = toList(storage.scan(key -> true));
-
-        assertThat(list, hasSize(1));
-
-        assertArrayEquals(dataRow1.value().array(), list.get(0).value().array());
-
-        DataRow dataRow2 = dataRow("key2", "value2");
-
-        storage.write(dataRow2);
-
-        list = toList(storage.scan(key -> true));
-
-        assertThat(list, hasSize(2));
-
-        // "key1" and "key2" have the same order both by hash and lexicographically.
-        assertArrayEquals(dataRow1.value().array(), list.get(0).value().array());
-        assertArrayEquals(dataRow2.value().array(), list.get(1).value().array());
-    }
-
-    /**
-     * Tests that scan operation works properly with passed filter.
-     *
-     * @throws Exception If failed.
-     */
-    @Test
-    public void scanFiltered() throws Exception {
-        DataRow dataRow1 = dataRow("key1", "value1");
-        DataRow dataRow2 = dataRow("key2", "value2");
-
-        storage.write(dataRow1);
-        storage.write(dataRow2);
-
-        List<DataRow> list = toList(storage.scan(key -> stringKey(key).charAt(3) == '1'));
-
-        assertThat(list, hasSize(1));
-
-        assertArrayEquals(dataRow1.value().array(), list.get(0).value().array());
-
-        list = toList(storage.scan(key -> stringKey(key).charAt(3) == '2'));
-
-        assertThat(list, hasSize(1));
-
-        assertArrayEquals(dataRow2.value().array(), list.get(0).value().array());
-
-        list = toList(storage.scan(key -> false));
-
-        assertTrue(list.isEmpty());
-    }
-
-    /**
-     * Tests that {@link InsertInvokeClosure} inserts a data row if there is no existing data row with the same key.
-     */
-    @Test
-    public void testInsertClosure() {
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        var closure = new InsertInvokeClosure(dataRow);
-
-        storage.invoke(dataRow, closure);
-
-        assertTrue(closure.result());
-
-        checkHasSameEntry(dataRow);
-    }
-
-    /**
-     * Tests that {@link InsertInvokeClosure} doesn't insert a data row if there is an existing data row with the same key.
-     */
-    @Test
-    public void testInsertClosure_failureBranch() {
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        var closure = new InsertInvokeClosure(dataRow);
-
-        storage.invoke(dataRow, closure);
-
-        assertTrue(closure.result());
-
-        DataRow sameKeyRow = dataRow(KEY, "test");
-
-        var sameClosure = new InsertInvokeClosure(sameKeyRow);
-
-        storage.invoke(sameKeyRow, sameClosure);
-
-        assertFalse(sameClosure.result());
-
-        checkHasSameEntry(dataRow);
-    }
-
-    /**
-     * Tests that {@link DeleteExactInvokeClosure} deletes a data row if a key and a value matches the ones passed in the closure.
-     */
-    @Test
-    public void testDeleteExactClosure() {
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        storage.write(dataRow);
-
-        checkHasSameEntry(dataRow);
-
-        var closure = new DeleteExactInvokeClosure(dataRow);
-
-        storage.invoke(dataRow, closure);
-
-        assertTrue(closure.result());
-
-        assertNull(storage.read(dataRow));
-    }
-
-    /**
-     * Tests that {@link DeleteExactInvokeClosure} doesn't delete a data row if a key and a value don't match the ones passed in the
-     * closure.
-     */
-    @Test
-    public void testDeleteExactClosure_failureBranch() {
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        storage.write(dataRow);
-
-        checkHasSameEntry(dataRow);
-
-        var closure = new DeleteExactInvokeClosure(dataRow(KEY, "test"));
-
-        storage.invoke(dataRow, closure);
-
-        assertFalse(closure.result());
-
-        checkHasSameEntry(dataRow);
-    }
-
-    /**
-     * Tests that {@link GetAndRemoveInvokeClosure} successfully retrieves and removes a data row.
-     */
-    @Test
-    public void testGetAndRemoveClosure() {
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        storage.write(dataRow);
-
-        checkHasSameEntry(dataRow);
-
-        var closure = new GetAndRemoveInvokeClosure();
-
-        storage.invoke(dataRow, closure);
-
-        assertTrue(closure.result());
-
-        checkRowsEqual(dataRow, closure.oldRow());
-
-        assertNull(storage.read(dataRow));
-    }
-
-    /**
-     * Tests that {@link GetAndRemoveInvokeClosure} doesn't retrieve and remove a data row if it doesn't exist.
-     */
-    @Test
-    public void testGetAndRemoveClosure_failureBranch() {
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        storage.write(dataRow);
-
-        checkHasSameEntry(dataRow);
-
-        var closure = new GetAndRemoveInvokeClosure();
-
-        storage.invoke(searchRow("test"), closure);
-
-        assertFalse(closure.result());
-
-        assertNull(closure.oldRow());
-
-        checkHasSameEntry(dataRow);
-    }
-
-    /**
-     * Tests that {@link GetAndReplaceInvokeClosure} with the {@code GetAndReplaceInvokeClosure#onlyIfExists} set to {@code false} retrieves
-     * and replaces the existing entry in the storage.
-     */
-    @Test
-    public void testGetAndReplaceClosureIfExistsFalse_entryExists() {
-        String newValue = "newValue";
-
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        storage.write(dataRow);
-
-        checkHasSameEntry(dataRow);
-
-        DataRow newRow = dataRow(KEY, newValue);
-
-        var closure = new GetAndReplaceInvokeClosure(newRow, false);
-
-        storage.invoke(dataRow, closure);
-
-        DataRow replaced = closure.oldRow();
-
-        assertNotNull(replaced);
-
-        assertTrue(closure.result());
-
-        checkRowsEqual(dataRow, replaced);
-
-        checkHasDifferentEntry(dataRow);
-        checkHasSameEntry(newRow);
-    }
-
-    /**
-     * Tests that {@link GetAndReplaceInvokeClosure} with the {@code GetAndReplaceInvokeClosure#onlyIfExists} set to {@code false}
-     * successfully inserts a new data row and returns an empty row if a previous row with the same key doesn't exist .
-     */
-    @Test
-    public void testGetAndReplaceClosureIfExistsFalse_entryNotExists() {
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        var closure = new GetAndReplaceInvokeClosure(dataRow, false);
-
-        storage.invoke(dataRow, closure);
-
-        DataRow replaced = closure.oldRow();
-
-        assertTrue(closure.result());
-
-        assertNull(replaced);
-
-        checkHasSameEntry(dataRow);
-    }
-
-    /**
-     * Tests that {@link GetAndReplaceInvokeClosure} with the {@code GetAndReplaceInvokeClosure#onlyIfExists} set to {@code true} retrieves
-     * and replaces the existing entry in the storage.
-     */
-    @Test
-    public void testGetAndReplaceClosureIfExistsTrue_entryExists() {
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        storage.write(dataRow);
-
-        checkHasSameEntry(dataRow);
-
-        DataRow newRow = dataRow(KEY, "test");
-
-        var closure = new GetAndReplaceInvokeClosure(newRow, true);
-
-        storage.invoke(dataRow, closure);
-
-        DataRow replaced = closure.oldRow();
-
-        assertNotNull(replaced);
-
-        assertTrue(closure.result());
-
-        checkHasDifferentEntry(dataRow);
-        checkHasSameEntry(newRow);
-    }
-
-    /**
-     * Tests that {@link GetAndReplaceInvokeClosure} with the {@code GetAndReplaceInvokeClosure#onlyIfExists} set to {@code true} doesn't
-     * insert a new entry if a previous one doesn't exist.
-     */
-    @Test
-    public void testGetAndReplaceClosureIfExistsTrue_entryNotExists() {
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        var closure = new GetAndReplaceInvokeClosure(dataRow, true);
-
-        storage.invoke(dataRow, closure);
-
-        DataRow replaced = closure.oldRow();
-
-        assertNull(replaced);
-
-        assertFalse(closure.result());
-
-        assertNull(storage.read(dataRow));
-    }
-
-    /**
-     * Tests that {@link ReplaceExactInvokeClosure} replaces the data row with a given key and a given value in the storage.
-     */
-    @Test
-    public void testReplaceExactClosure() {
-        String newValue = "newValue";
-
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        storage.write(dataRow);
-
-        checkHasSameEntry(dataRow);
-
-        DataRow newRow = dataRow(KEY, newValue);
-
-        var closure = new ReplaceExactInvokeClosure(dataRow, newRow);
-
-        storage.invoke(dataRow, closure);
-
-        assertTrue(closure.result());
-
-        checkHasDifferentEntry(dataRow);
-        checkHasSameEntry(newRow);
-    }
-
-    /**
-     * Tests that {@link ReplaceExactInvokeClosure} doesn't replace the data row with a given key and a given value if the value in the
-     * storage doesn't match the value passed via the closure.
-     */
-    @Test
-    public void testReplaceExactClosure_failureBranch() {
-        String newValue = "newValue";
-
-        DataRow dataRow = dataRow(KEY, VALUE);
-
-        storage.write(dataRow);
-
-        checkHasSameEntry(dataRow);
-
-        DataRow newRow = dataRow(KEY, newValue);
-
-        var closure = new ReplaceExactInvokeClosure(newRow, dataRow);
-
-        storage.invoke(dataRow, closure);
-
-        assertFalse(closure.result());
-
-        checkHasSameEntry(dataRow);
-    }
-
-    /**
-     * Tests the {@link PartitionStorage#readAll(List)} operation successfully reads data rows from the storage.
-     */
-    @Test
-    public void testReadAll() {
-        List<DataRow> rows = insertBulk(100);
-
-        Collection<DataRow> readRows = storage.readAll(rows);
-
-        assertThat(
-                readRows.stream().map(DataRow::value).collect(Collectors.toList()),
-                containsInAnyOrder(rows.stream().map(DataRow::value).toArray(ByteBuffer[]::new))
-        );
-    }
-
-    /**
-     * Tests that {@link PartitionStorage#writeAll(List)} operation successfully writes a collection of data rows into the storage.
-     */
-    @Test
-    public void testWriteAll() {
-        List<DataRow> rows = IntStream.range(0, 100)
-                .mapToObj(i -> dataRow(KEY + i, VALUE + i))
-                .collect(Collectors.toList());
-
-        storage.writeAll(rows);
-        rows.forEach(this::checkHasSameEntry);
-    }
-
-    /**
-     * Tests that {@link PartitionStorage#insertAll(List)} operation doesn't insert data rows which keys are already present in the storage.
-     * This operation must also return the list of such data rows.
-     */
-    @Test
-    public void testInsertAll() {
-        List<DataRow> rows = insertBulk(100);
-
-        List<DataRow> oldRows = rows.subList(0, 50);
-
-        List<DataRow> newInsertion = Stream.concat(
-                oldRows.stream(),
-                IntStream.range(100, 150).mapToObj(i -> dataRow(KEY + "_" + i, VALUE + "_" + i))
-        ).collect(Collectors.toList());
-
-        Collection<DataRow> cantInsert = storage.insertAll(newInsertion);
-
-        assertEquals(oldRows, cantInsert);
-    }
-
-    /**
-     * Tests that {@link PartitionStorage#removeAll(List)} operation successfully retrieves and removes a collection of {@link SearchRow}s.
-     */
-    @Test
-    public void testRemoveAll() throws Exception {
-        List<DataRow> rows = insertBulk(100);
-
-        Collection<SearchRow> skipped = storage.removeAll(rows);
-
-        assertEquals(0, skipped.size());
-
-        Cursor<DataRow> scan = storage.scan(row -> true);
-
-        assertFalse(scan.hasNext());
-
-        scan.close();
-    }
-
-    @Test
-    public void testRemoveAllKeyNotExists() {
-        SearchRow row = searchRow(KEY);
-        Collection<SearchRow> skipped = storage.removeAll(Collections.singletonList(row));
-
-        assertNotNull(skipped);
-
-        assertEquals(1, skipped.size());
-        assertEquals(row, skipped.iterator().next());
-    }
-
-    /**
-     * Tests that {@link PartitionStorage#removeAllExact(List)} operation successfully removes and retrieves a collection of data rows with
-     * the given exact keys and values from the storage.
-     */
-    @Test
-    public void testRemoveAllExact() throws Exception {
-        List<DataRow> rows = insertBulk(100);
-
-        Collection<DataRow> skipped = storage.removeAllExact(rows);
-
-        assertEquals(0, skipped.size());
-
-        Cursor<DataRow> scan = storage.scan(row -> true);
-
-        assertFalse(scan.hasNext());
-
-        scan.close();
-    }
-
-    /**
-     * Tests that {@link PartitionStorage#removeAllExact(List)} operation doesn't remove and retrieve a collection of data rows with the
-     * given exact keys and values from the storage if the value in the storage doesn't match the given value.
-     */
-    @Test
-    public void testRemoveAllExact_failureBranch() {
-        List<DataRow> rows = insertBulk(100);
-
-        List<DataRow> notExactRows = IntStream.range(0, 100)
-                .mapToObj(i -> dataRow(KEY + i, VALUE + (i + 1)))
-                .collect(Collectors.toList());
-
-        Collection<DataRow> skipped = storage.removeAllExact(notExactRows);
-
-        assertEquals(notExactRows, skipped);
-
-        rows.forEach(this::checkHasSameEntry);
-    }
-
-    /**
-     * Tests that {@link PartitionStorage#snapshot(Path)} and {@link PartitionStorage#restoreSnapshot(Path)} operations work properly
-     * in basic scenario of creating snapshot and restoring it on the clear db.
-     *
-     * @param workDir Directory to store snapshot file.
-     * @throws Exception If failed to take snapshot.
-     */
-    @Test
-    public void testSnapshot(@WorkDirectory Path workDir) throws Exception {
-        List<DataRow> rows = insertBulk(10);
-
-        Path snapshotDir = workDir.resolve("snapshot");
-
-        Files.createDirectories(snapshotDir);
-
-        storage.snapshot(snapshotDir).get(1, TimeUnit.SECONDS);
-
-        storage.removeAll(rows);
-
-        storage.restoreSnapshot(snapshotDir);
-
-        rows.forEach(this::checkHasSameEntry);
-    }
-
-    /**
-     * Inserts and returns a given amount of data rows with {@link #KEY}_i as a key and {@link #VALUE}_i as a value where i is an index of
-     * the data row.
-     *
-     * @param numberOfEntries Amount of entries to insert.
-     * @return List of inserted rows.
-     */
-    private List<DataRow> insertBulk(int numberOfEntries) {
-        List<DataRow> rows = IntStream.range(0, numberOfEntries)
-                .mapToObj(i -> dataRow(KEY + "_" + i, VALUE + "_" + i))
-                .collect(Collectors.toList());
-
-        storage.insertAll(rows);
-        rows.forEach(this::checkHasSameEntry);
-
-        // Clone key and value byte arrays so that returned rows have new references.
-        // This way we check that the ConcurrentHashMapStorage performs an actual array comparison.
-        return rows.stream().map(row -> {
-            byte[] valueBytes = row.valueBytes();
-
-            assert valueBytes != null;
-
-            return new SimpleDataRow(row.keyBytes().clone(), valueBytes.clone());
-        }).collect(Collectors.toList());
-    }
-
-    /**
-     * Checks that the storage contains a row with a given key but with a different value.
-     *
-     * @param row Data row.
-     */
-    private void checkHasDifferentEntry(DataRow row) {
-        DataRow read = storage.read(row);
-
-        assertNotNull(read);
-        assertFalse(Arrays.equals(row.valueBytes(), read.valueBytes()));
-    }
-
-    /**
-     * Checks that the storage contains a specific data row.
-     *
-     * @param row Expected data row.
-     */
-    protected void checkHasSameEntry(DataRow row) {
-        DataRow read = storage.read(row);
-
-        assertNotNull(read);
-        checkRowsEqual(row, read);
-    }
-
-    /**
-     * Checks that two rows are equal.
-     *
-     * @param expected Expected data row.
-     * @param actual   Actual data row.
-     */
-    private static void checkRowsEqual(DataRow expected, DataRow actual) {
-        assertArrayEquals(expected.keyBytes(), actual.keyBytes());
-        assertArrayEquals(expected.valueBytes(), actual.valueBytes());
-    }
-
-    /**
-     * Wraps string key into a search row.
-     *
-     * @param key String key.
-     * @return Search row.
-     */
-    protected SearchRow searchRow(String key) {
-        return new SearchRow() {
-            @Override
-            public byte[] keyBytes() {
-                return key.getBytes(StandardCharsets.UTF_8);
-            }
-
-            @Override
-            public ByteBuffer key() {
-                return ByteBuffer.wrap(keyBytes());
-            }
-        };
-    }
-
-    /**
-     * Get key as a string.
-     *
-     * @param searchRow Search row.
-     * @return String key.
-     */
-    protected String stringKey(SearchRow searchRow) {
-        return new String(searchRow.keyBytes(), StandardCharsets.UTF_8);
-    }
-
-    /**
-     * Wraps string key/value pair into a data row.
-     *
-     * @param key   String key.
-     * @param value String value.
-     * @return Data row.
-     */
-    protected DataRow dataRow(String key, String value) {
-        return new SimpleDataRow(
-                key.getBytes(StandardCharsets.UTF_8),
-                value.getBytes(StandardCharsets.UTF_8)
-        );
-    }
-
-    /**
-     * Converts cursor to list.
-     *
-     * @param cursor Cursor.
-     * @param <T>    Type of cursor content.
-     * @return List.
-     * @throws Exception If error occurred during iteration or while closing the cursor.
-     */
-    @NotNull
-    private static <T> List<T> toList(Cursor<T> cursor) throws Exception {
-        try (cursor) {
-            return StreamSupport.stream(cursor.spliterator(), false).collect(Collectors.toList());
-        }
-    }
-}