1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
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 
17 package com.android.internal.util;
18 
19 import static com.android.internal.util.BitUtils.bytesToBEInt;
20 import static com.android.internal.util.BitUtils.bytesToLEInt;
21 import static com.android.internal.util.BitUtils.getUint16;
22 import static com.android.internal.util.BitUtils.getUint32;
23 import static com.android.internal.util.BitUtils.getUint8;
24 import static com.android.internal.util.BitUtils.packBits;
25 import static com.android.internal.util.BitUtils.uint16;
26 import static com.android.internal.util.BitUtils.uint32;
27 import static com.android.internal.util.BitUtils.uint8;
28 import static com.android.internal.util.BitUtils.unpackBits;
29 
30 import static org.junit.Assert.assertEquals;
31 import static org.junit.Assert.assertTrue;
32 
33 import android.os.Build;
34 
35 import androidx.test.filters.SmallTest;
36 
37 import com.android.testutils.DevSdkIgnoreRule;
38 import com.android.testutils.DevSdkIgnoreRunner;
39 
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 
43 import java.nio.ByteBuffer;
44 import java.util.Arrays;
45 import java.util.Random;
46 
47 @SmallTest
48 @RunWith(DevSdkIgnoreRunner.class)
49 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
50 public class BitUtilsTest {
51 
52     @Test
53     public void testUnsignedByteWideningConversions() {
54         byte b0 = 0;
55         byte b1 = 1;
56         byte bm1 = -1;
57         assertEquals(0, uint8(b0));
58         assertEquals(1, uint8(b1));
59         assertEquals(127, uint8(Byte.MAX_VALUE));
60         assertEquals(128, uint8(Byte.MIN_VALUE));
61         assertEquals(255, uint8(bm1));
62         assertEquals(255, uint8((byte)255));
63     }
64 
65     @Test
66     public void testUnsignedShortWideningConversions() {
67         short s0 = 0;
68         short s1 = 1;
69         short sm1 = -1;
70         assertEquals(0, uint16(s0));
71         assertEquals(1, uint16(s1));
72         assertEquals(32767, uint16(Short.MAX_VALUE));
73         assertEquals(32768, uint16(Short.MIN_VALUE));
74         assertEquals(65535, uint16(sm1));
75         assertEquals(65535, uint16((short)65535));
76     }
77 
78     @Test
79     public void testUnsignedShortComposition() {
80         byte b0 = 0;
81         byte b1 = 1;
82         byte b2 = 2;
83         byte b10 = 10;
84         byte b16 = 16;
85         byte b128 = -128;
86         byte b224 = -32;
87         byte b255 = -1;
88         assertEquals(0x0000, uint16(b0, b0));
89         assertEquals(0xffff, uint16(b255, b255));
90         assertEquals(0x0a01, uint16(b10, b1));
91         assertEquals(0x8002, uint16(b128, b2));
92         assertEquals(0x01ff, uint16(b1, b255));
93         assertEquals(0x80ff, uint16(b128, b255));
94         assertEquals(0xe010, uint16(b224, b16));
95     }
96 
97     @Test
98     public void testUnsignedIntWideningConversions() {
99         assertEquals(0, uint32(0));
100         assertEquals(1, uint32(1));
101         assertEquals(2147483647L, uint32(Integer.MAX_VALUE));
102         assertEquals(2147483648L, uint32(Integer.MIN_VALUE));
103         assertEquals(4294967295L, uint32(-1));
104         assertEquals(4294967295L, uint32((int)4294967295L));
105     }
106 
107     @Test
108     public void testBytesToInt() {
109         assertEquals(0x00000000, bytesToBEInt(bytes(0, 0, 0, 0)));
110         assertEquals(0xffffffff, bytesToBEInt(bytes(255, 255, 255, 255)));
111         assertEquals(0x0a000001, bytesToBEInt(bytes(10, 0, 0, 1)));
112         assertEquals(0x0a000002, bytesToBEInt(bytes(10, 0, 0, 2)));
113         assertEquals(0x0a001fff, bytesToBEInt(bytes(10, 0, 31, 255)));
114         assertEquals(0xe0000001, bytesToBEInt(bytes(224, 0, 0, 1)));
115 
116         assertEquals(0x00000000, bytesToLEInt(bytes(0, 0, 0, 0)));
117         assertEquals(0x01020304, bytesToLEInt(bytes(4, 3, 2, 1)));
118         assertEquals(0xffff0000, bytesToLEInt(bytes(0, 0, 255, 255)));
119     }
120 
121     @Test
122     public void testUnsignedGetters() {
123         ByteBuffer b = ByteBuffer.allocate(4);
124         b.putInt(0xffff);
125 
126         assertEquals(0x0, getUint8(b, 0));
127         assertEquals(0x0, getUint8(b, 1));
128         assertEquals(0xff, getUint8(b, 2));
129         assertEquals(0xff, getUint8(b, 3));
130 
131         assertEquals(0x0, getUint16(b, 0));
132         assertEquals(0xffff, getUint16(b, 2));
133 
134         b.rewind();
135         b.putInt(0xffffffff);
136         assertEquals(0xffffffffL, getUint32(b, 0));
137     }
138 
139     @Test
140     public void testBitsPacking() {
141         BitPackingTestCase[] testCases = {
142             new BitPackingTestCase(0, ints()),
143             new BitPackingTestCase(1, ints(0)),
144             new BitPackingTestCase(2, ints(1)),
145             new BitPackingTestCase(3, ints(0, 1)),
146             new BitPackingTestCase(4, ints(2)),
147             new BitPackingTestCase(6, ints(1, 2)),
148             new BitPackingTestCase(9, ints(0, 3)),
149             new BitPackingTestCase(~Long.MAX_VALUE, ints(63)),
150             new BitPackingTestCase(~Long.MAX_VALUE + 1, ints(0, 63)),
151             new BitPackingTestCase(~Long.MAX_VALUE + 2, ints(1, 63)),
152         };
153         for (BitPackingTestCase tc : testCases) {
154             int[] got = unpackBits(tc.packedBits);
155             assertTrue(
156                     "unpackBits("
157                             + tc.packedBits
158                             + "): expected "
159                             + Arrays.toString(tc.bits)
160                             + " but got "
161                             + Arrays.toString(got),
162                     Arrays.equals(tc.bits, got));
163         }
164         for (BitPackingTestCase tc : testCases) {
165             long got = packBits(tc.bits);
166             assertEquals(
167                     "packBits("
168                             + Arrays.toString(tc.bits)
169                             + "): expected "
170                             + tc.packedBits
171                             + " but got "
172                             + got,
173                     tc.packedBits,
174                     got);
175         }
176 
177         long[] moreTestCases = {
178             0, 1, -1, 23895, -908235, Long.MAX_VALUE, Long.MIN_VALUE, new Random().nextLong(),
179         };
180         for (long l : moreTestCases) {
181             assertEquals(l, packBits(unpackBits(l)));
182         }
183     }
184 
185     static byte[] bytes(int b1, int b2, int b3, int b4) {
186         return new byte[] {b(b1), b(b2), b(b3), b(b4)};
187     }
188 
189     static byte b(int i) {
190         return (byte) i;
191     }
192 
193     static int[] ints(int... array) {
194         return array;
195     }
196 
197     static class BitPackingTestCase {
198         final int[] bits;
199         final long packedBits;
200 
201         BitPackingTestCase(long packedBits, int[] bits) {
202             this.bits = bits;
203             this.packedBits = packedBits;
204         }
205     }
206 }
207