Skip to content

Commit 62786e1

Browse files
committed
Fix and improve tests
1 parent d0e44d2 commit 62786e1

File tree

1 file changed

+69
-60
lines changed

1 file changed

+69
-60
lines changed

test/src/main/java/org/apache/accumulo/test/fate/accumulo/AccumuloStoreIT.java

+69-60
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,12 @@
2121
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
2222
import static org.junit.jupiter.api.Assertions.assertEquals;
2323
import static org.junit.jupiter.api.Assertions.assertThrows;
24-
import static org.junit.jupiter.params.provider.Arguments.arguments;
2524

2625
import java.util.Iterator;
2726
import java.util.List;
2827
import java.util.Set;
2928
import java.util.TreeSet;
30-
import java.util.function.Consumer;
3129
import java.util.stream.Collectors;
32-
import java.util.stream.Stream;
3330

3431
import org.apache.accumulo.core.client.Accumulo;
3532
import org.apache.accumulo.core.client.BatchWriter;
@@ -42,19 +39,18 @@
4239
import org.apache.accumulo.core.fate.FateInstanceType;
4340
import org.apache.accumulo.core.fate.FateStore;
4441
import org.apache.accumulo.core.fate.ReadOnlyFateStore;
45-
import org.apache.accumulo.core.fate.StackOverflowException;
4642
import org.apache.accumulo.core.fate.accumulo.AccumuloStore;
4743
import org.apache.accumulo.core.fate.accumulo.schema.FateSchema;
4844
import org.apache.accumulo.harness.SharedMiniClusterBase;
4945
import org.apache.accumulo.test.fate.FateIT;
5046
import org.apache.hadoop.io.Text;
5147
import org.junit.jupiter.api.AfterAll;
48+
import org.junit.jupiter.api.AfterEach;
5249
import org.junit.jupiter.api.BeforeAll;
50+
import org.junit.jupiter.api.BeforeEach;
51+
import org.junit.jupiter.api.Nested;
5352
import org.junit.jupiter.api.Test;
5453
import org.junit.jupiter.api.function.Executable;
55-
import org.junit.jupiter.params.ParameterizedTest;
56-
import org.junit.jupiter.params.provider.Arguments;
57-
import org.junit.jupiter.params.provider.MethodSource;
5854
import org.slf4j.Logger;
5955
import org.slf4j.LoggerFactory;
6056

@@ -121,64 +117,76 @@ public void testCreateWithCollisionAndExceedRetryLimit() throws Exception {
121117
}
122118
}
123119

124-
/**
125-
* Test that an operation only works with the expected statuses present for the transaction.
126-
*/
127-
@ParameterizedTest(name = "{index} => Operation: {0}")
128-
@MethodSource("operationStatusPairs")
129-
public void testStatuses(String description,
130-
Consumer<FateStore.FateTxStore<FateIT.TestEnv>> operationConsumer,
131-
Set<ReadOnlyFateStore.TStatus> acceptableStatuses) throws Exception {
132-
try (ClientContext client =
133-
(ClientContext) Accumulo.newClient().from(getClientProps()).build()) {
134-
final String tableName = getUniqueNames(1)[0];
135-
try {
136-
client.tableOperations().create(tableName);
137-
FateId fateId = FateId.from(fateInstanceType, 1L);
138-
TestAccumuloStore store = new TestAccumuloStore(client, tableName, List.of(fateId));
139-
store.create();
140-
FateStore.FateTxStore<FateIT.TestEnv> txStore = store.reserve(fateId);
141-
142-
// for each TStatus, set the status and verify that the operation only works if it is in the
143-
// expected set of statuses
144-
for (ReadOnlyFateStore.TStatus status : ReadOnlyFateStore.TStatus.values()) {
145-
injectStatus(client, tableName, fateId, status);
146-
assertEquals(status, store.getStatus(fateId));
147-
Executable testOp = () -> operationConsumer.accept(txStore);
148-
if (!acceptableStatuses.contains(status)) {
149-
assertThrows(IllegalStateException.class, testOp,
150-
"Expected " + description + " to fail with status " + status + " but it did not");
151-
} else {
152-
assertDoesNotThrow(testOp, "Expected " + description + " to succeed with status "
153-
+ status + " but it did not");
154-
}
120+
@Nested
121+
class TestStatusEnforcement {
122+
123+
String tableName;
124+
ClientContext client;
125+
FateId fateId;
126+
TestAccumuloStore store;
127+
FateStore.FateTxStore<FateIT.TestEnv> txStore;
128+
129+
@BeforeEach
130+
public void setup() throws Exception {
131+
client = (ClientContext) Accumulo.newClient().from(getClientProps()).build();
132+
tableName = getUniqueNames(1)[0];
133+
client.tableOperations().create(tableName);
134+
fateId = FateId.from(fateInstanceType, 1L);
135+
store = new TestAccumuloStore(client, tableName, List.of(fateId));
136+
store.create();
137+
txStore = store.reserve(fateId);
138+
}
139+
140+
@AfterEach
141+
public void teardown() throws Exception {
142+
client.close();
143+
}
144+
145+
private void testOperationWithStatuses(Runnable beforeOperation, Executable operation,
146+
Set<ReadOnlyFateStore.TStatus> acceptableStatuses) throws Exception {
147+
for (ReadOnlyFateStore.TStatus status : ReadOnlyFateStore.TStatus.values()) {
148+
// Run any needed setup for the operation before each iteration
149+
beforeOperation.run();
150+
151+
injectStatus(client, tableName, fateId, status);
152+
assertEquals(status, store.getStatus(fateId));
153+
if (!acceptableStatuses.contains(status)) {
154+
assertThrows(IllegalStateException.class, operation,
155+
"Expected operation to fail with status " + status + " but it did not");
156+
} else {
157+
assertDoesNotThrow(operation,
158+
"Expected operation to succeed with status " + status + " but it did not");
155159
}
156-
} finally {
160+
}
161+
}
162+
163+
@Test
164+
public void push() throws Exception {
165+
testOperationWithStatuses(() -> {}, // No special setup needed for push
166+
() -> txStore.push(new FateIT.TestRepo("testOp")),
167+
Set.of(ReadOnlyFateStore.TStatus.IN_PROGRESS, ReadOnlyFateStore.TStatus.NEW));
168+
}
169+
170+
@Test
171+
public void pop() throws Exception {
172+
testOperationWithStatuses(() -> {
173+
// Setup for pop: Ensure there something to pop by first pushing
157174
try {
158-
client.tableOperations().delete(tableName);
159-
} catch (TableNotFoundException e) {
160-
// ignore
175+
injectStatus(client, tableName, fateId, ReadOnlyFateStore.TStatus.NEW);
176+
txStore.push(new FateIT.TestRepo("testOp"));
177+
} catch (Exception e) {
178+
throw new RuntimeException("Failed to setup for pop", e);
161179
}
162-
}
180+
}, txStore::pop, Set.of(ReadOnlyFateStore.TStatus.FAILED_IN_PROGRESS));
163181
}
164-
}
165182

166-
public static Stream<Arguments> operationStatusPairs() {
167-
return Stream
168-
.of(arguments("push()", (Consumer<FateStore.FateTxStore<FateIT.TestEnv>>) txStore -> {
169-
try {
170-
txStore.push(new FateIT.TestRepo("testOp"));
171-
} catch (StackOverflowException e) {
172-
throw new RuntimeException(e);
173-
}
174-
}, Set.of(ReadOnlyFateStore.TStatus.IN_PROGRESS, ReadOnlyFateStore.TStatus.NEW)),
175-
arguments("pop()",
176-
(Consumer<FateStore.FateTxStore<FateIT.TestEnv>>) FateStore.FateTxStore::pop,
177-
Set.of(ReadOnlyFateStore.TStatus.FAILED_IN_PROGRESS)),
178-
arguments("delete()",
179-
(Consumer<FateStore.FateTxStore<FateIT.TestEnv>>) FateStore.FateTxStore::delete,
180-
Set.of(ReadOnlyFateStore.TStatus.NEW, ReadOnlyFateStore.TStatus.SUBMITTED,
181-
ReadOnlyFateStore.TStatus.SUCCESSFUL, ReadOnlyFateStore.TStatus.FAILED)));
183+
@Test
184+
public void delete() throws Exception {
185+
testOperationWithStatuses(() -> {}, // No special setup needed for delete
186+
txStore::delete,
187+
Set.of(ReadOnlyFateStore.TStatus.NEW, ReadOnlyFateStore.TStatus.SUBMITTED,
188+
ReadOnlyFateStore.TStatus.SUCCESSFUL, ReadOnlyFateStore.TStatus.FAILED));
189+
}
182190
}
183191

184192
/**
@@ -194,4 +202,5 @@ private void injectStatus(ClientContext client, String table, FateId fateId,
194202
throw new RuntimeException(e);
195203
}
196204
}
205+
197206
}

0 commit comments

Comments
 (0)