Return-Path: X-Original-To: apmail-cassandra-commits-archive@www.apache.org Delivered-To: apmail-cassandra-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A633F116E3 for ; Mon, 19 May 2014 10:30:36 +0000 (UTC) Received: (qmail 98826 invoked by uid 500); 19 May 2014 10:30:36 -0000 Delivered-To: apmail-cassandra-commits-archive@cassandra.apache.org Received: (qmail 98789 invoked by uid 500); 19 May 2014 10:30:36 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 98777 invoked by uid 99); 19 May 2014 10:30:36 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 19 May 2014 10:30:36 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 4DEBE986BC5; Mon, 19 May 2014 10:30:36 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: slebresne@apache.org To: commits@cassandra.apache.org Date: Mon, 19 May 2014 10:30:36 -0000 Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: [1/2] git commit: Validate method for CollectionType Repository: cassandra Updated Branches: refs/heads/trunk 308f2c0fc -> 5b5301332 Validate method for CollectionType patch by slebresne; reviewed by thobbs for CASSANDRA-7208 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/590b3b23 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/590b3b23 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/590b3b23 Branch: refs/heads/trunk Commit: 590b3b23ac2db333048c52c5323b78d0630605ae Parents: 33bd8c2 Author: Sylvain Lebresne Authored: Mon May 19 12:28:49 2014 +0200 Committer: Sylvain Lebresne Committed: Mon May 19 12:28:49 2014 +0200 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cassandra/db/marshal/CollectionType.java | 5 -- .../serializers/CollectionSerializer.java | 12 +-- .../cassandra/serializers/ListSerializer.java | 15 ++++ .../cassandra/serializers/MapSerializer.java | 18 ++++ .../cassandra/serializers/SetSerializer.java | 15 ++++ .../db/marshal/CollectionTypeTest.java | 93 ++++++++++++++++++++ 7 files changed, 149 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 3a9eb2b..4efaa46 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -15,6 +15,7 @@ * Make batchlog replay asynchronous (CASSANDRA-6134) * remove unused classes (CASSANDRA-7197) * Limit user types to the keyspace they are defined in (CASSANDRA-6643) + * Add validate method to CollectionType (CASSANDRA-7208) Merged from 2.0: * (Hadoop) support authentication in CqlRecordReader (CASSANDRA-7221) * (Hadoop) Close java driver Cluster in CQLRR.close (CASSANDRA-7228) http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/src/java/org/apache/cassandra/db/marshal/CollectionType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/CollectionType.java b/src/java/org/apache/cassandra/db/marshal/CollectionType.java index 7f75a5f..b1d8da1 100644 --- a/src/java/org/apache/cassandra/db/marshal/CollectionType.java +++ b/src/java/org/apache/cassandra/db/marshal/CollectionType.java @@ -85,11 +85,6 @@ public abstract class CollectionType extends AbstractType } } - public void validate(ByteBuffer bytes) - { - valueComparator().validate(bytes); - } - @Override public boolean isCompatibleWith(AbstractType previous) { http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/src/java/org/apache/cassandra/serializers/CollectionSerializer.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/serializers/CollectionSerializer.java b/src/java/org/apache/cassandra/serializers/CollectionSerializer.java index 5452a96..7cddb12 100644 --- a/src/java/org/apache/cassandra/serializers/CollectionSerializer.java +++ b/src/java/org/apache/cassandra/serializers/CollectionSerializer.java @@ -25,15 +25,11 @@ import org.apache.cassandra.utils.ByteBufferUtil; public abstract class CollectionSerializer implements TypeSerializer { - public void validate(ByteBuffer bytes) throws MarshalException - { - // The collection is not currently being properly validated. - } - protected abstract List serializeValues(T value); protected abstract int getElementCount(T value); public abstract T deserializeForNativeProtocol(ByteBuffer buffer, int version); + public abstract void validateForNativeProtocol(ByteBuffer buffer, int version); public ByteBuffer serialize(T value) { @@ -52,6 +48,12 @@ public abstract class CollectionSerializer implements TypeSerializer return deserializeForNativeProtocol(bytes, 3); } + public void validate(ByteBuffer bytes) throws MarshalException + { + // Same thing than above + validateForNativeProtocol(bytes, 3); + } + public static ByteBuffer pack(List buffers, int elements, int version) { int size = 0; http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/src/java/org/apache/cassandra/serializers/ListSerializer.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/serializers/ListSerializer.java b/src/java/org/apache/cassandra/serializers/ListSerializer.java index e662341..b64c012 100644 --- a/src/java/org/apache/cassandra/serializers/ListSerializer.java +++ b/src/java/org/apache/cassandra/serializers/ListSerializer.java @@ -60,6 +60,21 @@ public class ListSerializer extends CollectionSerializer> return value.size(); } + public void validateForNativeProtocol(ByteBuffer bytes, int version) + { + try + { + ByteBuffer input = bytes.duplicate(); + int n = readCollectionSize(input, version); + for (int i = 0; i < n; i++) + elements.validate(readValue(input, version)); + } + catch (BufferUnderflowException e) + { + throw new MarshalException("Not enough bytes to read a list"); + } + } + public List deserializeForNativeProtocol(ByteBuffer bytes, int version) { try http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/src/java/org/apache/cassandra/serializers/MapSerializer.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/serializers/MapSerializer.java b/src/java/org/apache/cassandra/serializers/MapSerializer.java index 5d349dd..34e7c05 100644 --- a/src/java/org/apache/cassandra/serializers/MapSerializer.java +++ b/src/java/org/apache/cassandra/serializers/MapSerializer.java @@ -67,6 +67,24 @@ public class MapSerializer extends CollectionSerializer> return value.size(); } + public void validateForNativeProtocol(ByteBuffer bytes, int version) + { + try + { + ByteBuffer input = bytes.duplicate(); + int n = readCollectionSize(input, version); + for (int i = 0; i < n; i++) + { + keys.validate(readValue(input, version)); + values.validate(readValue(input, version)); + } + } + catch (BufferUnderflowException e) + { + throw new MarshalException("Not enough bytes to read a set"); + } + } + public Map deserializeForNativeProtocol(ByteBuffer bytes, int version) { try http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/src/java/org/apache/cassandra/serializers/SetSerializer.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/serializers/SetSerializer.java b/src/java/org/apache/cassandra/serializers/SetSerializer.java index 812dd68..136b4e0 100644 --- a/src/java/org/apache/cassandra/serializers/SetSerializer.java +++ b/src/java/org/apache/cassandra/serializers/SetSerializer.java @@ -60,6 +60,21 @@ public class SetSerializer extends CollectionSerializer> return value.size(); } + public void validateForNativeProtocol(ByteBuffer bytes, int version) + { + try + { + ByteBuffer input = bytes.duplicate(); + int n = readCollectionSize(input, version); + for (int i = 0; i < n; i++) + elements.validate(readValue(input, version)); + } + catch (BufferUnderflowException e) + { + throw new MarshalException("Not enough bytes to read a set"); + } + } + public Set deserializeForNativeProtocol(ByteBuffer bytes, int version) { try http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java index c51d304..18156c3 100644 --- a/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java +++ b/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java @@ -18,6 +18,7 @@ package org.apache.cassandra.db.marshal; import java.nio.ByteBuffer; +import java.util.*; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -25,8 +26,10 @@ import com.google.common.collect.ImmutableSet; import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import org.apache.cassandra.utils.ByteBufferUtil; +import org.apache.cassandra.serializers.*; public class CollectionTypeTest { @@ -112,4 +115,94 @@ public class CollectionTypeTest } } } + + @Test + public void listSerDerTest() + { + ListSerializer sls = ListType.getInstance(UTF8Type.instance).getSerializer(); + ListSerializer ils = ListType.getInstance(Int32Type.instance).getSerializer(); + + List sl = Arrays.asList("Foo", "Bar"); + List il = Arrays.asList(3, 1, 5); + + ByteBuffer sb = sls.serialize(sl); + ByteBuffer ib = ils.serialize(il); + + assertEquals(sls.deserialize(sb), sl); + assertEquals(ils.deserialize(ib), il); + + sls.validate(sb); + ils.validate(ib); + + // string list with integer list type + assertInvalid(ils, sb); + // non list value + assertInvalid(sls, UTF8Type.instance.getSerializer().serialize("foo")); + } + + @Test + public void setSerDerTest() + { + SetSerializer sss = SetType.getInstance(UTF8Type.instance).getSerializer(); + SetSerializer iss = SetType.getInstance(Int32Type.instance).getSerializer(); + + Set ss = new HashSet(){{ add("Foo"); add("Bar"); }}; + Set is = new HashSet(){{ add(3); add(1); add(5); }}; + + ByteBuffer sb = sss.serialize(ss); + ByteBuffer ib = iss.serialize(is); + + assertEquals(sss.deserialize(sb), ss); + assertEquals(iss.deserialize(ib), is); + + sss.validate(sb); + iss.validate(ib); + + // string set with integer set type + assertInvalid(iss, sb); + // non set value + assertInvalid(sss, UTF8Type.instance.getSerializer().serialize("foo")); + } + + @Test + public void setMapDerTest() + { + MapSerializer sms = MapType.getInstance(UTF8Type.instance, UTF8Type.instance).getSerializer(); + MapSerializer ims = MapType.getInstance(Int32Type.instance, Int32Type.instance).getSerializer(); + + Map sm = new HashMap(){{ put("Foo", "xxx"); put("Bar", "yyy"); }}; + Map im = new HashMap(){{ put(3, 0); put(1, 8); put(5, 2); }}; + + ByteBuffer sb = sms.serialize(sm); + ByteBuffer ib = ims.serialize(im); + + assertEquals(sms.deserialize(sb), sm); + assertEquals(ims.deserialize(ib), im); + + sms.validate(sb); + ims.validate(ib); + + // string map with integer map type + assertInvalid(ims, sb); + // non map value + assertInvalid(sms, UTF8Type.instance.getSerializer().serialize("foo")); + + MapSerializer sims = MapType.getInstance(Int32Type.instance, UTF8Type.instance).getSerializer(); + MapSerializer isms = MapType.getInstance(UTF8Type.instance, Int32Type.instance).getSerializer(); + + // only key are invalid + assertInvalid(isms, sb); + // only values are invalid + assertInvalid(sims, sb); + } + + private void assertInvalid(TypeSerializer type, ByteBuffer value) + { + try { + type.validate(value); + fail("Value " + ByteBufferUtil.bytesToHex(value) + " shouldn't be valid for type " + type); + } catch (MarshalException e) { + // ok, that's what we want + } + } }