blob: b297f6e07c78810e5f09a9b63f6a9d1dc827b1d3 [file] [log] [blame]
Carmelo Cascone6b32c992016-04-13 11:53:09 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Carmelo Cascone6b32c992016-04-13 11:53:09 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onlab.util;
18
19import com.google.common.testing.EqualsTester;
Carmelo Casconeb10194c2017-08-23 19:16:51 +020020import org.junit.Assert;
Brian O'Connoraf1d12e2017-08-17 12:21:48 -070021import org.junit.Rule;
Carmelo Cascone6b32c992016-04-13 11:53:09 -070022import org.junit.Test;
Brian O'Connoraf1d12e2017-08-17 12:21:48 -070023import org.junit.rules.ExpectedException;
Carmelo Cascone6b32c992016-04-13 11:53:09 -070024
25import java.nio.ByteBuffer;
26import java.nio.ByteOrder;
27import java.util.Random;
28
Carmelo Casconeb10194c2017-08-23 19:16:51 +020029import static java.lang.String.format;
Carmelo Cascone6b32c992016-04-13 11:53:09 -070030import static org.hamcrest.MatcherAssert.assertThat;
31import static org.hamcrest.Matchers.equalTo;
32import static org.hamcrest.Matchers.is;
33
34public class ImmutableByteSequenceTest {
Brian O'Connoraf1d12e2017-08-17 12:21:48 -070035 @Rule
36 public ExpectedException thrown = ExpectedException.none();
Carmelo Cascone6b32c992016-04-13 11:53:09 -070037
38 @Test
39 public void testCopy() throws Exception {
40
41 byte byteValue = (byte) 1;
42 short shortValue = (short) byteValue;
43 int intValue = (int) byteValue;
44 long longValue = (long) byteValue;
45 byte[] arrayValue = new byte[64];
46 arrayValue[63] = byteValue;
47 ByteBuffer bufferValue = ByteBuffer.allocate(64).put(arrayValue);
48
49 ImmutableByteSequence bsByte = ImmutableByteSequence.copyFrom(byteValue);
50 ImmutableByteSequence bsShort = ImmutableByteSequence.copyFrom(shortValue);
51 ImmutableByteSequence bsInt = ImmutableByteSequence.copyFrom(intValue);
52 ImmutableByteSequence bsLong = ImmutableByteSequence.copyFrom(longValue);
53 ImmutableByteSequence bsArray = ImmutableByteSequence.copyFrom(arrayValue);
54 ImmutableByteSequence bsBuffer = ImmutableByteSequence.copyFrom(bufferValue);
55
56 assertThat("byte sequence of a byte value must have size 1",
57 bsByte.size(), is(equalTo(1)));
58 assertThat("byte sequence of a short value must have size 2",
59 bsShort.size(), is(equalTo(2)));
60 assertThat("byte sequence of an int value must have size 4",
61 bsInt.size(), is(equalTo(4)));
62 assertThat("byte sequence of a long value must have size 8",
63 bsLong.size(), is(equalTo(8)));
64 assertThat("byte sequence of a byte array value must have same size of the array",
65 bsArray.size(), is(equalTo(arrayValue.length)));
66 assertThat("byte sequence of a byte buffer value must have same size of the buffer",
67 bsBuffer.size(), is(equalTo(bufferValue.capacity())));
68
69 String errStr = "incorrect byte sequence value";
70
71 assertThat(errStr, bsByte.asArray()[0], is(equalTo(byteValue)));
72 assertThat(errStr, bsShort.asArray()[1], is(equalTo(byteValue)));
73 assertThat(errStr, bsInt.asArray()[3], is(equalTo(byteValue)));
74 assertThat(errStr, bsLong.asArray()[7], is(equalTo(byteValue)));
75 assertThat(errStr, bsArray.asArray()[63], is(equalTo(byteValue)));
76 assertThat(errStr, bsBuffer.asArray()[63], is(equalTo(byteValue)));
77 }
78
79 @Test
80 public void testEndianness() throws Exception {
81
82 long longValue = new Random().nextLong();
83
84 // creates a new sequence from a big-endian buffer
85 ByteBuffer bbBigEndian = ByteBuffer
86 .allocate(8)
87 .order(ByteOrder.BIG_ENDIAN)
88 .putLong(longValue);
89 ImmutableByteSequence bsBufferCopyBigEndian =
90 ImmutableByteSequence.copyFrom(bbBigEndian);
91
92 // creates a new sequence from a little-endian buffer
93 ByteBuffer bbLittleEndian = ByteBuffer
94 .allocate(8)
95 .order(ByteOrder.LITTLE_ENDIAN)
96 .putLong(longValue);
97 ImmutableByteSequence bsBufferCopyLittleEndian =
98 ImmutableByteSequence.copyFrom(bbLittleEndian);
99
100 // creates a new sequence from primitive type
101 ImmutableByteSequence bsLongCopy =
102 ImmutableByteSequence.copyFrom(longValue);
103
104
105 new EqualsTester()
106 // big-endian byte array cannot be equal to little-endian array
107 .addEqualityGroup(bbBigEndian.array())
108 .addEqualityGroup(bbLittleEndian.array())
109 // all byte sequences must be equal
110 .addEqualityGroup(bsBufferCopyBigEndian,
111 bsBufferCopyLittleEndian,
112 bsLongCopy)
113 // byte buffer views of all sequences must be equal
114 .addEqualityGroup(bsBufferCopyBigEndian.asReadOnlyBuffer(),
115 bsBufferCopyLittleEndian.asReadOnlyBuffer(),
116 bsLongCopy.asReadOnlyBuffer())
117 // byte buffer orders of all sequences must be ByteOrder.BIG_ENDIAN
118 .addEqualityGroup(bsBufferCopyBigEndian.asReadOnlyBuffer().order(),
119 bsBufferCopyLittleEndian.asReadOnlyBuffer().order(),
120 bsLongCopy.asReadOnlyBuffer().order(),
121 ByteOrder.BIG_ENDIAN)
122 .testEquals();
123 }
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700124
125 @Test
126 public void testBitSetMethods() throws Exception {
127 // All zeros tests
128 assertThat("3 bytes, all 0's",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200129 ImmutableByteSequence.ofZeros(3),
130 is(equalTo(ImmutableByteSequence.copyFrom(
131 new byte[]{0, 0, 0}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700132 assertThat("3 bytes, all 0's via prefix",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200133 ImmutableByteSequence.prefixZeros(3, 3 * Byte.SIZE),
134 is(equalTo(ImmutableByteSequence.copyFrom(
135 new byte[]{0, 0, 0}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700136
137 // All ones tests
138 assertThat("3 bytes, all 1's",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200139 ImmutableByteSequence.ofZeros(3),
140 is(equalTo(ImmutableByteSequence.copyFrom(
141 new byte[]{0, 0, 0}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700142 assertThat("3 bytes, all 1's via prefix",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200143 ImmutableByteSequence.prefixOnes(3, 3 * Byte.SIZE),
144 is(equalTo(ImmutableByteSequence.copyFrom(
145 new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700146
147 // Zero prefix tests
148 assertThat("2 bytes, prefixed with 5 0's",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200149 ImmutableByteSequence.prefix(2, 5, (byte) 0),
150 is(equalTo(ImmutableByteSequence.copyFrom(
151 new byte[]{(byte) 0x7, (byte) 0xff}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700152 assertThat("4 bytes, prefixed with 16 0's",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200153 ImmutableByteSequence.prefix(4, 16, (byte) 0),
154 is(equalTo(ImmutableByteSequence.copyFrom(
155 new byte[]{0, 0, (byte) 0xff, (byte) 0xff}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700156 assertThat("4 bytes, prefixed with 20 0's",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200157 ImmutableByteSequence.prefix(4, 20, (byte) 0),
158 is(equalTo(ImmutableByteSequence.copyFrom(
159 new byte[]{0, 0, (byte) 0x0f, (byte) 0xff}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700160 assertThat("8 bytes, prefixed with 36 0's",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200161 ImmutableByteSequence.prefixZeros(8, 38),
162 is(equalTo(ImmutableByteSequence.copyFrom(
163 new byte[]{0, 0, 0, 0, (byte) 0x03, (byte) 0xff, (byte) 0xff, (byte) 0xff}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700164
165 // Ones prefix tests
166 assertThat("2 bytes, prefixed with 5 1's",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200167 ImmutableByteSequence.prefix(2, 5, (byte) 0xff),
168 is(equalTo(ImmutableByteSequence.copyFrom(
169 new byte[]{(byte) 0xf8, 0}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700170 assertThat("4 bytes, prefixed with 16 1's",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200171 ImmutableByteSequence.prefix(4, 16, (byte) 0xff),
172 is(equalTo(ImmutableByteSequence.copyFrom(
173 new byte[]{(byte) 0xff, (byte) 0xff, 0, 0}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700174 assertThat("4 bytes, prefixed with 20 1's",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200175 ImmutableByteSequence.prefix(4, 20, (byte) 0xff),
176 is(equalTo(ImmutableByteSequence.copyFrom(
177 new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xf0, 0}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700178 assertThat("8 bytes, prefixed with 10 1's",
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200179 ImmutableByteSequence.prefixOnes(8, 10),
180 is(equalTo(ImmutableByteSequence.copyFrom(
181 new byte[]{(byte) 0xff, (byte) 0xc0, 0, 0, 0, 0, 0, 0}))));
Brian O'Connoraf1d12e2017-08-17 12:21:48 -0700182 }
183
184 @Test
185 public void testBadPrefixVal() {
186 thrown.expect(IllegalArgumentException.class);
187 thrown.reportMissingExceptionWithMessage(
188 "Expect IllegalArgumentException due to val = 0x7");
189 ImmutableByteSequence.prefix(5, 10, (byte) 0x7);
190 }
Carmelo Casconeb10194c2017-08-23 19:16:51 +0200191
192 @Test
193 public void testMsbIndex() {
194 assertThat("Value 0 should have MSB index -1",
195 ImmutableByteSequence.copyFrom(0).msbIndex(), is(-1));
196 for (int i = 0; i < 63; i++) {
197 long value = (long) Math.pow(2, i);
198 assertThat(format("Value %d should have MSB index %d", value, i),
199 ImmutableByteSequence.copyFrom(value).msbIndex(), is(i));
200 }
201 }
202
203 private void checkIllegalFit(ImmutableByteSequence bytes, int bitWidth) {
204 try {
205 ImmutableByteSequence.fit(bytes, bitWidth);
206 Assert.fail(format("Except ByteSequenceTrimException due to value = %s and bitWidth %d",
207 bytes.toString(), bitWidth));
208 } catch (ImmutableByteSequence.ByteSequenceTrimException e) {
209 // We expect this.
210 }
211 }
212
213 private void checkLegalFit(ImmutableByteSequence bytes, int bitWidth)
214 throws ImmutableByteSequence.ByteSequenceTrimException {
215 ImmutableByteSequence fitBytes = ImmutableByteSequence.fit(bytes, bitWidth);
216 ImmutableByteSequence sameBytes = ImmutableByteSequence.fit(fitBytes, bytes.size() * 8);
217 assertThat(format("Fitted value %s (re-extended to %s) not equal to original value %s",
218 fitBytes, sameBytes, bytes),
219 sameBytes,
220 is(equalTo(bytes)));
221 }
222
223 @Test
224 public void testFit() throws ImmutableByteSequence.ByteSequenceTrimException {
225 // Test fit by forcing a given MSB index.
226 for (int msbIndex = 0; msbIndex < 32; msbIndex++) {
227 long value = (long) Math.pow(2, msbIndex);
228 ImmutableByteSequence bytes = ImmutableByteSequence.copyFrom(value);
229 checkLegalFit(bytes, msbIndex + 1);
230 if (msbIndex != 0) {
231 checkIllegalFit(bytes, msbIndex);
232 }
233 }
234 }
235
236 @Test
237 public void testRandomFit() throws ImmutableByteSequence.ByteSequenceTrimException {
238 // Test fit against the computed MSB index.
239 Random random = new Random();
240 for (int i = 0; i < 1000; i++) {
241 ImmutableByteSequence bytes = ImmutableByteSequence.copyFrom((long) Math.abs(random.nextInt()));
242 int msbIndex = bytes.msbIndex();
243 checkIllegalFit(bytes, msbIndex - random.nextInt(16));
244 checkLegalFit(bytes, msbIndex + 2 + random.nextInt(16));
245 checkLegalFit(bytes, msbIndex + 1);
246 }
247 }
Carmelo Cascone6b32c992016-04-13 11:53:09 -0700248}