/*
 * 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.cassandra.db;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.junit.AfterClass;
import org.apache.cassandra.db.LegacyLayout.CellGrouper;
import org.apache.cassandra.db.LegacyLayout.LegacyBound;
import org.apache.cassandra.db.LegacyLayout.LegacyCell;
import org.apache.cassandra.db.LegacyLayout.LegacyRangeTombstone;
import org.apache.cassandra.db.filter.ColumnFilter;
import org.apache.cassandra.db.marshal.MapType;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.db.rows.BufferCell;
import org.apache.cassandra.db.rows.Cell;
import org.apache.cassandra.db.rows.RowIterator;
import org.apache.cassandra.db.rows.SerializationHelper;
import org.apache.cassandra.db.rows.UnfilteredRowIterator;
import org.apache.cassandra.db.rows.UnfilteredRowIteratorSerializer;
import org.apache.cassandra.db.transform.FilteredRows;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.io.util.DataInputBuffer;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.serializers.Int32Serializer;
import org.apache.cassandra.serializers.UTF8Serializer;
import org.apache.cassandra.service.MigrationManager;
import org.apache.cassandra.utils.FBUtilities;
import org.junit.BeforeClass;
import org.junit.Test;

import org.apache.cassandra.SchemaLoader;
import org.apache.cassandra.Util;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.cql3.QueryProcessor;
import org.apache.cassandra.cql3.UntypedResultSet;
import org.apache.cassandra.db.marshal.Int32Type;
import org.apache.cassandra.db.marshal.SetType;
import org.apache.cassandra.db.partitions.PartitionUpdate;
import org.apache.cassandra.db.rows.BTreeRow;
import org.apache.cassandra.db.rows.Row;
import org.apache.cassandra.dht.Murmur3Partitioner;
import org.apache.cassandra.schema.KeyspaceParams;
import org.apache.cassandra.utils.Hex;

import static org.apache.cassandra.net.MessagingService.VERSION_21;
import static org.apache.cassandra.utils.ByteBufferUtil.bytes;
import static org.junit.Assert.*;

public class LegacyLayoutTest
{
    static Util.PartitionerSwitcher sw;
    static String KEYSPACE = "Keyspace1";

    @BeforeClass
    public static void defineSchema() throws ConfigurationException
    {
        DatabaseDescriptor.daemonInitialization();
        sw = Util.switchPartitioner(Murmur3Partitioner.instance);
        SchemaLoader.loadSchema();
        SchemaLoader.createKeyspace(KEYSPACE, KeyspaceParams.simple(1));
    }

    @AfterClass
    public static void resetPartitioner()
    {
        sw.close();
    }

    @Test
    public void testFromUnfilteredRowIterator() throws Throwable
    {
        CFMetaData table = CFMetaData.Builder.create("ks", "table")
                                             .withPartitioner(Murmur3Partitioner.instance)
                                             .addPartitionKey("k", Int32Type.instance)
                                             .addRegularColumn("a", SetType.getInstance(Int32Type.instance, true))
                                             .addRegularColumn("b", SetType.getInstance(Int32Type.instance, true))
                                             .build();

        ColumnDefinition a = table.getColumnDefinition(new ColumnIdentifier("a", false));
        ColumnDefinition b = table.getColumnDefinition(new ColumnIdentifier("b", false));

        Row.Builder builder = BTreeRow.unsortedBuilder(0);
        builder.newRow(Clustering.EMPTY);
        builder.addComplexDeletion(a, new DeletionTime(1L, 1));
        builder.addComplexDeletion(b, new DeletionTime(1L, 1));
        Row row = builder.build();

        ByteBuffer key = bytes(1);
        PartitionUpdate upd = PartitionUpdate.singleRowUpdate(table, key, row);

        LegacyLayout.LegacyUnfilteredPartition p = LegacyLayout.fromUnfilteredRowIterator(null, upd.unfilteredIterator());
        assertEquals(DeletionTime.LIVE, p.partitionDeletion);
        assertEquals(0, p.cells.size());

        LegacyLayout.LegacyRangeTombstoneList l = p.rangeTombstones;
        assertEquals("a", l.starts[0].collectionName.name.toString());
        assertEquals("a", l.ends[0].collectionName.name.toString());

        assertEquals("b", l.starts[1].collectionName.name.toString());
        assertEquals("b", l.ends[1].collectionName.name.toString());
    }

    /**
     * Tests with valid sstables containing duplicate RT entries at index boundaries
     * in 2.1 format, where DATA below is a > 1000 byte long string of letters,
     * and the column index is set to 1kb

     [
     {"key": "1",
     "cells": [["1:_","1:!",1513015245,"t",1513015263],
     ["1:1:","",1513015467727335],
     ["1:1:val1","DATA",1513015467727335],
     ["1:_","1:!",1513015245,"t",1513015263],
     ["1:1:val2","DATA",1513015467727335],
     ["1:_","1:!",1513015245,"t",1513015263],
     ["1:1:val3","DATA",1513015467727335],
     ["1:_","1:!",1513015245,"t",1513015263],
     ["1:2:","",1513015458470156],
     ["1:2:val1","DATA",1513015458470156],
     ["1:_","1:!",1513015245,"t",1513015263],
     ["1:2:val2","DATA",1513015458470156],
     ["1:_","1:!",1513015245,"t",1513015263],
     ["1:2:val3","DATA",1513015458470156],
     ["1:_","1:!",1513015245,"t",1513015263],
     ["1:3:","",1513015450253602],
     ["1:3:val1","DATA",1513015450253602],
     ["1:_","1:!",1513015245,"t",1513015263],
     ["1:3:val2","DATA",1513015450253602],
     ["1:_","1:!",1513015245,"t",1513015263],
     ["1:3:val3","DATA",1513015450253602]]}
     ]
     *
     * See CASSANDRA-14008 for details.
     */
    @Test
    public void testRTBetweenColumns() throws Throwable
    {
        QueryProcessor.executeInternal(String.format("CREATE TABLE \"%s\".legacy_ka_repeated_rt (k1 int, c1 int, c2 int, val1 text, val2 text, val3 text, primary key (k1, c1, c2))", KEYSPACE));

        Keyspace keyspace = Keyspace.open(KEYSPACE);
        ColumnFamilyStore cfs = keyspace.getColumnFamilyStore("legacy_ka_repeated_rt");

        Path legacySSTableRoot = Paths.get("test/data/legacy-sstables/ka/legacy_tables/legacy_ka_repeated_rt/");

        for (String filename : new String[]{ "Keyspace1-legacy_ka_repeated_rt-ka-1-CompressionInfo.db",
                                             "Keyspace1-legacy_ka_repeated_rt-ka-1-Data.db",
                                             "Keyspace1-legacy_ka_repeated_rt-ka-1-Digest.sha1",
                                             "Keyspace1-legacy_ka_repeated_rt-ka-1-Filter.db",
                                             "Keyspace1-legacy_ka_repeated_rt-ka-1-Index.db",
                                             "Keyspace1-legacy_ka_repeated_rt-ka-1-Statistics.db",
                                             "Keyspace1-legacy_ka_repeated_rt-ka-1-Summary.db",
                                             "Keyspace1-legacy_ka_repeated_rt-ka-1-TOC.txt" })
        {
            Files.copy(Paths.get(legacySSTableRoot.toString(), filename), cfs.getDirectories().getDirectoryForNewSSTables().toPath().resolve(filename));
        }

        cfs.loadNewSSTables();

        UntypedResultSet rs = QueryProcessor.executeInternal(String.format("SELECT * FROM \"%s\".legacy_ka_repeated_rt WHERE k1=1", KEYSPACE));
        assertEquals(3, rs.size());

        UntypedResultSet rs2 = QueryProcessor.executeInternal(String.format("SELECT * FROM \"%s\".legacy_ka_repeated_rt WHERE k1=1 AND c1=1", KEYSPACE));
        assertEquals(3, rs2.size());

        for (int i = 1; i <= 3; i++)
        {
            UntypedResultSet rs3 = QueryProcessor.executeInternal(String.format("SELECT * FROM \"%s\".legacy_ka_repeated_rt WHERE k1=1 AND c1=1 AND c2=%s", KEYSPACE, i));
            assertEquals(1, rs3.size());
        }

    }


    private static UnfilteredRowIterator roundTripVia21(UnfilteredRowIterator partition) throws IOException
    {
        try (DataOutputBuffer out = new DataOutputBuffer())
        {
            LegacyLayout.serializeAsLegacyPartition(null, partition, out, VERSION_21);
            try (DataInputBuffer in = new DataInputBuffer(out.buffer(), false))
            {
                return LegacyLayout.deserializeLegacyPartition(in, VERSION_21, SerializationHelper.Flag.LOCAL, partition.partitionKey().getKey());
            }
        }
    }

    @Test
    public void testStaticRangeTombstoneRoundTripUnexpectedDeletion() throws Throwable
    {
        // this variant of the bug deletes a row with the same clustering key value as the name of the static collection
        QueryProcessor.executeInternal(String.format("CREATE TABLE \"%s\".legacy_static_rt_rt_1 (pk int, ck1 text, ck2 text, v int, s set<text> static, primary key (pk, ck1, ck2))", KEYSPACE));
        Keyspace keyspace = Keyspace.open(KEYSPACE);
        CFMetaData table = keyspace.getColumnFamilyStore("legacy_static_rt_rt_1").metadata;
        ColumnDefinition v = table.getColumnDefinition(new ColumnIdentifier("v", false));
        ColumnDefinition bug = table.getColumnDefinition(new ColumnIdentifier("s", false));

        Row.Builder builder;
        builder = BTreeRow.unsortedBuilder(0);
        builder.newRow(Clustering.STATIC_CLUSTERING);
        builder.addComplexDeletion(bug, new DeletionTime(1L, 1));
        Row staticRow = builder.build();

        builder = BTreeRow.unsortedBuilder(0);
        builder.newRow(new BufferClustering(UTF8Serializer.instance.serialize("s"), UTF8Serializer.instance.serialize("anything")));
        builder.addCell(new BufferCell(v, 1L, Cell.NO_TTL, Cell.NO_DELETION_TIME, Int32Serializer.instance.serialize(1), null));
        Row row = builder.build();

        DecoratedKey pk = table.decorateKey(bytes(1));
        PartitionUpdate upd = PartitionUpdate.singleRowUpdate(table, pk, row, staticRow);

        try (RowIterator before = FilteredRows.filter(upd.unfilteredIterator(), FBUtilities.nowInSeconds());
             RowIterator after = FilteredRows.filter(roundTripVia21(upd.unfilteredIterator()), FBUtilities.nowInSeconds()))
        {
            while (before.hasNext() || after.hasNext())
                assertEquals(before.hasNext() ? before.next() : null, after.hasNext() ? after.next() : null);
        }
    }

    @Test
    public void testStaticRangeTombstoneRoundTripCorruptRead() throws Throwable
    {
        // this variant of the bug corrupts the byte stream of the partition, so that a sequential read starting before
        // this partition will fail with a CorruptSSTableException, and possible yield junk results
        QueryProcessor.executeInternal(String.format("CREATE TABLE \"%s\".legacy_static_rt_rt_2 (pk int, ck int, nameWithLengthGreaterThan4 set<int> static, primary key (pk, ck))", KEYSPACE));
        Keyspace keyspace = Keyspace.open(KEYSPACE);
        CFMetaData table = keyspace.getColumnFamilyStore("legacy_static_rt_rt_2").metadata;

        ColumnDefinition bug = table.getColumnDefinition(new ColumnIdentifier("nameWithLengthGreaterThan4", false));

        Row.Builder builder = BTreeRow.unsortedBuilder(0);
        builder.newRow(Clustering.STATIC_CLUSTERING);
        builder.addComplexDeletion(bug, new DeletionTime(1L, 1));
        Row row = builder.build();

        DecoratedKey pk = table.decorateKey(bytes(1));
        PartitionUpdate upd = PartitionUpdate.singleRowUpdate(table, pk, row);

        UnfilteredRowIterator afterRoundTripVia32 = roundTripVia21(upd.unfilteredIterator());
        try (DataOutputBuffer out = new DataOutputBuffer())
        {
            // we only encounter a corruption/serialization error after writing this to a 3.0 format and reading it back
            UnfilteredRowIteratorSerializer.serializer.serialize(afterRoundTripVia32, ColumnFilter.all(table), out, MessagingService.current_version);
            try (DataInputBuffer in = new DataInputBuffer(out.buffer(), false);
                 UnfilteredRowIterator afterSerialization = UnfilteredRowIteratorSerializer.serializer.deserialize(in, MessagingService.current_version, table, ColumnFilter.all(table), SerializationHelper.Flag.LOCAL))
            {
                while (afterSerialization.hasNext())
                    afterSerialization.next();
            }
        }
    }

    @Test
    public void testCollectionDeletionRoundTripForDroppedColumn() throws Throwable
    {
        // this variant of the bug deletes a row with the same clustering key value as the name of the static collection
        QueryProcessor.executeInternal(String.format("CREATE TABLE \"%s\".legacy_rt_rt_dc (pk int, ck1 text, v int, s set<text>, primary key (pk, ck1))", KEYSPACE));
        Keyspace keyspace = Keyspace.open(KEYSPACE);
        CFMetaData table = keyspace.getColumnFamilyStore("legacy_rt_rt_dc").metadata;
        ColumnDefinition v = table.getColumnDefinition(new ColumnIdentifier("v", false));
        ColumnDefinition bug = table.getColumnDefinition(new ColumnIdentifier("s", false));

        Row.Builder builder;
        builder = BTreeRow.unsortedBuilder(0);
        builder.newRow(new BufferClustering(UTF8Serializer.instance.serialize("a")));
        builder.addCell(BufferCell.live(v, 0L, Int32Serializer.instance.serialize(1), null));
        builder.addComplexDeletion(bug, new DeletionTime(1L, 1));
        Row row = builder.build();

        DecoratedKey pk = table.decorateKey(bytes(1));
        PartitionUpdate upd = PartitionUpdate.singleRowUpdate(table, pk, row);

        // we need to perform the round trip in two parts here, with a column drop inbetween
        try (RowIterator before = FilteredRows.filter(upd.unfilteredIterator(), FBUtilities.nowInSeconds());
             DataOutputBuffer serialized21 = new DataOutputBuffer())
        {
            LegacyLayout.serializeAsLegacyPartition(null, upd.unfilteredIterator(), serialized21, VERSION_21);
            QueryProcessor.executeInternal(String.format("ALTER TABLE \"%s\".legacy_rt_rt_dc DROP s", KEYSPACE));
            try (DataInputBuffer in = new DataInputBuffer(serialized21.buffer(), false))
            {
                try (UnfilteredRowIterator deser21 = LegacyLayout.deserializeLegacyPartition(in, VERSION_21, SerializationHelper.Flag.LOCAL, upd.partitionKey().getKey());
                    RowIterator after = FilteredRows.filter(deser21, FBUtilities.nowInSeconds());)
                {
                    while (before.hasNext() || after.hasNext())
                        assertEquals(before.hasNext() ? before.next() : null, after.hasNext() ? after.next() : null);
                }
            }

        }
    }

    @Test
    public void testDecodeLegacyPagedRangeCommandSerializer() throws IOException
    {
        /*
         Run on 2.1
         public static void main(String[] args) throws IOException, ConfigurationException
         {
             Gossiper.instance.start((int) (System.currentTimeMillis() / 1000));
             Keyspace.setInitialized();
             CFMetaData cfMetaData = CFMetaData.sparseCFMetaData("ks", "cf", UTF8Type.instance)
             .addColumnDefinition(new ColumnDefinition("ks", "cf", new ColumnIdentifier("v", true), SetType.getInstance(Int32Type.instance, false), null, null, null, null, ColumnDefinition.Kind.REGULAR));
             KSMetaData ksMetaData = KSMetaData.testMetadata("ks", SimpleStrategy.class, KSMetaData.optsWithRF(3), cfMetaData);
             MigrationManager.announceNewKeyspace(ksMetaData);
             RowPosition position = RowPosition.ForKey.get(ByteBufferUtil.EMPTY_BYTE_BUFFER, new Murmur3Partitioner());
             SliceQueryFilter filter = new IdentityQueryFilter();
             Composite cellName = CellNames.compositeSparseWithCollection(new ByteBuffer[0], Int32Type.instance.decompose(1), new ColumnIdentifier("v", true), false);
             try (DataOutputBuffer buffer = new DataOutputBuffer(1024))
             {
                 PagedRangeCommand command = new PagedRangeCommand("ks", "cf", 1, AbstractBounds.bounds(position, true, position, true), filter, cellName, filter.finish(), Collections.emptyList(), 1, true);
                 PagedRangeCommand.serializer.serialize(command, buffer, MessagingService.current_version);
                 System.out.println(Hex.bytesToHex(buffer.toByteArray()));
             }
         }
         */

        DatabaseDescriptor.daemonInitialization();
        Keyspace.setInitialized();
        CFMetaData table = CFMetaData.Builder.create("ks", "cf")
                                             .addPartitionKey("k", Int32Type.instance)
                                             .addRegularColumn("v", SetType.getInstance(Int32Type.instance, true))
                                             .build();
        SchemaLoader.createKeyspace("ks", KeyspaceParams.simple(1));
        MigrationManager.announceNewColumnFamily(table);

        byte[] bytes = Hex.hexToBytes("00026b73000263660000000000000001fffffffe01000000088000000000000000010000000880000000000000000000000100000000007fffffffffffffff000b00017600000400000001000000000000000000000101");
        ReadCommand.legacyPagedRangeCommandSerializer.deserialize(new DataInputBuffer(bytes), VERSION_21);
    }

    @Test
    public void testDecodeCollectionPageBoundary()
    {
        CFMetaData table = CFMetaData.Builder.create("ks", "cf")
                                             .addPartitionKey("k", Int32Type.instance)
                                             .addRegularColumn("v", SetType.getInstance(Int32Type.instance, true))
                                             .build();

        ColumnDefinition v = table.getColumnDefinition(new ColumnIdentifier("v", false));
        ByteBuffer bound = LegacyLayout.encodeCellName(table, Clustering.EMPTY, v.name.bytes, Int32Type.instance.decompose(1));

        LegacyLayout.decodeSliceBound(table, bound, true);
    }

    @Test
    public void testAsymmetricRTBoundSerializedSize()
    {
        CFMetaData table = CFMetaData.Builder.create("ks", "cf")
                                             .addPartitionKey("k", Int32Type.instance)
                                             .addClusteringColumn("c1", Int32Type.instance)
                                             .addClusteringColumn("c2", Int32Type.instance)
                                             .addRegularColumn("v", Int32Type.instance)
                                             .build();

        ByteBuffer one = Int32Type.instance.decompose(1);
        ByteBuffer two = Int32Type.instance.decompose(2);
        PartitionUpdate p = new PartitionUpdate(table, table.decorateKey(one), table.partitionColumns(), 0);
        p.add(new RangeTombstone(Slice.make(new ClusteringBound(ClusteringPrefix.Kind.EXCL_START_BOUND, new ByteBuffer[] { one, one }),
                                            new ClusteringBound(ClusteringPrefix.Kind.INCL_END_BOUND, new ByteBuffer[] { two })),
                                 new DeletionTime(1, 1)
        ));

        LegacyLayout.fromUnfilteredRowIterator(null, p.unfilteredIterator());
        LegacyLayout.serializedSizeAsLegacyPartition(null, p.unfilteredIterator(), VERSION_21);
    }

    @Test
    public void testCellGrouper()
    {
        // CREATE TABLE %s (pk int, ck int, v map<text, text>, PRIMARY KEY (pk, ck))
        CFMetaData cfm = CFMetaData.Builder.create("ks", "table")
                                           .addPartitionKey("pk", Int32Type.instance)
                                           .addClusteringColumn("ck", Int32Type.instance)
                                           .addRegularColumn("v", MapType.getInstance(UTF8Type.instance, UTF8Type.instance, true))
                                           .build();
        SerializationHelper helper = new SerializationHelper(cfm, MessagingService.VERSION_22, SerializationHelper.Flag.LOCAL, ColumnFilter.all(cfm));
        LegacyLayout.CellGrouper cg = new LegacyLayout.CellGrouper(cfm, helper);

        ClusteringBound startBound = ClusteringBound.create(ClusteringPrefix.Kind.INCL_START_BOUND, new ByteBuffer[] {bytes(2)});
        ClusteringBound endBound = ClusteringBound.create(ClusteringPrefix.Kind.EXCL_END_BOUND, new ByteBuffer[] {bytes(2)});
        LegacyLayout.LegacyBound start = new LegacyLayout.LegacyBound(startBound, false, cfm.getColumnDefinition(bytes("v")));
        LegacyLayout.LegacyBound end = new LegacyLayout.LegacyBound(endBound, false, cfm.getColumnDefinition(bytes("v")));
        LegacyLayout.LegacyRangeTombstone lrt = new LegacyLayout.LegacyRangeTombstone(start, end, new DeletionTime(2, 1588598040));
        assertTrue(cg.addAtom(lrt));

        // add a real cell
        LegacyLayout.LegacyCell cell = new LegacyLayout.LegacyCell(LegacyLayout.LegacyCell.Kind.REGULAR,
                                                                   new LegacyLayout.LegacyCellName(Clustering.make(bytes(2)),
                                                                                                   cfm.getColumnDefinition(bytes("v")),
                                                                                                   bytes("g")),
                                                                   bytes("v"), 3, Integer.MAX_VALUE, 0);
        assertTrue(cg.addAtom(cell));

        // add legacy range tombstone where collection name is null for the end bound (this gets translated to a row tombstone)
        startBound = ClusteringBound.create(ClusteringPrefix.Kind.EXCL_START_BOUND, new ByteBuffer[] {bytes(2)});
        endBound = ClusteringBound.create(ClusteringPrefix.Kind.EXCL_END_BOUND, new ByteBuffer[] {bytes(2)});
        start = new LegacyLayout.LegacyBound(startBound, false, cfm.getColumnDefinition(bytes("v")));
        end = new LegacyLayout.LegacyBound(endBound, false, null);
        assertTrue(cg.addAtom(new LegacyLayout.LegacyRangeTombstone(start, end, new DeletionTime(1, 1588598040))));
    }

    private static LegacyCell cell(Clustering clustering, ColumnDefinition column, ByteBuffer value, long timestamp)
    {
        return new LegacyCell(LegacyCell.Kind.REGULAR,
                              new LegacyLayout.LegacyCellName(clustering, column, null),
                              value,
                              timestamp,
                              Cell.NO_DELETION_TIME,
                              Cell.NO_TTL);
    }

    /**
     * This tests that when {@link CellGrouper} gets a collection tombstone for
     * a non-fetched collection, then that tombstone does not incorrectly stop the grouping of the current row, as
     * was done before CASSANDRA-15805.
     *
     * <p>Please note that this rely on a query only _fetching_ some of the table columns, which in practice only
     * happens for thrift queries, and thrift queries shouldn't mess up with CQL tables and collection tombstones,
     * so this test is not of the utmost importance. Nonetheless, the pre-CASSANDRA-15805 behavior was incorrect and
     * this ensure it is fixed.
     */
    @Test
    public void testCellGrouperOnNonFecthedCollectionTombstone()
    {
        // CREATE TABLE %s (pk int, ck int, a text, b set<text>, c text, PRIMARY KEY (pk, ck))
        CFMetaData cfm = CFMetaData.Builder.create("ks", "table")
                                           .addPartitionKey("pk", Int32Type.instance)
                                           .addClusteringColumn("ck", Int32Type.instance)
                                           .addRegularColumn("a", UTF8Type.instance)
                                           .addRegularColumn("b", SetType.getInstance(UTF8Type.instance, true))
                                           .addRegularColumn("c", UTF8Type.instance)
                                           .build();

        // Creates a filter that _only_ fetches a and c, but not b.
        ColumnFilter filter = ColumnFilter.selectionBuilder()
                                          .add(cfm.getColumnDefinition(bytes("a")))
                                          .add(cfm.getColumnDefinition(bytes("c")))
                                          .build();
        SerializationHelper helper = new SerializationHelper(cfm,
                                                             MessagingService.VERSION_22,
                                                             SerializationHelper.Flag.LOCAL,
                                                             filter);
        CellGrouper grouper = new CellGrouper(cfm, helper);
        Clustering clustering = new BufferClustering(bytes(1));

        // We add a cell for a, then a collection tombstone for b, and then a cell for c (for the same clustering).
        // All those additions should return 'true' as all belong to the same row.
        LegacyCell ca = cell(clustering, cfm.getColumnDefinition(bytes("a")), bytes("v1"), 1);
        assertTrue(grouper.addAtom(ca));

        ClusteringBound startBound = ClusteringBound.inclusiveStartOf(bytes(1));
        ClusteringBound endBound = ClusteringBound.inclusiveEndOf(bytes(1));
        ColumnDefinition bDef = cfm.getColumnDefinition(bytes("b"));
        assert bDef != null;
        LegacyBound start = new LegacyBound(startBound, false, bDef);
        LegacyBound end = new LegacyBound(endBound, false, bDef);
        LegacyRangeTombstone rtb = new LegacyRangeTombstone(start, end, new DeletionTime(1, 1588598040));
        assertTrue(rtb.isCollectionTombstone()); // Ensure we're testing what we think
        assertTrue(grouper.addAtom(rtb));

        LegacyCell cc = cell(clustering, cfm.getColumnDefinition(bytes("c")), bytes("v2"), 1);
        assertTrue(grouper.addAtom(cc));
    }
}
