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 org.junit.Assert.assertNull; 20 import static org.junit.Assert.fail; 21 22 import androidx.test.filters.SmallTest; 23 import androidx.test.runner.AndroidJUnit4; 24 25 import org.junit.Test; 26 import org.junit.runner.RunWith; 27 28 import java.util.Arrays; 29 import java.util.Objects; 30 31 @SmallTest 32 @RunWith(AndroidJUnit4.class) 33 public class RingBufferTest { 34 35 @Test testEmptyRingBuffer()36 public void testEmptyRingBuffer() { 37 RingBuffer<String> buffer = new RingBuffer<>(String.class, 100); 38 39 assertArraysEqual(new String[0], buffer.toArray()); 40 } 41 42 @Test testIncorrectConstructorArguments()43 public void testIncorrectConstructorArguments() { 44 try { 45 RingBuffer<String> buffer = new RingBuffer<>(String.class, -10); 46 fail("Should not be able to create a negative capacity RingBuffer"); 47 } catch (IllegalArgumentException expected) { 48 } 49 50 try { 51 RingBuffer<String> buffer = new RingBuffer<>(String.class, 0); 52 fail("Should not be able to create a 0 capacity RingBuffer"); 53 } catch (IllegalArgumentException expected) { 54 } 55 } 56 57 @Test testRingBufferWithNoWrapping()58 public void testRingBufferWithNoWrapping() { 59 RingBuffer<String> buffer = new RingBuffer<>(String.class, 100); 60 61 buffer.append("a"); 62 buffer.append("b"); 63 buffer.append("c"); 64 buffer.append("d"); 65 buffer.append("e"); 66 67 String[] expected = {"a", "b", "c", "d", "e"}; 68 assertArraysEqual(expected, buffer.toArray()); 69 } 70 71 @Test testRingBufferWithCapacity1()72 public void testRingBufferWithCapacity1() { 73 RingBuffer<String> buffer = new RingBuffer<>(String.class, 1); 74 75 buffer.append("a"); 76 assertArraysEqual(new String[]{"a"}, buffer.toArray()); 77 78 buffer.append("b"); 79 assertArraysEqual(new String[]{"b"}, buffer.toArray()); 80 81 buffer.append("c"); 82 assertArraysEqual(new String[]{"c"}, buffer.toArray()); 83 84 buffer.append("d"); 85 assertArraysEqual(new String[]{"d"}, buffer.toArray()); 86 87 buffer.append("e"); 88 assertArraysEqual(new String[]{"e"}, buffer.toArray()); 89 } 90 91 @Test testRingBufferWithWrapping()92 public void testRingBufferWithWrapping() { 93 int capacity = 100; 94 RingBuffer<String> buffer = new RingBuffer<>(String.class, capacity); 95 96 buffer.append("a"); 97 buffer.append("b"); 98 buffer.append("c"); 99 buffer.append("d"); 100 buffer.append("e"); 101 102 String[] expected1 = {"a", "b", "c", "d", "e"}; 103 assertArraysEqual(expected1, buffer.toArray()); 104 105 String[] expected2 = new String[capacity]; 106 int firstIndex = 0; 107 int lastIndex = capacity - 1; 108 109 expected2[firstIndex] = "e"; 110 for (int i = 1; i < capacity; i++) { 111 buffer.append("x"); 112 expected2[i] = "x"; 113 } 114 assertArraysEqual(expected2, buffer.toArray()); 115 116 buffer.append("x"); 117 expected2[firstIndex] = "x"; 118 assertArraysEqual(expected2, buffer.toArray()); 119 120 for (int i = 0; i < 10; i++) { 121 for (String s : expected2) { 122 buffer.append(s); 123 } 124 } 125 assertArraysEqual(expected2, buffer.toArray()); 126 127 buffer.append("a"); 128 expected2[lastIndex] = "a"; 129 assertArraysEqual(expected2, buffer.toArray()); 130 } 131 132 @Test testGetNextSlot()133 public void testGetNextSlot() { 134 int capacity = 100; 135 RingBuffer<DummyClass1> buffer = new RingBuffer<>(DummyClass1.class, capacity); 136 137 final DummyClass1[] actual = new DummyClass1[capacity]; 138 final DummyClass1[] expected = new DummyClass1[capacity]; 139 for (int i = 0; i < capacity; ++i) { 140 final DummyClass1 obj = buffer.getNextSlot(); 141 obj.x = capacity * i; 142 actual[i] = obj; 143 expected[i] = new DummyClass1(); 144 expected[i].x = capacity * i; 145 } 146 assertArraysEqual(expected, buffer.toArray()); 147 148 for (int i = 0; i < capacity; ++i) { 149 if (actual[i] != buffer.getNextSlot()) { 150 fail("getNextSlot() should re-use objects if available"); 151 } 152 } 153 154 RingBuffer<DummyClass2> buffer2 = new RingBuffer<>(DummyClass2.class, capacity); 155 assertNull("getNextSlot() should return null if the object can't be initiated " 156 + "(No nullary constructor)", buffer2.getNextSlot()); 157 158 RingBuffer<DummyClass3> buffer3 = new RingBuffer<>(DummyClass3.class, capacity); 159 assertNull("getNextSlot() should return null if the object can't be initiated " 160 + "(Inaccessible class)", buffer3.getNextSlot()); 161 } 162 163 public static final class DummyClass1 { 164 int x; 165 equals(Object o)166 public boolean equals(Object o) { 167 if (o instanceof DummyClass1) { 168 final DummyClass1 other = (DummyClass1) o; 169 return other.x == this.x; 170 } 171 return false; 172 } 173 } 174 175 public static final class DummyClass2 { DummyClass2(int x)176 public DummyClass2(int x) {} 177 } 178 179 private static final class DummyClass3 {} 180 assertArraysEqual(T[] expected, T[] got)181 static <T> void assertArraysEqual(T[] expected, T[] got) { 182 if (expected.length != got.length) { 183 fail(Arrays.toString(expected) + " and " + Arrays.toString(got) 184 + " did not have the same length"); 185 } 186 187 for (int i = 0; i < expected.length; i++) { 188 if (!Objects.equals(expected[i], got[i])) { 189 fail(Arrays.toString(expected) + " and " + Arrays.toString(got) 190 + " were not equal"); 191 } 192 } 193 } 194 } 195