use of io.pravega.test.common.IntentionalException in project pravega by pravega.
the class StorageReadManagerTests method testDependents.
/**
* Tests the ability to queue dependent reads (subsequent reads that only want to read a part of a previous read).
* Test this both with successful and failed reads.
*/
@Test
public void testDependents() {
final Duration waitTimeout = Duration.ofSeconds(5);
TestStorage storage = new TestStorage();
CompletableFuture<Integer> signal = new CompletableFuture<>();
AtomicBoolean wasReadInvoked = new AtomicBoolean();
storage.readImplementation = () -> {
if (wasReadInvoked.getAndSet(true)) {
Assert.fail("Read was invoked multiple times, which is a likely indicator that the requests were not chained.");
}
return signal;
};
@Cleanup StorageReadManager reader = new StorageReadManager(SEGMENT_METADATA, storage, executorService());
// Create some reads.
CompletableFuture<StorageReadManager.Result> c1 = new CompletableFuture<>();
CompletableFuture<StorageReadManager.Result> c2 = new CompletableFuture<>();
reader.execute(new StorageReadManager.Request(0, 100, c1::complete, c1::completeExceptionally, TIMEOUT));
reader.execute(new StorageReadManager.Request(50, 100, c2::complete, c2::completeExceptionally, TIMEOUT));
Assert.assertFalse("One or more of the reads has completed prematurely.", c1.isDone() || c2.isDone());
signal.completeExceptionally(new IntentionalException());
AssertExtensions.assertThrows("The first read was not failed with the correct exception.", () -> c1.get(waitTimeout.toMillis(), TimeUnit.MILLISECONDS), ex -> ex instanceof IntentionalException);
AssertExtensions.assertThrows("The second read was not failed with the correct exception.", () -> c2.get(waitTimeout.toMillis(), TimeUnit.MILLISECONDS), ex -> ex instanceof IntentionalException);
}
use of io.pravega.test.common.IntentionalException in project pravega by pravega.
the class StreamSegmentContainerRegistryTests method testStartAlreadyRunning.
/**
* Tests a scenario where a container startup is requested immediately after the shutdown of the same container or
* while that one is running. This tests both the case when a container auto-shuts down due to failure and when it
* is shut down in a controlled manner.
*/
@Test
public void testStartAlreadyRunning() throws Exception {
final int containerId = 1;
TestContainerFactory factory = new TestContainerFactory();
@Cleanup StreamSegmentContainerRegistry registry = new StreamSegmentContainerRegistry(factory, executorService());
registry.startContainer(containerId, TIMEOUT).join();
TestContainer container1 = (TestContainer) registry.getContainer(containerId);
// 1. While running.
AssertExtensions.assertThrows("startContainer() did not throw for already registered container.", () -> registry.startContainer(containerId, TIMEOUT), ex -> ex instanceof IllegalArgumentException);
// 2. After a container fails - while shutting down.
// Manually control when the Container actually shuts down.
container1.stopSignal = new ReusableLatch();
container1.fail(new IntentionalException());
val startContainer2 = registry.startContainer(containerId, TIMEOUT);
Assert.assertFalse("startContainer() completed before previous container shut down (with failure).", startContainer2.isDone());
container1.stopSignal.release();
startContainer2.get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
TestContainer container2 = (TestContainer) registry.getContainer(containerId);
Assert.assertEquals("Container1 was not shut down (with failure).", Service.State.FAILED, container1.state());
Assert.assertEquals("Container2 was not started properly.", Service.State.RUNNING, container2.state());
// 3. After a controlled shutdown - while shutting down.
// Manually control when the Container actually shuts down.
container2.stopSignal = new ReusableLatch();
container2.stopAsync();
val startContainer3 = registry.startContainer(containerId, TIMEOUT);
Assert.assertFalse("startContainer() completed before previous container shut down (normally).", startContainer3.isDone());
container2.stopSignal.release();
startContainer3.get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
TestContainer container3 = (TestContainer) registry.getContainer(containerId);
Assert.assertEquals("Container2 was not shut down (normally).", Service.State.TERMINATED, container2.state());
Assert.assertEquals("Container3 was not started properly.", Service.State.RUNNING, container3.state());
}
use of io.pravega.test.common.IntentionalException in project pravega by pravega.
the class StreamSegmentContainerRegistryTests method testContainerFailureOnStartup.
/**
* Tests the ability to detect a container failure and unregister the container in case the container fails on startup.
*/
@Test
public void testContainerFailureOnStartup() throws Exception {
final int containerId = 123;
// We insert a ReusableLatch that will allow us to manually delay the TestContainer's shutdown/closing process
// so that we have enough time to verify that calling getContainer() on a currently shutting down container will
// throw the appropriate exception.
ReusableLatch closeReleaseSignal = new ReusableLatch();
TestContainerFactory factory = new TestContainerFactory(new IntentionalException(), closeReleaseSignal);
@Cleanup StreamSegmentContainerRegistry registry = new StreamSegmentContainerRegistry(factory, executorService());
AssertExtensions.assertThrows("Unexpected exception thrown upon failed container startup.", registry.startContainer(containerId, TIMEOUT)::join, ex -> ex instanceof IntentionalException || (ex instanceof IllegalStateException && ex.getCause() instanceof IntentionalException));
AssertExtensions.assertThrows("Container is registered even if it failed to start (and is currently shut down).", () -> registry.getContainer(containerId), ex -> ex instanceof ContainerNotFoundException);
// Unblock container closing, which will, in turn, unblock its de-registration.
closeReleaseSignal.release();
AssertExtensions.assertThrows("Container is registered even if it failed to start (and has been unregistered).", () -> registry.getContainer(containerId), ex -> ex instanceof ContainerNotFoundException);
}
use of io.pravega.test.common.IntentionalException in project pravega by pravega.
the class RollingStorageTests method testConcatNativelyFailure.
/**
* Tests the ability to use native concat for those cases when it's appropriate.
*/
@Test
public void testConcatNativelyFailure() throws Exception {
final int initialTargetLength = (int) DEFAULT_ROLLING_POLICY.getMaxLength() / 2;
final int initialSourceLength = (int) DEFAULT_ROLLING_POLICY.getMaxLength() - initialTargetLength;
final String sourceSegmentName = "SourceSegment";
// Concat succeeds, but can't delete header.
@Cleanup val baseStorage = new TestStorage();
@Cleanup val s = new RollingStorage(baseStorage, DEFAULT_ROLLING_POLICY);
s.initialize(1);
// Create a target and a source, making sure they have the right sizes for a native concat.
s.create(SEGMENT_NAME);
val targetHandle = (RollingSegmentHandle) s.openWrite(SEGMENT_NAME);
val writeStream = new ByteArrayOutputStream();
populate(s, targetHandle, 1, initialTargetLength, initialTargetLength, writeStream);
s.create(sourceSegmentName);
val sourceHandle = (RollingSegmentHandle) s.openWrite(sourceSegmentName);
populate(s, sourceHandle, 1, initialSourceLength, initialSourceLength, writeStream);
s.seal(sourceHandle);
// Attempt to concat, but intentionally fail the deletion of the source header.
baseStorage.deleteFailure = sn -> sn.equals(sourceHandle.getHeaderHandle().getSegmentName()) ? new IntentionalException() : null;
AssertExtensions.assertThrows("Unexpected exception when doing native concat.", () -> s.concat(targetHandle, initialTargetLength, sourceSegmentName), ex -> ex instanceof IntentionalException);
// However, the concat should have worked, so the source segment is now inaccessible.
baseStorage.deleteFailure = null;
checkConcatResult(s, targetHandle, sourceSegmentName, 1, initialTargetLength + initialSourceLength);
checkWrittenData(writeStream.toByteArray(), s.openRead(SEGMENT_NAME), s);
}
use of io.pravega.test.common.IntentionalException in project pravega by pravega.
the class RollingStorageTests method testConcatHeaderFailure.
/**
* Tests the ability to handle partially executed concat operations for header concat, such as being able to write
* the concat entry but not actually concat the source header file.
*/
@Test
public void testConcatHeaderFailure() throws Exception {
final int initialTargetLength = (int) DEFAULT_ROLLING_POLICY.getMaxLength() / 2;
final String sourceSegmentName = "SourceSegment";
@Cleanup val baseStorage = new TestStorage();
@Cleanup val s = new RollingStorage(baseStorage, DEFAULT_ROLLING_POLICY);
s.initialize(1);
// Create a Target Segment and a Source Segment and write some data to them.
s.create(SEGMENT_NAME);
val targetHandle = (RollingSegmentHandle) s.openWrite(SEGMENT_NAME);
val writeStream = new ByteArrayOutputStream();
populate(s, targetHandle, 1, initialTargetLength, initialTargetLength, writeStream);
s.create(sourceSegmentName);
val sourceHandle = (RollingSegmentHandle) s.openWrite(sourceSegmentName);
populate(s, sourceHandle, APPENDS_PER_SEGMENT, initialTargetLength, initialTargetLength, writeStream);
s.seal(sourceHandle);
// Simulate a native concat exception, and try a few times.
baseStorage.concatFailure = sn -> sn.equals(sourceHandle.getHeaderHandle().getSegmentName()) ? new IntentionalException() : null;
for (int i = 0; i < 4; i++) {
AssertExtensions.assertThrows("Unexpected error reported from concat.", () -> s.concat(targetHandle, initialTargetLength, sourceSegmentName), ex -> ex instanceof IntentionalException);
}
// Clear the intentional failure and try again, after which check the results.
baseStorage.concatFailure = null;
s.concat(targetHandle, initialTargetLength, sourceSegmentName);
checkConcatResult(s, targetHandle, sourceSegmentName, 1 + sourceHandle.chunks().size(), initialTargetLength + (int) sourceHandle.length());
checkWrittenData(writeStream.toByteArray(), s.openRead(SEGMENT_NAME), s);
}
Aggregations