/* * 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.thrift; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import junit.framework.Assert; import org.apache.cassandra.SchemaLoader; import org.apache.cassandra.config.Schema; import org.apache.cassandra.service.EmbeddedCassandraService; import org.apache.cassandra.utils.ByteBufferUtil; import org.apache.thrift.TException; import org.junit.BeforeClass; import org.junit.Test; public class MultiSliceTest extends SchemaLoader { private static CassandraServer server; @BeforeClass public static void setup() throws IOException, TException { Schema.instance.clear(); // Schema are now written on disk and will be reloaded new EmbeddedCassandraService().start(); ThriftSessionManager.instance.setCurrentSocket(new InetSocketAddress(9160)); server = new CassandraServer(); server.set_keyspace("Keyspace1"); } private static MultiSliceRequest makeMultiSliceRequest(ByteBuffer key) { ColumnParent cp = new ColumnParent("Standard1"); MultiSliceRequest req = new MultiSliceRequest(); req.setKey(key); req.setCount(1000); req.reversed = false; req.setColumn_parent(cp); return req; } @Test public void test_multi_slice_optional_column_slice() throws TException { ColumnParent cp = new ColumnParent("Standard1"); ByteBuffer key = ByteBuffer.wrap("multi_slice".getBytes()); List<String> expected = new ArrayList<String>(); for (char a = 'a'; a <= 'z'; a++) expected.add(a + ""); addTheAlphabetToRow(key, cp); MultiSliceRequest req = makeMultiSliceRequest(key); req.setColumn_slices(new ArrayList<ColumnSlice>()); req.getColumn_slices().add(new ColumnSlice()); List<ColumnOrSuperColumn> list = server.get_multi_slice(req); assertColumnNameMatches(expected, list); } @Test public void test_multi_slice() throws TException { ColumnParent cp = new ColumnParent("Standard1"); ByteBuffer key = ByteBuffer.wrap("multi_slice_two_slice".getBytes()); addTheAlphabetToRow(key, cp); MultiSliceRequest req = makeMultiSliceRequest(key); req.setColumn_slices(Arrays.asList(columnSliceFrom("a", "e"), columnSliceFrom("i", "n"))); assertColumnNameMatches(Arrays.asList("a", "b", "c", "d", "e", "i", "j", "k" , "l", "m" , "n"), server.get_multi_slice(req)); } @Test public void test_with_overlap() throws TException { ColumnParent cp = new ColumnParent("Standard1"); ByteBuffer key = ByteBuffer.wrap("overlap".getBytes()); addTheAlphabetToRow(key, cp); MultiSliceRequest req = makeMultiSliceRequest(key); req.setColumn_slices(Arrays.asList(columnSliceFrom("a", "e"), columnSliceFrom("d", "g"))); assertColumnNameMatches(Arrays.asList("a", "b", "c", "d", "e", "f", "g"), server.get_multi_slice(req)); } @Test public void test_with_overlap_reversed() throws TException { ColumnParent cp = new ColumnParent("Standard1"); ByteBuffer key = ByteBuffer.wrap("overlap_reversed".getBytes()); addTheAlphabetToRow(key, cp); MultiSliceRequest req = makeMultiSliceRequest(key); req.reversed = true; req.setColumn_slices(Arrays.asList(columnSliceFrom("e", "a"), columnSliceFrom("g", "d"))); assertColumnNameMatches(Arrays.asList("g", "f", "e", "d", "c", "b", "a"), server.get_multi_slice(req)); } @Test(expected=InvalidRequestException.class) public void test_that_column_slice_is_proper() throws TException { ByteBuffer key = ByteBuffer.wrap("overlap".getBytes()); MultiSliceRequest req = makeMultiSliceRequest(key); req.reversed = true; req.setColumn_slices(Arrays.asList(columnSliceFrom("a", "e"), columnSliceFrom("g", "d"))); assertColumnNameMatches(Arrays.asList("a", "b", "c", "d", "e", "f", "g"), server.get_multi_slice(req)); } @Test public void test_with_overlap_reversed_with_count() throws TException { ColumnParent cp = new ColumnParent("Standard1"); ByteBuffer key = ByteBuffer.wrap("overlap_reversed_count".getBytes()); addTheAlphabetToRow(key, cp); MultiSliceRequest req = makeMultiSliceRequest(key); req.setCount(6); req.reversed = true; req.setColumn_slices(Arrays.asList(columnSliceFrom("e", "a"), columnSliceFrom("g", "d"))); assertColumnNameMatches(Arrays.asList("g", "f", "e", "d", "c", "b"), server.get_multi_slice(req)); } @Test public void test_with_overlap_with_count() throws TException { ColumnParent cp = new ColumnParent("Standard1"); ByteBuffer key = ByteBuffer.wrap("overlap_reversed_count".getBytes()); addTheAlphabetToRow(key, cp); MultiSliceRequest req = makeMultiSliceRequest(key); req.setCount(6); req.setColumn_slices(Arrays.asList(columnSliceFrom("a", "e"), columnSliceFrom("d", "g"), columnSliceFrom("d", "g"))); assertColumnNameMatches(Arrays.asList("a", "b", "c", "d", "e", "f"), server.get_multi_slice(req)); } private static void addTheAlphabetToRow(ByteBuffer key, ColumnParent parent) throws InvalidRequestException, UnavailableException, TimedOutException { for (char a = 'a'; a <= 'z'; a++) { Column c1 = new Column(); c1.setName(ByteBufferUtil.bytes(String.valueOf(a))); c1.setValue(new byte [0]); c1.setTimestamp(System.nanoTime()); server.insert(key, parent, c1, ConsistencyLevel.ONE); } } private static void assertColumnNameMatches(List<String> expected , List<ColumnOrSuperColumn> actual) { Assert.assertEquals(actual+" "+expected +" did not have same number of elements", actual.size(), expected.size()); for (int i = 0 ; i< expected.size() ; i++) { Assert.assertEquals(actual.get(i) +" did not equal "+ expected.get(i), expected.get(i), new String(actual.get(i).getColumn().getName())); } } private ColumnSlice columnSliceFrom(String startInclusive, String endInclusive) { ColumnSlice cs = new ColumnSlice(); cs.setStart(ByteBufferUtil.bytes(startInclusive)); cs.setFinish(ByteBufferUtil.bytes(endInclusive)); return cs; } }