Skip to content

Commit e9a3a08

Browse files
CursedFlamesNotStirred
authored andcommitted
Unit tests for CloCollectorFuture
1 parent d9b8087 commit e9a3a08

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

src/main/java/io/github/opencubicchunks/cubicchunks/server/level/CloCollectorFuture.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class CloCollectorFuture extends CompletableFuture<List<Either<CloAccess,
2424

2525
private final Either<CloAccess, ChunkHolder.ChunkLoadingFailure>[] results;
2626
// Vanilla expects that the center chunk is in the middle of the list; this is not the case for cubes, so we manually swap the center cube to the middle
27-
private AtomicInteger indexToBeSwappedWithCenterIndex = new AtomicInteger();
27+
private AtomicInteger indexToBeSwappedWithCenterIndex = new AtomicInteger(-1);
2828

2929
public CloCollectorFuture(int size) {
3030
this.size = size;
@@ -37,7 +37,10 @@ public void add(Either<CloAccess, ChunkHolder.ChunkLoadingFailure> either, @Null
3737
} else {
3838
int i = index.getAndIncrement();
3939
if (isCenterCube) {
40-
indexToBeSwappedWithCenterIndex.set(i);
40+
int oldValue = indexToBeSwappedWithCenterIndex.getAndSet(i);
41+
if (oldValue != -1) {
42+
throw new IllegalStateException("Tried to set center cube when center cube was already set");
43+
}
4144
}
4245
results[i] = either;
4346
}
@@ -49,6 +52,9 @@ public void add(Either<CloAccess, ChunkHolder.ChunkLoadingFailure> either, @Null
4952

5053
private void done() {
5154
int i = indexToBeSwappedWithCenterIndex.get();
55+
if (i == -1) {
56+
throw new IllegalStateException("All Clos were received but no center cube was set");
57+
}
5258
int j = results.length / 2;
5359
var results = Arrays.asList(this.results);
5460
Collections.swap(results, i, j);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package io.github.opencubicchunks.cubicchunks.test.server.level;
2+
3+
import static org.junit.jupiter.api.Assertions.assertFalse;
4+
import static org.junit.jupiter.api.Assertions.assertNotSame;
5+
import static org.junit.jupiter.api.Assertions.assertSame;
6+
import static org.junit.jupiter.api.Assertions.assertThrows;
7+
import static org.junit.jupiter.api.Assertions.assertTrue;
8+
import static org.mockito.Mockito.mock;
9+
10+
import com.mojang.datafixers.util.Either;
11+
import io.github.opencubicchunks.cubicchunks.server.level.CloCollectorFuture;
12+
import io.github.opencubicchunks.cubicchunks.testutils.BaseTest;
13+
import io.github.opencubicchunks.cubicchunks.world.level.chunklike.CloAccess;
14+
import org.junit.jupiter.api.Test;
15+
import org.junit.jupiter.api.TestInstance;
16+
17+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
18+
public class TestCloCollectorFuture extends BaseTest {
19+
@Test public void testFutureCompletion() throws Exception {
20+
for (int i = 0; i < 9; i++) { // Run nine times, putting the center cube at each index
21+
var future = new CloCollectorFuture(9);
22+
CloAccess centerCube = mock();
23+
CloAccess others = mock();
24+
for (int j = 0; j < 9; j++) {
25+
assertFalse(future.isDone(), "future shouldn't complete until all Clos are added");
26+
future.add(Either.left(j == i ? centerCube : others), null, j == i);
27+
}
28+
assertTrue(future.isDone(), "future should be complete once all Clos are added");
29+
assertSame(future.get().get(4).left().get(), centerCube, "centerCube should be at center index");
30+
for (int j = 0; j < 9; j++) {
31+
if (j == 4) continue;
32+
assertNotSame(future.get().get(j).left().get(), centerCube, "reference to centerCube should not be duplicated at any other index");
33+
}
34+
}
35+
}
36+
37+
@Test public void testMultipleCenterCubes() {
38+
var future = new CloCollectorFuture(9);
39+
CloAccess cloAccess = mock();
40+
future.add(Either.left(cloAccess), null, true);
41+
assertThrows(IllegalStateException.class, () -> future.add(Either.left(cloAccess), null, true), "trying to set centerCube multiple times should throw an exception");
42+
}
43+
44+
@Test public void testMissingCenterCube() {
45+
var future = new CloCollectorFuture(9);
46+
CloAccess cloAccess = mock();
47+
for (int i = 0; i < 8; i++) {
48+
future.add(Either.left(cloAccess), null, false);
49+
}
50+
assertThrows(IllegalStateException.class, () -> future.add(Either.left(cloAccess), null, false), "completing without having set centerCube should throw an exception");
51+
}
52+
53+
@Test public void testFutureExceptionPropagation() {
54+
for (int i = 0; i < 9; i++) { // Run nine times, throwing an exception at each index
55+
var future = new CloCollectorFuture(9);
56+
var exception = new Exception("test exception");
57+
CloAccess cloAccess = mock();
58+
for (int j = 0; j < 9; j++) {
59+
future.add(Either.left(cloAccess), i == j ? exception : null, false);
60+
}
61+
assertTrue(future.isCompletedExceptionally(), "future should complete exceptionally upon receiving an Exception");
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)