use of io.pravega.test.common.IntentionalException in project pravega by pravega.
the class StorageWriterTests method testWithStorageRecoverableCorruptionErrors.
/**
* Tests the StorageWriter in a Scenario where the Storage component throws data corruption exceptions (i.e., badOffset),
* but after reconciliation, the data is not corrupt.
*/
@Test
public void testWithStorageRecoverableCorruptionErrors() throws Exception {
final int failWriteEvery = 3;
final int failSealEvery = 7;
final int failMergeEvery = 5;
@Cleanup TestContext context = new TestContext(DEFAULT_CONFIG);
// Inject write errors every now and then.
AtomicInteger writeCount = new AtomicInteger();
AtomicInteger writeFailCount = new AtomicInteger();
context.storage.setWriteInterceptor((segmentName, offset, data, length, storage) -> {
if (writeCount.incrementAndGet() % failWriteEvery == 0) {
return storage.write(InMemoryStorage.newHandle(segmentName, false), offset, data, length, TIMEOUT).thenRun(() -> {
writeFailCount.incrementAndGet();
throw new IntentionalException(String.format("S=%s,O=%d,L=%d", segmentName, offset, length));
});
}
return null;
});
// Inject Seal errors every now and then.
AtomicInteger sealCount = new AtomicInteger();
AtomicInteger sealFailCount = new AtomicInteger();
context.storage.setSealInterceptor((segmentName, storage) -> {
if (sealCount.incrementAndGet() % failSealEvery == 0) {
return storage.seal(InMemoryStorage.newHandle(segmentName, false), TIMEOUT).thenRun(() -> {
sealFailCount.incrementAndGet();
throw new IntentionalException(String.format("S=%s", segmentName));
});
}
return null;
});
// Inject Merge/Concat errors every now and then.
AtomicInteger mergeCount = new AtomicInteger();
AtomicInteger mergeFailCount = new AtomicInteger();
context.storage.setConcatInterceptor((targetSegment, offset, sourceSegment, storage) -> {
if (mergeCount.incrementAndGet() % failMergeEvery == 0) {
return storage.concat(InMemoryStorage.newHandle(targetSegment, false), offset, sourceSegment, TIMEOUT).thenRun(() -> {
mergeFailCount.incrementAndGet();
throw new IntentionalException(String.format("T=%s,O=%d,S=%s", targetSegment, offset, sourceSegment));
});
}
return null;
});
testWriter(context);
AssertExtensions.assertGreaterThan("Not enough writes were made for this test.", 0, writeCount.get());
AssertExtensions.assertGreaterThan("Not enough write failures happened for this test.", 0, writeFailCount.get());
AssertExtensions.assertGreaterThan("Not enough seals were made for this test.", 0, sealCount.get());
AssertExtensions.assertGreaterThan("Not enough seal failures happened for this test.", 0, sealFailCount.get());
AssertExtensions.assertGreaterThan("Not enough mergers were made for this test.", 0, mergeCount.get());
AssertExtensions.assertGreaterThan("Not enough merge failures happened for this test.", 0, mergeFailCount.get());
}
use of io.pravega.test.common.IntentionalException in project pravega by pravega.
the class StreamSegmentContainerTests method testStartFailure.
/**
* Tests the behavior when there is a startup failure (i.e., already started services need to shut down.
*/
@Test
public void testStartFailure() throws Exception {
final Duration shutdownTimeout = Duration.ofSeconds(5);
@Cleanup val context = new TestContext();
val failedWriterFactory = new FailedWriterFactory();
AtomicReference<OperationLog> log = new AtomicReference<>();
val watchableDurableLogFactory = new WatchableOperationLogFactory(context.operationLogFactory, log::set);
val containerFactory = new StreamSegmentContainerFactory(DEFAULT_CONFIG, watchableDurableLogFactory, context.readIndexFactory, failedWriterFactory, context.storageFactory, executorService());
val container = containerFactory.createStreamSegmentContainer(CONTAINER_ID);
container.startAsync();
// Wait for the container to be shut down and verify it is failed.
ServiceListeners.awaitShutdown(container, shutdownTimeout, false);
Assert.assertEquals("Container is not in a failed state after a failed startup.", Service.State.FAILED, container.state());
Throwable actualException = Exceptions.unwrap(container.failureCause());
boolean exceptionMatch = actualException instanceof IntentionalException;
if (!exceptionMatch) {
Assert.fail(String.format("Container did not fail with the correct exception. Expected '%s', Actual '%s'.", IntentionalException.class.getSimpleName(), actualException));
}
// Verify the OperationLog is also shut down, and make sure it is not in a Failed state.
ServiceListeners.awaitShutdown(log.get(), shutdownTimeout, true);
}
use of io.pravega.test.common.IntentionalException in project pravega by pravega.
the class StreamSegmentMapperTests method testGetOrAssignStreamSegmentIdWithFailures.
/**
* Tests the ability of the StreamSegmentMapper to generate/return the Id of an existing StreamSegment, when dealing
* with Storage failures (or inexistent StreamSegments).
*/
@Test
public void testGetOrAssignStreamSegmentIdWithFailures() {
final String segmentName = "Segment";
final String transactionName = StreamSegmentNameUtils.getTransactionNameFromId(segmentName, UUID.randomUUID());
HashSet<String> storageSegments = new HashSet<>();
storageSegments.add(segmentName);
storageSegments.add(transactionName);
@Cleanup TestContext context = new TestContext();
setupOperationLog(context);
// 1. Unable to access storage.
context.storage.getInfoHandler = sn -> Futures.failedFuture(new IntentionalException());
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception when the Storage access failed.", () -> context.mapper.getOrAssignStreamSegmentId(segmentName, TIMEOUT), ex -> ex instanceof IntentionalException);
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception when the Storage access failed.", () -> context.mapper.getOrAssignStreamSegmentId(transactionName, TIMEOUT), ex -> ex instanceof IntentionalException);
// 2a. StreamSegmentNotExists (Stand-Alone segment)
setupStorageGetHandler(context, storageSegments, sn -> StreamSegmentInformation.builder().name(sn).build());
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception for a non-existent stand-alone StreamSegment.", () -> context.mapper.getOrAssignStreamSegmentId(segmentName + "foo", TIMEOUT), ex -> ex instanceof StreamSegmentNotExistsException);
// 2b. Transaction does not exist.
final String inexistentTransactionName = StreamSegmentNameUtils.getTransactionNameFromId(segmentName, UUID.randomUUID());
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception for a non-existent Transaction.", () -> context.mapper.getOrAssignStreamSegmentId(inexistentTransactionName, TIMEOUT), ex -> ex instanceof StreamSegmentNotExistsException);
// 2c. Transaction exists, but not its parent.
final String noValidParentTransactionName = StreamSegmentNameUtils.getTransactionNameFromId("foo", UUID.randomUUID());
storageSegments.add(noValidParentTransactionName);
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception for a Transaction with an inexistent parent.", () -> context.mapper.getOrAssignStreamSegmentId(noValidParentTransactionName, TIMEOUT), ex -> ex instanceof StreamSegmentNotExistsException);
// 2d. Attribute fetch failure.
val testStateStore = new TestStateStore();
val badMapper = new StreamSegmentMapper(context.metadata, context.operationLog, testStateStore, context.noOpMetadataCleanup, context.storage, executorService());
val segmentName2 = segmentName + "2";
val transactionName2 = StreamSegmentNameUtils.getTransactionNameFromId(segmentName2, UUID.randomUUID());
context.storage.getInfoHandler = sn -> CompletableFuture.completedFuture(StreamSegmentInformation.builder().name(sn).build());
testStateStore.getHandler = () -> Futures.failedFuture(new IntentionalException("intentional"));
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception for a Segment when attributes could not be retrieved.", () -> badMapper.getOrAssignStreamSegmentId(segmentName2, TIMEOUT), ex -> ex instanceof IntentionalException);
AssertExtensions.assertThrows("getOrAssignStreamSegmentId did not throw the right exception for a Transaction when attributes could not be retrieved.", () -> badMapper.getOrAssignStreamSegmentId(transactionName2, TIMEOUT), ex -> ex instanceof IntentionalException);
}
use of io.pravega.test.common.IntentionalException in project pravega by pravega.
the class AbstractThreadPoolServiceTests method testShutdownRunException.
/**
* Tests the behavior of AbstractThreadPoolService during shutdown when only a RunException is present.
*/
@Test
public void testShutdownRunException() {
@Cleanup val s = newService();
s.stopAsync();
s.runFuture.completeExceptionally(new IntentionalException());
AssertExtensions.assertThrows("Service did not fail when runFuture failed.", () -> s.awaitTerminated(), ex -> ex instanceof IllegalStateException);
Assert.assertEquals("Unexpected state upon failed shutdown.", Service.State.FAILED, s.state());
Assert.assertTrue("Unexpected failure cause.", s.failureCause() instanceof IntentionalException);
}
use of io.pravega.test.common.IntentionalException in project pravega by pravega.
the class AbstractThreadPoolServiceTests method testShutdownStopAndRunException.
/**
* Tests the behavior of AbstractThreadPoolService during shutdown when both a StopException and a RunException are present.
*/
@Test
public void testShutdownStopAndRunException() {
val s = newService();
// Stop it and verify it hasn't shut down - it should still be waiting on the runFuture.
val stopException = new IntentionalException("stop");
s.errorHandler(stopException);
val runException = new IntentionalException("run");
s.runFuture.completeExceptionally(runException);
AssertExtensions.assertThrows("Service did not fail.", () -> s.awaitTerminated(), ex -> ex instanceof IllegalStateException);
Assert.assertEquals("Unexpected state upon failed shutdown.", Service.State.FAILED, s.state());
Assert.assertEquals("Unexpected failure cause.", stopException, s.failureCause());
Assert.assertEquals("Unexpected suppressed exception.", runException, s.failureCause().getSuppressed()[0]);
}
Aggregations