Skip to content

Commit 6422932

Browse files
committed
add a ton of unit tests
1 parent d2ff145 commit 6422932

File tree

7 files changed

+288
-98
lines changed

7 files changed

+288
-98
lines changed

core/src/main/java/com/datastax/oss/driver/api/core/data/CqlVector.java

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@
1818
package com.datastax.oss.driver.api.core.data;
1919

2020
import com.datastax.oss.driver.api.core.type.codec.TypeCodec;
21+
import com.datastax.oss.driver.internal.core.type.codec.ParseUtils;
2122
import com.datastax.oss.driver.shaded.guava.common.base.Preconditions;
2223
import com.datastax.oss.driver.shaded.guava.common.base.Predicates;
23-
import com.datastax.oss.driver.shaded.guava.common.base.Splitter;
2424
import com.datastax.oss.driver.shaded.guava.common.collect.Iterables;
25-
import com.datastax.oss.driver.shaded.guava.common.collect.Streams;
2625
import edu.umd.cs.findbugs.annotations.NonNull;
2726
import java.io.IOException;
2827
import java.io.InvalidObjectException;
@@ -35,7 +34,6 @@
3534
import java.util.Iterator;
3635
import java.util.List;
3736
import java.util.Objects;
38-
import java.util.stream.Collectors;
3937
import java.util.stream.Stream;
4038

4139
/**
@@ -90,11 +88,48 @@ public static <V> CqlVector<V> newInstance(List<V> list) {
9088
public static <V> CqlVector<V> from(@NonNull String str, @NonNull TypeCodec<V> subtypeCodec) {
9189
Preconditions.checkArgument(str != null, "Cannot create CqlVector from null string");
9290
Preconditions.checkArgument(!str.isEmpty(), "Cannot create CqlVector from empty string");
93-
ArrayList<V> vals =
94-
Streams.stream(Splitter.on(", ").split(str.substring(1, str.length() - 1)))
95-
.map(subtypeCodec::parse)
96-
.collect(Collectors.toCollection(ArrayList::new));
97-
return new CqlVector(vals);
91+
if (str == null || str.isEmpty() || str.equalsIgnoreCase("NULL")) return null;
92+
93+
int idx = ParseUtils.skipSpaces(str, 0);
94+
if (str.charAt(idx++) != '[')
95+
throw new IllegalArgumentException(
96+
String.format(
97+
"Cannot parse list value from \"%s\", at character %d expecting '[' but got '%c'",
98+
str, idx, str.charAt(idx)));
99+
100+
idx = ParseUtils.skipSpaces(str, idx);
101+
102+
if (str.charAt(idx) == ']') {
103+
return null;
104+
}
105+
106+
List<V> list = new ArrayList<>();
107+
while (idx < str.length()) {
108+
int n;
109+
try {
110+
n = ParseUtils.skipCQLValue(str, idx);
111+
} catch (IllegalArgumentException e) {
112+
throw new IllegalArgumentException(
113+
String.format(
114+
"Cannot parse list value from \"%s\", invalid CQL value at character %d", str, idx),
115+
e);
116+
}
117+
118+
list.add(subtypeCodec.parse(str.substring(idx, n)));
119+
idx = n;
120+
121+
idx = ParseUtils.skipSpaces(str, idx);
122+
if (str.charAt(idx) == ']') return new CqlVector<>(list);
123+
if (str.charAt(idx++) != ',')
124+
throw new IllegalArgumentException(
125+
String.format(
126+
"Cannot parse list value from \"%s\", at character %d expecting ',' but got '%c'",
127+
str, idx, str.charAt(idx)));
128+
129+
idx = ParseUtils.skipSpaces(str, idx);
130+
}
131+
throw new IllegalArgumentException(
132+
String.format("Malformed list value \"%s\", missing closing ']'", str));
98133
}
99134

100135
private final List<T> list;

core/src/main/java/com/datastax/oss/driver/api/core/type/DataTypes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import com.datastax.oss.protocol.internal.ProtocolConstants;
3333
import edu.umd.cs.findbugs.annotations.NonNull;
3434
import java.util.Arrays;
35-
import java.util.List;
3635

3736
/** Constants and factory methods to obtain data type instances. */
3837
public class DataTypes {
@@ -69,7 +68,8 @@ public static DataType custom(@NonNull String className) {
6968

7069
/* Vector support is currently implemented as a custom type but is also parameterized */
7170
if (className.startsWith(DefaultVectorType.VECTOR_CLASS_NAME)) {
72-
String paramsString = className.substring(
71+
String paramsString =
72+
className.substring(
7373
DefaultVectorType.VECTOR_CLASS_NAME.length() + 1, className.length() - 1);
7474
int lastCommaIndex = paramsString.lastIndexOf(',');
7575
if (lastCommaIndex == -1) {

core/src/main/java/com/datastax/oss/driver/internal/core/type/DefaultVectorType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public String getClassName() {
6161
@Override
6262
public String asCql(boolean includeFrozen, boolean pretty) {
6363
return String.format(
64-
"VECTOR<%s, %d>", this.subtype.asCql(includeFrozen, pretty).toUpperCase(), getDimensions());
64+
"VECTOR<%s, %d>", this.subtype.asCql(includeFrozen, pretty).toLowerCase(), getDimensions());
6565
}
6666

6767
/* ============== General class implementation ============== */

core/src/main/java/com/datastax/oss/driver/internal/core/type/codec/VectorCodec.java

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,9 @@
2626
import com.datastax.oss.driver.internal.core.type.DefaultVectorType;
2727
import com.datastax.oss.driver.internal.core.type.util.VIntCoding;
2828
import com.datastax.oss.driver.shaded.guava.common.base.Optional;
29-
import com.datastax.oss.driver.shaded.guava.common.collect.Iterables;
3029
import edu.umd.cs.findbugs.annotations.NonNull;
3130
import edu.umd.cs.findbugs.annotations.Nullable;
32-
33-
import java.net.InetAddress;
3431
import java.nio.ByteBuffer;
35-
import java.time.Instant;
36-
import java.time.LocalDate;
37-
import java.time.LocalTime;
3832
import java.util.ArrayList;
3933
import java.util.Iterator;
4034
import java.util.List;
@@ -71,8 +65,10 @@ public GenericType<CqlVector<SubtypeT>> getJavaType() {
7165
}
7266

7367
@NonNull
74-
public Optional<Integer> serializedSize(){
75-
return subtypeCodec.serializedSize().isPresent() ? Optional.of(subtypeCodec.serializedSize().get() * cqlType.getDimensions()) : Optional.absent();
68+
public Optional<Integer> serializedSize() {
69+
return subtypeCodec.serializedSize().isPresent()
70+
? Optional.of(subtypeCodec.serializedSize().get() * cqlType.getDimensions())
71+
: Optional.absent();
7672
}
7773

7874
@NonNull
@@ -110,9 +106,7 @@ public CqlVector<SubtypeT> decode(
110106
public String format(CqlVector<SubtypeT> value) {
111107
if (value == null) return "NULL";
112108

113-
return value.stream()
114-
.map(subtypeCodec::format)
115-
.collect(Collectors.joining(", ", "[", "]"));
109+
return value.stream().map(subtypeCodec::format).collect(Collectors.joining(", ", "[", "]"));
116110
}
117111

118112
@Nullable
@@ -166,6 +160,13 @@ public ByteBuffer encode(
166160
valueBuff.rewind();
167161
valueBuffs[i] = valueBuff;
168162
}
163+
// if too many elements, throw
164+
if (values.hasNext()) {
165+
throw new IllegalArgumentException(
166+
String.format(
167+
"Too many elements; must provide elements for %d dimensions",
168+
cqlType.getDimensions()));
169+
}
169170
/* Since we already did an early return for <= 0 dimensions above */
170171
assert valueBuffs.length > 0;
171172
ByteBuffer rv = ByteBuffer.allocate(allValueBuffsSize);
@@ -183,8 +184,8 @@ public CqlVector<SubtypeT> decode(
183184
return null;
184185
}
185186

186-
int elementSize = Math.floorDiv(bytes.remaining(), cqlType.getDimensions());
187-
if (!(bytes.remaining() % cqlType.getDimensions() == 0)) {
187+
int elementSize = subtypeCodec.serializedSize().get();
188+
if (bytes.remaining() != cqlType.getDimensions() * elementSize) {
188189
throw new IllegalArgumentException(
189190
String.format(
190191
"Expected elements of uniform size, observed %d elements with total bytes %d",
@@ -252,6 +253,15 @@ public ByteBuffer encode(
252253
valueBuff.rewind();
253254
valueBuffs[i] = valueBuff;
254255
}
256+
257+
// if too many elements, throw
258+
if (values.hasNext()) {
259+
throw new IllegalArgumentException(
260+
String.format(
261+
"Too many elements; must provide elements for %d dimensions",
262+
cqlType.getDimensions()));
263+
}
264+
255265
/* Since we already did an early return for <= 0 dimensions above */
256266
assert valueBuffs.length > 0;
257267
ByteBuffer rv = ByteBuffer.allocate(allValueBuffsSize);
@@ -286,6 +296,13 @@ public CqlVector<SubtypeT> decode(
286296
}
287297
rv.add(subtypeCodec.decode(value, protocolVersion));
288298
}
299+
// if too many elements, throw
300+
if (input.hasRemaining()) {
301+
throw new IllegalArgumentException(
302+
String.format(
303+
"Too many elements; must provide elements for %d dimensions",
304+
cqlType.getDimensions()));
305+
}
289306

290307
return CqlVector.newInstance(rv);
291308
}

0 commit comments

Comments
 (0)