167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi/* 267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * Copyright (C) 2017 The Android Open Source Project 367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * 467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * Licensed under the Apache License, Version 2.0 (the "License"); 567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * you may not use this file except in compliance with the License. 667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * You may obtain a copy of the License at 767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * 867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * http://www.apache.org/licenses/LICENSE-2.0 967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * 1067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * Unless required by applicable law or agreed to in writing, software 1167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * distributed under the License is distributed on an "AS IS" BASIS, 1267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * See the License for the specific language governing permissions and 1467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi * limitations under the License. 1567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi */ 1667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 1767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichipackage com.android.internal.util; 1867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 1967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichiimport static org.junit.Assert.assertEquals; 20352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shankaimport static org.junit.Assert.assertNull; 2167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichiimport static org.junit.Assert.fail; 2267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 2367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichiimport android.support.test.filters.SmallTest; 2467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichiimport android.support.test.runner.AndroidJUnit4; 2567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 2667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichiimport org.junit.Test; 2767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichiimport org.junit.runner.RunWith; 2867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichiimport java.util.Arrays; 2967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichiimport java.util.Objects; 3067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 3167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 3267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi@SmallTest 3367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi@RunWith(AndroidJUnit4.class) 3467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichipublic class RingBufferTest { 3567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 3667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi @Test 3767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi public void testEmptyRingBuffer() { 3867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi RingBuffer<String> buffer = new RingBuffer<>(String.class, 100); 3967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 4067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(new String[0], buffer.toArray()); 4167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 4267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 4367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi @Test 4467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi public void testIncorrectConstructorArguments() { 4567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi try { 4667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi RingBuffer<String> buffer = new RingBuffer<>(String.class, -10); 4767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi fail("Should not be able to create a negative capacity RingBuffer"); 4867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } catch (IllegalArgumentException expected) { 4967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 5067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 5167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi try { 5267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi RingBuffer<String> buffer = new RingBuffer<>(String.class, 0); 5367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi fail("Should not be able to create a 0 capacity RingBuffer"); 5467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } catch (IllegalArgumentException expected) { 5567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 5667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 5767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 5867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi @Test 5967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi public void testRingBufferWithNoWrapping() { 6067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi RingBuffer<String> buffer = new RingBuffer<>(String.class, 100); 6167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 6267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("a"); 6367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("b"); 6467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("c"); 6567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("d"); 6667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("e"); 6767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 6867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi String[] expected = {"a", "b", "c", "d", "e"}; 6967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(expected, buffer.toArray()); 7067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 7167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 7267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi @Test 7367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi public void testRingBufferWithCapacity1() { 7467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi RingBuffer<String> buffer = new RingBuffer<>(String.class, 1); 7567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 7667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("a"); 7767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(new String[]{"a"}, buffer.toArray()); 7867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 7967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("b"); 8067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(new String[]{"b"}, buffer.toArray()); 8167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 8267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("c"); 8367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(new String[]{"c"}, buffer.toArray()); 8467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 8567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("d"); 8667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(new String[]{"d"}, buffer.toArray()); 8767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 8867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("e"); 8967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(new String[]{"e"}, buffer.toArray()); 9067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 9167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 9267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi @Test 9367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi public void testRingBufferWithWrapping() { 9467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi int capacity = 100; 9567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi RingBuffer<String> buffer = new RingBuffer<>(String.class, capacity); 9667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 9767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("a"); 9867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("b"); 9967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("c"); 10067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("d"); 10167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("e"); 10267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 10367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi String[] expected1 = {"a", "b", "c", "d", "e"}; 10467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(expected1, buffer.toArray()); 10567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 10667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi String[] expected2 = new String[capacity]; 10767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi int firstIndex = 0; 10867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi int lastIndex = capacity - 1; 10967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 11067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi expected2[firstIndex] = "e"; 11167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi for (int i = 1; i < capacity; i++) { 11267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("x"); 11367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi expected2[i] = "x"; 11467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 11567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(expected2, buffer.toArray()); 11667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 11767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("x"); 11867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi expected2[firstIndex] = "x"; 11967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(expected2, buffer.toArray()); 12067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 12167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi for (int i = 0; i < 10; i++) { 12267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi for (String s : expected2) { 12367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append(s); 12467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 12567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 12667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(expected2, buffer.toArray()); 12767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 12867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi buffer.append("a"); 12967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi expected2[lastIndex] = "a"; 13067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi assertArraysEqual(expected2, buffer.toArray()); 13167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 13267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 133352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka @Test 134352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka public void testGetNextSlot() { 135352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka int capacity = 100; 136352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka RingBuffer<DummyClass1> buffer = new RingBuffer<>(DummyClass1.class, capacity); 137352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka 138352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka final DummyClass1[] actual = new DummyClass1[capacity]; 139352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka final DummyClass1[] expected = new DummyClass1[capacity]; 140352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka for (int i = 0; i < capacity; ++i) { 141352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka final DummyClass1 obj = buffer.getNextSlot(); 142352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka obj.x = capacity * i; 143352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka actual[i] = obj; 144352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka expected[i] = new DummyClass1(); 145352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka expected[i].x = capacity * i; 146352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka } 147352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka assertArraysEqual(expected, buffer.toArray()); 148352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka 149352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka for (int i = 0; i < capacity; ++i) { 150352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka if (actual[i] != buffer.getNextSlot()) { 151352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka fail("getNextSlot() should re-use objects if available"); 152352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka } 153352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka } 154352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka 155352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka RingBuffer<DummyClass2> buffer2 = new RingBuffer<>(DummyClass2.class, capacity); 156352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka assertNull("getNextSlot() should return null if the object can't be initiated " 157352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka + "(No nullary constructor)", buffer2.getNextSlot()); 158352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka 159352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka RingBuffer<DummyClass3> buffer3 = new RingBuffer<>(DummyClass3.class, capacity); 160352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka assertNull("getNextSlot() should return null if the object can't be initiated " 161352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka + "(Inaccessible class)", buffer3.getNextSlot()); 162352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka } 163352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka 164352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka public static final class DummyClass1 { 165352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka int x; 166352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka 167352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka public boolean equals(Object o) { 168352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka if (o instanceof DummyClass1) { 169352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka final DummyClass1 other = (DummyClass1) o; 170352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka return other.x == this.x; 171352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka } 172352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka return false; 173352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka } 174352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka } 175352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka 176352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka public static final class DummyClass2 { 177352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka public DummyClass2(int x) {} 178352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka } 179352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka 180352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka private static final class DummyClass3 {} 181352dc57186ff796dbb7a095c609d1a0bae5d3fcaSudheer Shanka 18267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi static <T> void assertArraysEqual(T[] expected, T[] got) { 18367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi if (expected.length != got.length) { 18467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi fail(Arrays.toString(expected) + " and " + Arrays.toString(got) 18567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi + " did not have the same length"); 18667c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 18767c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi 18867c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi for (int i = 0; i < expected.length; i++) { 18967c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi if (!Objects.equals(expected[i], got[i])) { 19067c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi fail(Arrays.toString(expected) + " and " + Arrays.toString(got) 19167c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi + " were not equal"); 19267c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 19367c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 19467c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi } 19567c5e03b54e322a4dab897cbdd36d51ecc007f1eHugo Benichi} 196