1+ /*
2+ * Licensed to the Apache Software Foundation (ASF) under one
3+ * or more contributor license agreements. See the NOTICE file
4+ * distributed with this work for additional information
5+ * regarding copyright ownership. The ASF licenses this file
6+ * to you under the Apache License, Version 2.0 (the
7+ * "License"); you may not use this file except in compliance
8+ * with the License. You may obtain a copy of the License at
9+ *
10+ * http://www.apache.org/licenses/LICENSE-2.0
11+ *
12+ * Unless required by applicable law or agreed to in writing, software
13+ * distributed under the License is distributed on an "AS IS" BASIS,
14+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+ * See the License for the specific language governing permissions and
16+ * limitations under the License.
17+ */
18+
19+ package org .apache .cassandra .service .accord .serializers ;
20+
21+ import java .io .IOException ;
22+ import java .util .Arrays ;
23+
24+ import accord .utils .Gens ;
25+ import org .junit .Test ;
26+
27+ import accord .utils .Gen ;
28+ import org .apache .cassandra .db .TypeSizes ;
29+ import org .apache .cassandra .io .Serializers ;
30+ import org .apache .cassandra .io .UnversionedSerializer ;
31+ import org .apache .cassandra .io .util .DataInputPlus ;
32+ import org .apache .cassandra .io .util .DataOutputBuffer ;
33+ import org .apache .cassandra .io .util .DataOutputPlus ;
34+ import org .assertj .core .api .Assertions ;
35+
36+ import static accord .utils .Property .qt ;
37+
38+ public class SerializePackedTest
39+ {
40+ private static final Gen <int []> zeros = rs -> new int [rs .nextInt (0 , 10 )];
41+ private static final Gen <int []> randomZeroAndPositive = array (rs -> rs .nextInt (-1 , Integer .MAX_VALUE ) + 1 );
42+ private static final Gen <int []> randomZeroAndPositiveSmall = array (rs -> rs .nextInt (0 , 1 << 8 ));
43+ private static final Gen <int []> negatives = array (Gens .ints ().between (Integer .MIN_VALUE , -1 ), rs -> rs .nextInt (1 , 10 ));
44+
45+ private static final Gen <int []> monotonic = rs -> {
46+ int [] array = new int [rs .nextInt (0 , 10 )];
47+ for (int i = 0 ; i < array .length ; i ++)
48+ array [i ] = i ;
49+ return array ;
50+ };
51+
52+ private static final Gen <int []> zeroAndPositive = rs -> {
53+ if (rs .decide (0.2f )) return monotonic .next (rs );
54+ return randomZeroAndPositive .next (rs );
55+ };
56+
57+ private static final Gen <int []> zeroAndPositiveSmall = rs -> {
58+ if (rs .decide (0.2f )) return monotonic .next (rs );
59+ return randomZeroAndPositiveSmall .next (rs );
60+ };
61+
62+ private static Gen <int []> array (Gen .IntGen valueGen )
63+ {
64+ return array (valueGen , rs -> rs .nextInt (0 , 10 ));
65+ }
66+
67+ private static Gen <int []> array (Gen .IntGen valueGen , Gen .IntGen size )
68+ {
69+ return rs -> {
70+ int [] array = new int [size .nextInt (rs )];
71+ for (int i = 0 ; i < array .length ; i ++)
72+ array [i ] = valueGen .nextInt (rs );
73+ Arrays .sort (array );
74+ return array ;
75+ };
76+ }
77+
78+ @ Test
79+ public void serde ()
80+ {
81+ @ SuppressWarnings ({ "resource" , "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer ();
82+ qt ().forAll (zeroAndPositive ).check (array -> Serializers .testSerde (output , PackedSortedSerializer .instance , array ));
83+ }
84+
85+ @ Test
86+ public void serdeNegative ()
87+ {
88+ @ SuppressWarnings ({ "resource" , "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer ();
89+ qt ().forAll (negatives ).check (array -> {
90+ output .clear ();
91+ Assertions .assertThatThrownBy (() -> PackedSortedSerializer .instance .serialize (array , output ))
92+ .isInstanceOf (IllegalStateException .class )
93+ .hasMessageContaining ("Found a negative value at offset" );
94+ });
95+ }
96+
97+ @ Test
98+ public void serdeZeros ()
99+ {
100+ @ SuppressWarnings ({ "resource" , "IOResourceOpenedButNotSafelyClosed" }) DataOutputBuffer output = new DataOutputBuffer ();
101+ qt ().forAll (zeros ).check (array -> Serializers .testSerde (output , PackedSortedSerializer .instance , array ));
102+ }
103+
104+ @ Test
105+ public void serializerIsSmallerThanSimpleList ()
106+ {
107+ qt ().forAll (zeroAndPositiveSmall ).check (array -> {
108+ var list = SimpleListSerializer .instance .serialize (array );
109+ var packed = PackedSortedSerializer .instance .serialize (array );
110+
111+ Assertions .assertThat (packed .remaining ()).isLessThanOrEqualTo (list .remaining ());
112+ });
113+ }
114+
115+ public static class PackedSortedSerializer implements UnversionedSerializer <int []>
116+ {
117+ public static final PackedSortedSerializer instance = new PackedSortedSerializer ();
118+
119+ @ Override
120+ public void serialize (int [] t , DataOutputPlus out ) throws IOException
121+ {
122+ SerializePacked .serializePackedSortedIntsAndLength (t , out );
123+ }
124+
125+ @ Override
126+ public int [] deserialize (DataInputPlus in ) throws IOException
127+ {
128+ return SerializePacked .deserializePackedSortedIntsAndLength (in );
129+ }
130+
131+ @ Override
132+ public long serializedSize (int [] t )
133+ {
134+ return SerializePacked .serializedSizeOfPackedSortedIntsAndLength (t );
135+ }
136+ }
137+
138+ public static class SimpleListSerializer implements UnversionedSerializer <int []>
139+ {
140+ public static final SimpleListSerializer instance = new SimpleListSerializer ();
141+
142+ @ Override
143+ public void serialize (int [] t , DataOutputPlus out ) throws IOException
144+ {
145+ out .writeUnsignedVInt32 (t .length );
146+ for (int i : t )
147+ out .writeVInt32 (i );
148+ }
149+
150+ @ Override
151+ public int [] deserialize (DataInputPlus in ) throws IOException
152+ {
153+ int size = in .readUnsignedVInt32 ();
154+ int [] array = new int [size ];
155+ for (int i = 0 ; i < size ; i ++)
156+ array [i ] = in .readVInt32 ();
157+ return array ;
158+ }
159+
160+ @ Override
161+ public long serializedSize (int [] t )
162+ {
163+ long size = TypeSizes .sizeofUnsignedVInt (t .length );
164+ for (int i = 0 ; i < t .length ; i ++)
165+ size += TypeSizes .sizeofVInt (t [i ]);
166+ return size ;
167+ }
168+ }
169+ }
0 commit comments