Skip to content

Commit 66fa9c4

Browse files
committed
fix simple ring buffer and add tests
1 parent b866b05 commit 66fa9c4

File tree

3 files changed

+330
-25
lines changed

3 files changed

+330
-25
lines changed

common/src/main/java/com/tc/util/SimpleRingBuffer.java

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package com.tc.util;
1919

2020
import java.util.Arrays;
21+
import java.util.Collections;
2122
import java.util.Iterator;
2223
import java.util.Objects;
2324
import java.util.stream.Stream;
@@ -37,7 +38,7 @@ public SimpleRingBuffer(int size) {
3738
}
3839

3940
public void put(T item) {
40-
Objects.nonNull(item);
41+
Objects.requireNonNull(item);
4142
buffer[head++] = item;
4243
head = head % buffer.length;
4344
}
@@ -48,26 +49,35 @@ public Stream<T> stream() {
4849

4950
@Override
5051
public Iterator<T> iterator() {
51-
final Object[] ref = (buffer[head] != null) ? Arrays.copyOf(buffer, buffer.length) : Arrays.copyOf(buffer, head);
52-
final int end = head % ref.length;
53-
54-
return new Iterator<T>() {
55-
private int pos = (end + 1) % ref.length;
56-
57-
@Override
58-
public boolean hasNext() {
59-
return pos != end;
60-
}
52+
if (buffer[0] == null) {
53+
return Collections.emptyIterator();
54+
} else {
55+
// there is at least one item in the list;
56+
// if the list has not wrapped just reference the non-null list
57+
final Object[] ref = (buffer[head] != null) ? Arrays.copyOf(buffer, buffer.length) : Arrays.copyOf(buffer, head);
58+
// current head is the oldest item. If the list hasn't wrapped yet, oldest is the first
59+
final int pivot = head != ref.length ? head : 0;
6160

62-
@Override
63-
@SuppressWarnings("unchecked")
64-
public T next() {
65-
try {
66-
return (T)ref[pos++];
67-
} finally {
68-
pos = pos % ref.length;
61+
return new Iterator<T>() {
62+
private int pos = pivot;
63+
boolean done = false;
64+
65+
@Override
66+
public boolean hasNext() {
67+
return !done;
68+
}
69+
70+
@Override
71+
@SuppressWarnings("unchecked")
72+
public T next() {
73+
try {
74+
return (T)ref[pos++];
75+
} finally {
76+
pos = pos % ref.length;
77+
done = pos == pivot;
78+
}
6979
}
70-
}
71-
};
80+
};
81+
}
7282
}
7383
}
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* Copyright Terracotta, Inc.
3+
* Copyright IBM Corp. 2024, 2025
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
package com.tc.util;
19+
20+
import java.util.ArrayList;
21+
import java.util.Iterator;
22+
import java.util.List;
23+
24+
/**
25+
* Manual test class for SimpleRingBuffer that doesn't rely on JUnit
26+
*/
27+
public class SimpleRingBufferManualTest {
28+
29+
public static void main(String[] args) {
30+
testEmptyBuffer();
31+
testPartiallyFilledBuffer();
32+
testFullBufferNoWraparound();
33+
testWraparoundBuffer();
34+
testMultipleWraparounds();
35+
testNullRejection();
36+
testSingleElement();
37+
38+
System.out.println("All tests completed!");
39+
}
40+
41+
private static void testEmptyBuffer() {
42+
System.out.println("Testing empty buffer...");
43+
SimpleRingBuffer<String> buffer = new SimpleRingBuffer<>(5);
44+
Iterator<String> iterator = buffer.iterator();
45+
46+
// Empty buffer should have no elements
47+
if (iterator.hasNext()) {
48+
System.err.println("FAIL: Empty buffer should not have elements");
49+
} else {
50+
System.out.println("PASS: Empty buffer has no elements");
51+
}
52+
}
53+
54+
private static void testPartiallyFilledBuffer() {
55+
System.out.println("Testing partially filled buffer...");
56+
SimpleRingBuffer<String> buffer = new SimpleRingBuffer<>(5);
57+
buffer.put("A");
58+
buffer.put("B");
59+
buffer.put("C");
60+
61+
// Buffer has 3 elements, not wrapped around
62+
List<String> elements = collectElements(buffer);
63+
System.out.println("Elements: " + elements);
64+
65+
if (elements.size() != 3) {
66+
System.err.println("FAIL: Expected 3 elements, got " + elements.size());
67+
} else if (!elements.get(0).equals("A") || !elements.get(1).equals("B") || !elements.get(2).equals("C")) {
68+
System.err.println("FAIL: Elements in wrong order: " + elements);
69+
} else {
70+
System.out.println("PASS: Partially filled buffer has correct elements in order");
71+
}
72+
}
73+
74+
private static void testFullBufferNoWraparound() {
75+
System.out.println("Testing full buffer without wraparound...");
76+
SimpleRingBuffer<String> buffer = new SimpleRingBuffer<>(3);
77+
buffer.put("A");
78+
buffer.put("B");
79+
buffer.put("C");
80+
81+
// Buffer is full but hasn't wrapped around
82+
List<String> elements = collectElements(buffer);
83+
System.out.println("Elements: " + elements);
84+
85+
if (elements.size() != 3) {
86+
System.err.println("FAIL: Expected 3 elements, got " + elements.size());
87+
} else if (!elements.get(0).equals("A") || !elements.get(1).equals("B") || !elements.get(2).equals("C")) {
88+
System.err.println("FAIL: Elements in wrong order: " + elements);
89+
} else {
90+
System.out.println("PASS: Full buffer has correct elements in order");
91+
}
92+
}
93+
94+
private static void testWraparoundBuffer() {
95+
System.out.println("Testing buffer with wraparound...");
96+
SimpleRingBuffer<String> buffer = new SimpleRingBuffer<>(3);
97+
buffer.put("A");
98+
buffer.put("B");
99+
buffer.put("C");
100+
buffer.put("D"); // Overwrites A
101+
102+
// Buffer has wrapped around, D replaced A
103+
List<String> elements = collectElements(buffer);
104+
System.out.println("Elements: " + elements);
105+
106+
if (elements.size() != 3) {
107+
System.err.println("FAIL: Expected 3 elements, got " + elements.size());
108+
} else if (!elements.get(0).equals("B") || !elements.get(1).equals("C") || !elements.get(2).equals("D")) {
109+
System.err.println("FAIL: Elements in wrong order: " + elements);
110+
} else {
111+
System.out.println("PASS: Wrapped buffer has correct elements in order");
112+
}
113+
}
114+
115+
private static void testMultipleWraparounds() {
116+
System.out.println("Testing buffer with multiple wraparounds...");
117+
SimpleRingBuffer<String> buffer = new SimpleRingBuffer<>(3);
118+
buffer.put("A");
119+
buffer.put("B");
120+
buffer.put("C");
121+
buffer.put("D"); // Overwrites A
122+
buffer.put("E"); // Overwrites B
123+
buffer.put("F"); // Overwrites C
124+
125+
// After multiple wraparounds
126+
List<String> elements = collectElements(buffer);
127+
System.out.println("Elements: " + elements);
128+
129+
if (elements.size() != 3) {
130+
System.err.println("FAIL: Expected 3 elements, got " + elements.size());
131+
} else if (!elements.get(0).equals("D") || !elements.get(1).equals("E") || !elements.get(2).equals("F")) {
132+
System.err.println("FAIL: Elements in wrong order: " + elements);
133+
} else {
134+
System.out.println("PASS: Multiple wraparound buffer has correct elements in order");
135+
}
136+
}
137+
138+
private static void testNullRejection() {
139+
System.out.println("Testing null rejection...");
140+
SimpleRingBuffer<String> buffer = new SimpleRingBuffer<>(3);
141+
try {
142+
buffer.put(null);
143+
System.err.println("FAIL: Should have thrown NullPointerException");
144+
} catch (NullPointerException e) {
145+
System.out.println("PASS: Null was rejected with NullPointerException");
146+
}
147+
}
148+
149+
private static void testSingleElement() {
150+
System.out.println("Testing single element buffer...");
151+
SimpleRingBuffer<String> buffer = new SimpleRingBuffer<>(1);
152+
buffer.put("A");
153+
buffer.put("B"); // Overwrites A
154+
155+
List<String> elements = collectElements(buffer);
156+
System.out.println("Elements: " + elements);
157+
158+
if (elements.size() != 1) {
159+
System.err.println("FAIL: Expected 1 element, got " + elements.size());
160+
} else if (!elements.get(0).equals("B")) {
161+
System.err.println("FAIL: Expected element B, got " + elements.get(0));
162+
} else {
163+
System.out.println("PASS: Single element buffer contains only the newest element");
164+
}
165+
}
166+
167+
// Helper method to collect all elements from the buffer into a list
168+
private static <T> List<T> collectElements(SimpleRingBuffer<T> buffer) {
169+
List<T> result = new ArrayList<>();
170+
for (T element : buffer) {
171+
result.add(element);
172+
}
173+
return result;
174+
}
175+
}
176+
177+
// Made with Bob

0 commit comments

Comments
 (0)