IGNITE-12631 Incorrect rewriting wal record type in marshalled mode during iteration - Fixes #7371.

Signed-off-by: Ivan Rakov <irakov@apache.org>
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV1Serializer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV1Serializer.java
index 79e15a9..2d1386a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV1Serializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV1Serializer.java
@@ -386,10 +386,13 @@
                 size = in0.io().size();
             }
             catch (IOException ignore) {
-                // No-op. It just for information. Fail calculate file size.
+                // It just for information. Fail calculate file size.
+                e.addSuppressed(ignore);
             }
 
-            throw new IgniteCheckedException("Failed to read WAL record at position: " + startPos + " size: " + size, e);
+            throw new IgniteCheckedException(
+                "Failed to read WAL record at position: " + startPos + ", size: " + size + ", expectedPtr: " + expPtr, e
+            );
         }
     }
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV2Serializer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV2Serializer.java
index 26913f4..a1f7bfd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV2Serializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV2Serializer.java
@@ -141,7 +141,7 @@
                 else
                     buf.clear();
 
-                buf.put((byte)(recType.ordinal() + 1));
+                buf.put((byte)(recType.index() + 1));
 
                 buf.putLong(ptr.index());
                 buf.putInt(ptr.fileOffset());
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/pagemem/wal/record/WALRecordSerializationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/pagemem/wal/record/WALRecordSerializationTest.java
new file mode 100644
index 0000000..edd348d
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/pagemem/wal/record/WALRecordSerializationTest.java
@@ -0,0 +1,233 @@
+/*
+ * 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.pagemem.wal.record;
+
+import java.io.File;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
+import org.apache.ignite.internal.pagemem.wal.WALIterator;
+import org.apache.ignite.internal.pagemem.wal.WALPointer;
+import org.apache.ignite.internal.processors.cache.persistence.wal.FileDescriptor;
+import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.wal.record.RecordUtils;
+import org.apache.ignite.testframework.wal.record.UnsupportedWalRecord;
+import org.junit.Test;
+import org.mockito.internal.matchers.apachecommons.ReflectionEquals;
+
+import static org.apache.ignite.configuration.DataStorageConfiguration.DFLT_PAGE_SIZE;
+import static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.ZIP_SUFFIX;
+
+/**
+ * Tests of serialization and deserialization of all WAL record types {@link org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType}.
+ *
+ * It checks that all records can be successfully deserialized from early serialized record included serialization via
+ * compaction.
+ */
+public class WALRecordSerializationTest extends GridCommonAbstractTest {
+    /** Wal segment size. */
+    private static final int WAL_SEGMENT_SIZE = 4 * 1024 * 1024;
+
+    /** **/
+    private boolean compactionEnabled;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String name) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(name);
+
+        cfg.setDataStorageConfiguration(new DataStorageConfiguration()
+            .setDefaultDataRegionConfiguration(new DataRegionConfiguration()
+                .setPersistenceEnabled(true)
+                .setMaxSize(200 * 1024 * 1024))
+            .setWalSegmentSize(WAL_SEGMENT_SIZE)
+            .setWalCompactionEnabled(compactionEnabled));
+
+        cfg.setConsistentId(name);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} **/
+    @Override protected void beforeTest() throws Exception {
+        stopAllGrids();
+
+        cleanPersistenceDir();
+    }
+
+    /** {@inheritDoc} **/
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+
+        cleanPersistenceDir();
+    }
+
+    /**
+     * @throws Exception If fail.
+     */
+    @Test
+    public void testAllWalRecordsSerializedAndDeserializedSuccessfully() throws Exception {
+        compactionEnabled = false;
+
+        IgniteEx ignite = startGrid(0);
+
+        ignite.cluster().active(true);
+
+        WALRecord.RecordType[] recordTypes = WALRecord.RecordType.values();
+
+        List<ReflectionEquals> serializedRecords = new ArrayList<>();
+
+        IgniteWriteAheadLogManager wal = ignite.context().cache().context().wal();
+
+        ignite.context().cache().context().database().checkpointReadLock();
+        try {
+            for (WALRecord.RecordType recordType : recordTypes) {
+                WALRecord record = RecordUtils.buildWalRecord(recordType);
+
+                if (!(record instanceof UnsupportedWalRecord) && !(record instanceof SwitchSegmentRecord)) {
+                    serializedRecords.add(new ReflectionEquals(record, "prev", "pos",
+                        "updateCounter" //updateCounter for PartitionMetaStateRecord isn't serialized.
+                    ));
+
+                    wal.log(record);
+                }
+            }
+
+            wal.flush(null, true);
+
+        }
+        finally {
+            ignite.context().cache().context().database().checkpointReadUnlock();
+        }
+
+        stopGrid(0);
+
+        Iterator<ReflectionEquals> serializedIter = serializedRecords.iterator();
+        ReflectionEquals curExpRecord = serializedIter.hasNext() ? serializedIter.next() : null;
+
+        try (WALIterator iter = wal.replay(null)) {
+            while (iter.hasNext()) {
+                WALRecord record = iter.nextX().get2();
+
+                if (curExpRecord != null && curExpRecord.matches(record))
+                    curExpRecord = serializedIter.hasNext() ? serializedIter.next() : null;
+            }
+        }
+
+        assertNull("Expected record '" + curExpRecord + "' not found.", curExpRecord);
+    }
+
+    /**
+     * @throws Exception If fail.
+     */
+    @Test
+    public void testAllWalRecordsSerializedCompressedAndThenDeserializedSuccessfully() throws Exception {
+        compactionEnabled = true;
+
+        IgniteEx ignite = startGrid(0);
+
+        ignite.cluster().active(true);
+
+        WALRecord.RecordType[] recordTypes = WALRecord.RecordType.values();
+
+        List<ReflectionEquals> serializedRecords = new ArrayList<>();
+
+        IgniteWriteAheadLogManager wal = ignite.context().cache().context().wal();
+
+        WALPointer lastPointer = null;
+
+        ignite.context().cache().context().database().checkpointReadLock();
+        try {
+            for (WALRecord.RecordType recordType : recordTypes) {
+                WALRecord record = RecordUtils.buildWalRecord(recordType);
+
+                if (!(record instanceof UnsupportedWalRecord)
+                    && !(record instanceof SwitchSegmentRecord)
+                    && (recordType.purpose() == WALRecord.RecordPurpose.LOGICAL ||
+                    recordType == WALRecord.RecordType.CHECKPOINT_RECORD)) {
+
+                    serializedRecords.add(new ReflectionEquals(record, "prev", "pos",
+                        "updateCounter" //updateCounter for PartitionMetaStateRecord isn't serialized.
+                    ));
+
+                    lastPointer = wal.log(record);
+                }
+            }
+
+            wal.flush(null, true);
+
+        }
+        finally {
+            ignite.context().cache().context().database().checkpointReadUnlock();
+        }
+
+        String nodeFolderName = ignite.context().pdsFolderResolver().resolveFolders().folderName();
+        File nodeArchiveDir = Paths.get(
+            U.resolveWorkDirectory(U.defaultWorkDirectory(), "db", false).getAbsolutePath(),
+            "wal",
+            "archive",
+            nodeFolderName
+        ).toFile();
+        File walSegment = new File(nodeArchiveDir, FileDescriptor.fileName(((FileWALPointer)lastPointer).index()));
+        File walZipSegment = new File(nodeArchiveDir, FileDescriptor.fileName(((FileWALPointer)lastPointer).index()) + ZIP_SUFFIX);
+
+        // Spam WAL to move all data records to compressible WAL zone.
+        for (int i = 0; i < WAL_SEGMENT_SIZE / DFLT_PAGE_SIZE * 2; i++)
+            wal.log(new PageSnapshot(new FullPageId(-1, -1), new byte[DFLT_PAGE_SIZE], 1));
+
+        ignite.getOrCreateCache("generateDirtyPages");
+
+        // WAL archive segment is allowed to be compressed when it's at least one checkpoint away from current WAL head.
+        ignite.context().cache().context().database().wakeupForCheckpoint("Forced checkpoint").get();
+        ignite.context().cache().context().database().wakeupForCheckpoint("Forced checkpoint").get();
+
+        for (int i = 0; i < WAL_SEGMENT_SIZE / DFLT_PAGE_SIZE * 2; i++)
+            wal.log(new PageSnapshot(new FullPageId(-1, -1), new byte[DFLT_PAGE_SIZE], 1));
+
+        // Awaiting of zipping of the desirable segment.
+        assertTrue(GridTestUtils.waitForCondition(walZipSegment::exists, 15_000));
+
+        // Awaiting of removing of the desirable segment.
+        assertTrue(GridTestUtils.waitForCondition(() -> !walSegment.exists(), 15_000));
+
+        stopGrid(0);
+
+        Iterator<ReflectionEquals> serializedIter = serializedRecords.iterator();
+        ReflectionEquals curExpRecord = serializedIter.hasNext() ? serializedIter.next() : null;
+
+        try (WALIterator iter = wal.replay(null)) {
+            while (iter.hasNext()) {
+                WALRecord record = iter.nextX().get2();
+
+                if (curExpRecord != null && curExpRecord.matches(record))
+                    curExpRecord = serializedIter.hasNext() ? serializedIter.next() : null;
+            }
+        }
+
+        assertNull("Expected record '" + curExpRecord + "' not found.", curExpRecord);
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/pagemem/wal/record/WALRecordTest.java b/modules/core/src/test/java/org/apache/ignite/internal/pagemem/wal/record/WALRecordTest.java
index 8b66d51..ca8bb55 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/pagemem/wal/record/WALRecordTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/pagemem/wal/record/WALRecordTest.java
@@ -19,14 +19,15 @@
 
 import java.util.Arrays;
 import org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType;
+import org.apache.ignite.testframework.wal.record.RecordUtils;
 import org.junit.Test;
 
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
 /** */
 public class WALRecordTest {
-
     /** */
     @Test
     public void testRecordTypeIndex() {
@@ -43,4 +44,17 @@
 
         assertTrue(maxIdx < 256);
     }
+
+    /** */
+    @Test
+    public void testAllTestWalRecordBuilderConfigured() {
+        RecordType[] recordTypes = RecordType.values();
+
+        for (RecordType recordType : recordTypes)
+            assertNotNull(
+                "Test's builder of WAL record with type '" + recordType + "' not found. " +
+                    "Please, add such builder to RecordUtils for test purposes.",
+                RecordUtils.buildWalRecord(recordType)
+            );
+    }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/wal/record/RecordUtils.java b/modules/core/src/test/java/org/apache/ignite/testframework/wal/record/RecordUtils.java
new file mode 100644
index 0000000..2855de7
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/wal/record/RecordUtils.java
@@ -0,0 +1,566 @@
+/*
+ * 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.testframework.wal.record;
+
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Supplier;
+import org.apache.ignite.internal.pagemem.FullPageId;
+import org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord;
+import org.apache.ignite.internal.pagemem.wal.record.DataRecord;
+import org.apache.ignite.internal.pagemem.wal.record.ExchangeRecord;
+import org.apache.ignite.internal.pagemem.wal.record.MasterKeyChangeRecord;
+import org.apache.ignite.internal.pagemem.wal.record.MemoryRecoveryRecord;
+import org.apache.ignite.internal.pagemem.wal.record.MetastoreDataRecord;
+import org.apache.ignite.internal.pagemem.wal.record.MvccDataRecord;
+import org.apache.ignite.internal.pagemem.wal.record.MvccTxRecord;
+import org.apache.ignite.internal.pagemem.wal.record.PageSnapshot;
+import org.apache.ignite.internal.pagemem.wal.record.RollbackRecord;
+import org.apache.ignite.internal.pagemem.wal.record.SnapshotRecord;
+import org.apache.ignite.internal.pagemem.wal.record.SwitchSegmentRecord;
+import org.apache.ignite.internal.pagemem.wal.record.TxRecord;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageInsertFragmentRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageInsertRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageMvccMarkUpdatedRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageMvccUpdateNewTxStateHintRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageMvccUpdateTxStateHintRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageRemoveRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageSetFreeListPageRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageUpdateRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.FixCountRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.FixLeftmostChildRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.FixRemoveId;
+import org.apache.ignite.internal.pagemem.wal.record.delta.InitNewPageRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.InsertRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageAddRootRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageCutRootRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageInitRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageInitRootInlineRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageInitRootRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageUpdateLastAllocatedIndex;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageUpdateLastSuccessfulFullSnapshotId;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageUpdateLastSuccessfulSnapshotId;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageUpdateNextSnapshotId;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageUpdatePartitionDataRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageUpdatePartitionDataRecordV2;
+import org.apache.ignite.internal.pagemem.wal.record.delta.NewRootInitRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PageListMetaResetCountRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PagesListAddPageRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PagesListInitNewPageRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PagesListRemovePageRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetPreviousRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PartitionDestroyRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.PartitionMetaStateRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.RecycleRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.RemoveRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.ReplaceRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.RotatedIdPartRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.SplitExistingPageRecord;
+import org.apache.ignite.internal.pagemem.wal.record.delta.TrackingPageDeltaRecord;
+import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState;
+import org.apache.ignite.internal.processors.cache.mvcc.MvccVersionImpl;
+import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer;
+import org.apache.ignite.internal.processors.cache.tree.DataInnerIO;
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.transactions.TransactionState;
+
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_EXISTING_PAGE_SPLIT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_FIX_COUNT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_FIX_LEFTMOST_CHILD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_FIX_REMOVE_ID;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_FORWARD_PAGE_SPLIT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_INIT_NEW_ROOT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_META_PAGE_ADD_ROOT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_META_PAGE_CUT_ROOT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_META_PAGE_INIT_ROOT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_META_PAGE_INIT_ROOT2;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_META_PAGE_INIT_ROOT_V3;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_PAGE_INNER_REPLACE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_PAGE_INSERT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_PAGE_MERGE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_PAGE_RECYCLE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_PAGE_REMOVE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.BTREE_PAGE_REPLACE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.CHECKPOINT_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.CONSISTENT_CUT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.DATA_PAGE_INSERT_FRAGMENT_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.DATA_PAGE_INSERT_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.DATA_PAGE_REMOVE_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.DATA_PAGE_SET_FREE_LIST_PAGE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.DATA_PAGE_UPDATE_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.DATA_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.ENCRYPTED_DATA_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.ENCRYPTED_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.EXCHANGE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.HEADER_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.INIT_NEW_PAGE_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.MASTER_KEY_CHANGE_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.MEMORY_RECOVERY;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.METASTORE_DATA_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.META_PAGE_INIT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.META_PAGE_UPDATE_LAST_ALLOCATED_INDEX;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.META_PAGE_UPDATE_LAST_SUCCESSFUL_FULL_SNAPSHOT_ID;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.META_PAGE_UPDATE_LAST_SUCCESSFUL_SNAPSHOT_ID;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.META_PAGE_UPDATE_NEXT_SNAPSHOT_ID;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.MVCC_DATA_PAGE_MARK_UPDATED_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.MVCC_DATA_PAGE_NEW_TX_STATE_HINT_UPDATED_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.MVCC_DATA_PAGE_TX_STATE_HINT_UPDATED_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.MVCC_DATA_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.MVCC_TX_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PAGES_LIST_ADD_PAGE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PAGES_LIST_INIT_NEW_PAGE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PAGES_LIST_REMOVE_PAGE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PAGES_LIST_SET_NEXT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PAGES_LIST_SET_PREVIOUS;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PAGE_LIST_META_RESET_COUNT_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PAGE_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PARTITION_DESTROY;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PARTITION_META_PAGE_UPDATE_COUNTERS;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PARTITION_META_PAGE_UPDATE_COUNTERS_V2;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.PART_META_UPDATE_STATE;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.RESERVED;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.ROLLBACK_TX_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.ROTATED_ID_PART_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.SNAPSHOT;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.SWITCH_SEGMENT_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.TRACKING_PAGE_DELTA;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.TX_RECORD;
+import static org.apache.ignite.internal.processors.cache.tree.DataInnerIO.VERSIONS;
+
+/**
+ * Class contains builder methods for at least one record of each type{@link org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType}.
+ * NOTE!!: It is better to rewrite these builder methods to the builder of each record for flexible use where it is
+ * required.
+ */
+public class RecordUtils {
+    /** **/
+    private static final Map<WALRecord.RecordType, Supplier<WALRecord>> TEST_WAL_RECORD_SUPPLIER =
+        new EnumMap<WALRecord.RecordType, Supplier<WALRecord>>(WALRecord.RecordType.class) {{
+            put(TX_RECORD, RecordUtils::buildTxRecord);
+            put(PAGE_RECORD, RecordUtils::buildPageSnapshot);
+            put(DATA_RECORD, RecordUtils::buildDataRecord);
+            put(CHECKPOINT_RECORD, RecordUtils::buildCheckpointRecord);
+            put(HEADER_RECORD, RecordUtils::buildHeaderRecord);
+            put(INIT_NEW_PAGE_RECORD, RecordUtils::buildInitNewPageRecord);
+            put(DATA_PAGE_INSERT_RECORD, RecordUtils::buildDataPageInsertRecord);
+            put(DATA_PAGE_INSERT_FRAGMENT_RECORD, RecordUtils::buildDataPageInsertFragmentRecord);
+            put(DATA_PAGE_REMOVE_RECORD, RecordUtils::buildDataPageRemoveRecord);
+            put(DATA_PAGE_SET_FREE_LIST_PAGE, RecordUtils::buildDataPageSetFreeListPageRecord);
+            put(BTREE_META_PAGE_INIT_ROOT, RecordUtils::buildMetaPageInitRootRecord);
+            put(BTREE_META_PAGE_ADD_ROOT, RecordUtils::buildMetaPageAddRootRecord);
+            put(BTREE_META_PAGE_CUT_ROOT, RecordUtils::buildMetaPageCutRootRecord);
+            put(BTREE_INIT_NEW_ROOT, RecordUtils::buildNewRootInitRecord);
+            put(BTREE_PAGE_RECYCLE, RecordUtils::buildRecycleRecord);
+            put(BTREE_PAGE_INSERT, RecordUtils::buildInsertRecord);
+            put(BTREE_FIX_LEFTMOST_CHILD, RecordUtils::buildFixLeftmostChildRecord);
+            put(BTREE_FIX_COUNT, RecordUtils::buildFixCountRecord);
+            put(BTREE_PAGE_REPLACE, RecordUtils::buildReplaceRecord);
+            put(BTREE_PAGE_REMOVE, RecordUtils::buildRemoveRecord);
+            put(BTREE_PAGE_INNER_REPLACE, RecordUtils::buildBtreeInnerReplace);
+            put(BTREE_FIX_REMOVE_ID, RecordUtils::buildFixRemoveId);
+            put(BTREE_FORWARD_PAGE_SPLIT, RecordUtils::buildBtreeForwardPageSplit);
+            put(BTREE_EXISTING_PAGE_SPLIT, RecordUtils::buildSplitExistingPageRecord);
+            put(BTREE_PAGE_MERGE, RecordUtils::buildBtreeMergeRecord);
+            put(PAGES_LIST_SET_NEXT, RecordUtils::buildPagesListSetNextRecord);
+            put(PAGES_LIST_SET_PREVIOUS, RecordUtils::buildPagesListSetPreviousRecord);
+            put(PAGES_LIST_INIT_NEW_PAGE, RecordUtils::buildPagesListInitNewPageRecord);
+            put(PAGES_LIST_ADD_PAGE, RecordUtils::buildPagesListAddPageRecord);
+            put(PAGES_LIST_REMOVE_PAGE, RecordUtils::buildPagesListRemovePageRecord);
+            put(META_PAGE_INIT, RecordUtils::buildMetaPageInitRecord);
+            put(PARTITION_META_PAGE_UPDATE_COUNTERS, RecordUtils::buildMetaPageUpdatePartitionDataRecord);
+            put(MEMORY_RECOVERY, RecordUtils::buildMemoryRecoveryRecord);
+            put(TRACKING_PAGE_DELTA, RecordUtils::buildTrackingPageDeltaRecord);
+            put(META_PAGE_UPDATE_LAST_SUCCESSFUL_SNAPSHOT_ID, RecordUtils::buildMetaPageUpdateLastSuccessfulSnapshotId);
+            put(META_PAGE_UPDATE_LAST_SUCCESSFUL_FULL_SNAPSHOT_ID, RecordUtils::buildMetaPageUpdateLastSuccessfulFullSnapshotId);
+            put(META_PAGE_UPDATE_NEXT_SNAPSHOT_ID, RecordUtils::buildMetaPageUpdateNextSnapshotId);
+            put(META_PAGE_UPDATE_LAST_ALLOCATED_INDEX, RecordUtils::buildMetaPageUpdateLastAllocatedIndex);
+            put(PART_META_UPDATE_STATE, RecordUtils::buildPartitionMetaStateRecord);
+            put(PAGE_LIST_META_RESET_COUNT_RECORD, RecordUtils::buildPageListMetaResetCountRecord);
+            put(SWITCH_SEGMENT_RECORD, RecordUtils::buildSwitchSegmentRecord);
+            put(DATA_PAGE_UPDATE_RECORD, RecordUtils::buildDataPageUpdateRecord);
+            put(BTREE_META_PAGE_INIT_ROOT2, RecordUtils::buildMetaPageInitRootInlineRecord);
+            put(PARTITION_DESTROY, RecordUtils::buildPartitionDestroyRecord);
+            put(SNAPSHOT, RecordUtils::buildSnapshotRecord);
+            put(METASTORE_DATA_RECORD, RecordUtils::buildMetastoreDataRecord);
+            put(EXCHANGE, RecordUtils::buildExchangeRecord);
+            put(RESERVED, RecordUtils::buildReservedRecord);
+            put(ROLLBACK_TX_RECORD, RecordUtils::buildRollbackRecord);
+            put(PARTITION_META_PAGE_UPDATE_COUNTERS_V2, RecordUtils::buildMetaPageUpdatePartitionDataRecordV2);
+            put(MASTER_KEY_CHANGE_RECORD, RecordUtils::buildMasterKeyChangeRecord);
+            put(ROTATED_ID_PART_RECORD, RecordUtils::buildRotatedIdPartRecord);
+            put(MVCC_DATA_PAGE_MARK_UPDATED_RECORD, RecordUtils::buildDataPageMvccMarkUpdatedRecord);
+            put(MVCC_DATA_PAGE_TX_STATE_HINT_UPDATED_RECORD, RecordUtils::buildDataPageMvccUpdateTxStateHintRecord);
+            put(MVCC_DATA_PAGE_NEW_TX_STATE_HINT_UPDATED_RECORD, RecordUtils::buildDataPageMvccUpdateNewTxStateHintRecord);
+            put(ENCRYPTED_RECORD, RecordUtils::buildEncryptedRecord);
+            put(ENCRYPTED_DATA_RECORD, RecordUtils::buildEncryptedDataRecord);
+            put(MVCC_DATA_RECORD, RecordUtils::buildMvccDataRecord);
+            put(MVCC_TX_RECORD, RecordUtils::buildMvccTxRecord);
+            put(CONSISTENT_CUT, RecordUtils::buildConsistentCutRecord);
+            put(BTREE_META_PAGE_INIT_ROOT_V3, RecordUtils::buildBtreeMetaPageInitRootV3);
+        }};
+
+    /** **/
+    public static WALRecord buildWalRecord(WALRecord.RecordType recordType) {
+        Supplier<WALRecord> supplier = TEST_WAL_RECORD_SUPPLIER.get(recordType);
+
+        return supplier == null ? null : supplier.get();
+    }
+
+    /** **/
+    public static TxRecord buildTxRecord() {
+        return new TxRecord(
+            TransactionState.PREPARED,
+            new GridCacheVersion(),
+            new GridCacheVersion(),
+            Collections.singletonMap((short)1, Collections.singletonList((short)1))
+        );
+    }
+
+    /** **/
+    public static PageSnapshot buildPageSnapshot() {
+        //Deserialization doesn't check size from header but it is always expected page size as length of pageData.
+        byte[] random = new byte[4096];
+        //Real page size should be equal to page size.
+        return new PageSnapshot(new FullPageId(1L, 1), random, 4096);
+    }
+
+    /** **/
+    public static DataRecord buildDataRecord() {
+        return new DataRecord(Collections.emptyList());
+    }
+
+    /** **/
+    public static CheckpointRecord buildCheckpointRecord() {
+        CheckpointRecord record = new CheckpointRecord(new FileWALPointer(1, 1, 1));
+        record.cacheGroupStates(new HashMap<>());
+        return record;
+    }
+
+    /** **/
+    public static UnsupportedWalRecord buildHeaderRecord() {
+        return new UnsupportedWalRecord(HEADER_RECORD);
+    }
+
+    /** **/
+    public static InitNewPageRecord buildInitNewPageRecord() {
+        return new InitNewPageRecord(1, 1L, 1, 1, 1L);
+    }
+
+    /** **/
+    public static DataPageInsertRecord buildDataPageInsertRecord() {
+        byte[] random = {1, 3, 5};
+        return new DataPageInsertRecord(1, 1L, random);
+    }
+
+    /** **/
+    public static DataPageInsertFragmentRecord buildDataPageInsertFragmentRecord() {
+        byte[] random = {1, 3, 5};
+        return new DataPageInsertFragmentRecord(1, 1L, random, 1L);
+    }
+
+    /** **/
+    public static DataPageRemoveRecord buildDataPageRemoveRecord() {
+        return new DataPageRemoveRecord(1, 1, 1);
+    }
+
+    /** **/
+    public static DataPageSetFreeListPageRecord buildDataPageSetFreeListPageRecord() {
+        return new DataPageSetFreeListPageRecord(1, 1, 1);
+    }
+
+    /** **/
+    public static MetaPageInitRootRecord buildMetaPageInitRootRecord() {
+        return new MetaPageInitRootRecord(1, 1, 2);
+    }
+
+    /** **/
+    public static MetaPageAddRootRecord buildMetaPageAddRootRecord() {
+        return new MetaPageAddRootRecord(1, 1, 1);
+    }
+
+    /** **/
+    public static MetaPageCutRootRecord buildMetaPageCutRootRecord() {
+        return new MetaPageCutRootRecord(1, 1L);
+    }
+
+    /** **/
+    public static NewRootInitRecord buildNewRootInitRecord() {
+        DataInnerIO latest = VERSIONS.latest();
+        //Deserialization doesn't check size from header but it is always expected io.getItemSize as length of rowBytes.
+        byte[] rowBytes = new byte[latest.getItemSize()];
+
+        return new NewRootInitRecord(1, 1L, 1, latest, 1, rowBytes, 1L);
+    }
+
+    /** **/
+    public static RecycleRecord buildRecycleRecord() {
+        return new RecycleRecord(1, 1, 1);
+    }
+
+    /** **/
+    public static InsertRecord buildInsertRecord() {
+        DataInnerIO latest = VERSIONS.latest();
+        //Deserialization doesn't check size from header but it is always expected io.getItemSize as length of rowBytes.
+        byte[] rowBytes = new byte[latest.getItemSize()];
+
+        return new InsertRecord(1, 1, latest, 1, rowBytes, 1);
+    }
+
+    /** **/
+    public static FixLeftmostChildRecord buildFixLeftmostChildRecord() {
+        return new FixLeftmostChildRecord(1, 1, 1);
+    }
+
+    /** **/
+    public static FixCountRecord buildFixCountRecord() {
+        return new FixCountRecord(1, 1, 1);
+    }
+
+    /** **/
+    public static ReplaceRecord buildReplaceRecord() {
+        DataInnerIO latest = VERSIONS.latest();
+        //Deserialization doesn't check size from header but it is always expected io.getItemSize as length of rowBytes.
+        byte[] rowBytes = new byte[latest.getItemSize()];
+
+        return new ReplaceRecord(1, 1, latest, rowBytes, 1);
+    }
+
+    /** **/
+    public static RemoveRecord buildRemoveRecord() {
+        return new RemoveRecord(1, 1, 1, 1);
+    }
+
+    /** **/
+    public static UnsupportedWalRecord buildBtreeInnerReplace() {
+        return new UnsupportedWalRecord(BTREE_PAGE_INNER_REPLACE);
+    }
+
+    /** **/
+    public static FixRemoveId buildFixRemoveId() {
+        return new FixRemoveId(1, 1, 1);
+    }
+
+    /** **/
+    public static UnsupportedWalRecord buildBtreeForwardPageSplit() {
+        return new UnsupportedWalRecord(BTREE_FORWARD_PAGE_SPLIT);
+    }
+
+    /** **/
+    public static SplitExistingPageRecord buildSplitExistingPageRecord() {
+        return new SplitExistingPageRecord(1, 1, 1, 1);
+    }
+
+    /** **/
+    public static UnsupportedWalRecord buildBtreeMergeRecord() {
+        return new UnsupportedWalRecord(BTREE_PAGE_MERGE);
+    }
+
+    /** **/
+    public static PagesListSetNextRecord buildPagesListSetNextRecord() {
+        return new PagesListSetNextRecord(1, 1, 1);
+    }
+
+    /** **/
+    public static PagesListSetPreviousRecord buildPagesListSetPreviousRecord() {
+        return new PagesListSetPreviousRecord(1, 1, 1);
+    }
+
+    /** **/
+    public static PagesListInitNewPageRecord buildPagesListInitNewPageRecord() {
+        return new PagesListInitNewPageRecord(1, 1, 1, 1, 1, 1, 1);
+    }
+
+    /** **/
+    public static PagesListAddPageRecord buildPagesListAddPageRecord() {
+        return new PagesListAddPageRecord(1, 1, 1);
+    }
+
+    /** **/
+    public static PagesListRemovePageRecord buildPagesListRemovePageRecord() {
+        return new PagesListRemovePageRecord(1, 1, 1);
+    }
+
+    /** **/
+    public static MetaPageInitRecord buildMetaPageInitRecord() {
+        return new MetaPageInitRecord(1, 1, 1, 1, 1, 1);
+    }
+
+    /** **/
+    public static MetaPageUpdatePartitionDataRecord buildMetaPageUpdatePartitionDataRecord() {
+        return new MetaPageUpdatePartitionDataRecord(1, 1, 1, 1, 1, 1, (byte)1, 1);
+    }
+
+    /** **/
+    public static MemoryRecoveryRecord buildMemoryRecoveryRecord() {
+        return new MemoryRecoveryRecord(1);
+    }
+
+    /** **/
+    public static TrackingPageDeltaRecord buildTrackingPageDeltaRecord() {
+        return new TrackingPageDeltaRecord(1, 1, 1, 1, 1);
+    }
+
+    /** **/
+    public static MetaPageUpdateLastSuccessfulSnapshotId buildMetaPageUpdateLastSuccessfulSnapshotId() {
+        return new MetaPageUpdateLastSuccessfulSnapshotId(1, 1, 1, 1);
+    }
+
+    /** **/
+    public static MetaPageUpdateLastSuccessfulFullSnapshotId buildMetaPageUpdateLastSuccessfulFullSnapshotId() {
+        return new MetaPageUpdateLastSuccessfulFullSnapshotId(1, 1, 1);
+    }
+
+    /** **/
+    public static MetaPageUpdateNextSnapshotId buildMetaPageUpdateNextSnapshotId() {
+        return new MetaPageUpdateNextSnapshotId(1, 1, 1);
+    }
+
+    /** **/
+    public static MetaPageUpdateLastAllocatedIndex buildMetaPageUpdateLastAllocatedIndex() {
+        return new MetaPageUpdateLastAllocatedIndex(1, 1, 1);
+    }
+
+    /** **/
+    public static PartitionMetaStateRecord buildPartitionMetaStateRecord() {
+        return new PartitionMetaStateRecord(1, 1, GridDhtPartitionState.OWNING, 1);
+    }
+
+    /** **/
+    public static PageListMetaResetCountRecord buildPageListMetaResetCountRecord() {
+        return new PageListMetaResetCountRecord(1, 1);
+    }
+
+    /** **/
+    public static SwitchSegmentRecord buildSwitchSegmentRecord() {
+        return new SwitchSegmentRecord();
+    }
+
+    /** **/
+    public static DataPageUpdateRecord buildDataPageUpdateRecord() {
+        byte[] random = {1, 3, 5};
+
+        return new DataPageUpdateRecord(1, 1, 1, random);
+    }
+
+    /** **/
+    public static MetaPageInitRootInlineRecord buildMetaPageInitRootInlineRecord() {
+        return new MetaPageInitRootInlineRecord(1, 1, 2, 1);
+    }
+
+    /** **/
+    public static PartitionDestroyRecord buildPartitionDestroyRecord() {
+        return new PartitionDestroyRecord(1, 1);
+    }
+
+    /** **/
+    public static SnapshotRecord buildSnapshotRecord() {
+        return new SnapshotRecord(1, true);
+    }
+
+    /** **/
+    public static MetastoreDataRecord buildMetastoreDataRecord() {
+        byte[] value = {1, 3, 5};
+
+        return new MetastoreDataRecord("key", value);
+    }
+
+    /** **/
+    public static ExchangeRecord buildExchangeRecord() {
+        return new ExchangeRecord((short)1, ExchangeRecord.Type.LEFT, 1);
+    }
+
+    /** **/
+    public static UnsupportedWalRecord buildReservedRecord() {
+        return new UnsupportedWalRecord(RESERVED);
+    }
+
+    /** **/
+    public static RollbackRecord buildRollbackRecord() {
+        return new RollbackRecord(1, 1, 1, 1);
+    }
+
+    /** **/
+    public static MetaPageUpdatePartitionDataRecordV2 buildMetaPageUpdatePartitionDataRecordV2() {
+        return new MetaPageUpdatePartitionDataRecordV2(1, 1, 1, 1, 1, 1, (byte)1, 1, 1);
+    }
+
+    /** **/
+    public static MasterKeyChangeRecord buildMasterKeyChangeRecord() {
+        return new MasterKeyChangeRecord("", new HashMap<>());
+    }
+
+    /** **/
+    public static RotatedIdPartRecord buildRotatedIdPartRecord() {
+        return new RotatedIdPartRecord(1, 1, 2);
+    }
+
+    /** **/
+    public static DataPageMvccMarkUpdatedRecord buildDataPageMvccMarkUpdatedRecord() {
+        return new DataPageMvccMarkUpdatedRecord(1, 1, 2, 1, 1, 1);
+    }
+
+    /** **/
+    public static DataPageMvccUpdateTxStateHintRecord buildDataPageMvccUpdateTxStateHintRecord() {
+        return new DataPageMvccUpdateTxStateHintRecord(1, 1, 2, (byte)1);
+    }
+
+    /** **/
+    public static DataPageMvccUpdateNewTxStateHintRecord buildDataPageMvccUpdateNewTxStateHintRecord() {
+        return new DataPageMvccUpdateNewTxStateHintRecord(1, 1, 2, (byte)1);
+    }
+
+    /** **/
+    public static UnsupportedWalRecord buildEncryptedRecord() {
+        return new UnsupportedWalRecord(ENCRYPTED_RECORD);
+    }
+
+    /** **/
+    public static UnsupportedWalRecord buildEncryptedDataRecord() {
+        return new UnsupportedWalRecord(ENCRYPTED_DATA_RECORD);
+    }
+
+    /** **/
+    public static MvccDataRecord buildMvccDataRecord() {
+        return new MvccDataRecord(Collections.emptyList(), 1);
+    }
+
+    /** **/
+    public static MvccTxRecord buildMvccTxRecord() {
+        return new MvccTxRecord(
+            TransactionState.PREPARED,
+            new GridCacheVersion(),
+            new GridCacheVersion(),
+            new HashMap<>(),
+            new MvccVersionImpl()
+        );
+    }
+
+    /** **/
+    public static UnsupportedWalRecord buildConsistentCutRecord() {
+        return new UnsupportedWalRecord(CONSISTENT_CUT);
+    }
+
+    /** **/
+    public static UnsupportedWalRecord buildBtreeMetaPageInitRootV3() {
+        return new UnsupportedWalRecord(BTREE_META_PAGE_INIT_ROOT_V3);
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/wal/record/UnsupportedWalRecord.java b/modules/core/src/test/java/org/apache/ignite/testframework/wal/record/UnsupportedWalRecord.java
new file mode 100644
index 0000000..13407a1
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/wal/record/UnsupportedWalRecord.java
@@ -0,0 +1,46 @@
+/*
+ * 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.testframework.wal.record;
+
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * The wrapper of record type which isn't supported anymore.
+ */
+public class UnsupportedWalRecord extends WALRecord {
+    /** **/
+    private final RecordType recordType;
+
+    /**
+     * @param type Record type.
+     */
+    public UnsupportedWalRecord(RecordType type) {
+        recordType = type;
+    }
+
+    /** {@inheritDoc} */
+    @Override public RecordType type() {
+        return recordType;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(UnsupportedWalRecord.class, this, "super", super.toString());
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
index 5dbdea7..35c00cd 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
@@ -50,6 +50,7 @@
 import org.apache.ignite.internal.managers.IgniteDiagnosticMessagesTest;
 import org.apache.ignite.internal.managers.communication.GridIoManagerFileTransmissionSelfTest;
 import org.apache.ignite.internal.managers.discovery.IncompleteDeserializationExceptionTest;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecordSerializationTest;
 import org.apache.ignite.internal.pagemem.wal.record.WALRecordTest;
 import org.apache.ignite.internal.processors.DeadLockOnNodeLeftExchangeTest;
 import org.apache.ignite.internal.processors.affinity.GridAffinityAssignmentV2Test;
@@ -203,6 +204,7 @@
     AttributeNodeFilterSelfTest.class,
 
     WALRecordTest.class,
+    WALRecordSerializationTest.class,
 
     GridPeerDeploymentRetryTest.class,
     GridPeerDeploymentRetryModifiedTest.class,