Search in sources :

Example 6 with IntentionalException

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());
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Cleanup(lombok.Cleanup) IntentionalException(io.pravega.test.common.IntentionalException) Test(org.junit.Test)

Example 7 with IntentionalException

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);
}
Also used : lombok.val(lombok.val) OperationLog(io.pravega.segmentstore.server.OperationLog) Duration(java.time.Duration) AtomicReference(java.util.concurrent.atomic.AtomicReference) Cleanup(lombok.Cleanup) IntentionalException(io.pravega.test.common.IntentionalException) Test(org.junit.Test)

Example 8 with IntentionalException

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);
}
Also used : lombok.val(lombok.val) Cleanup(lombok.Cleanup) IntentionalException(io.pravega.test.common.IntentionalException) StreamSegmentNotExistsException(io.pravega.segmentstore.contracts.StreamSegmentNotExistsException) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 9 with 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);
}
Also used : lombok.val(lombok.val) Cleanup(lombok.Cleanup) IntentionalException(io.pravega.test.common.IntentionalException) Test(org.junit.Test)

Example 10 with 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]);
}
Also used : lombok.val(lombok.val) IntentionalException(io.pravega.test.common.IntentionalException) Test(org.junit.Test)

Aggregations

IntentionalException (io.pravega.test.common.IntentionalException)40 Test (org.junit.Test)39 lombok.val (lombok.val)26 Cleanup (lombok.Cleanup)25 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)16 AtomicReference (java.util.concurrent.atomic.AtomicReference)14 Assert (org.junit.Assert)11 AssertExtensions (io.pravega.test.common.AssertExtensions)10 ArrayList (java.util.ArrayList)10 CompletableFuture (java.util.concurrent.CompletableFuture)10 ByteArrayOutputStream (java.io.ByteArrayOutputStream)9 Duration (java.time.Duration)9 Rule (org.junit.Rule)9 Timeout (org.junit.rules.Timeout)9 StreamSegmentNotExistsException (io.pravega.segmentstore.contracts.StreamSegmentNotExistsException)8 StorageOperation (io.pravega.segmentstore.server.logs.operations.StorageOperation)8 ThreadPooledTestSuite (io.pravega.test.common.ThreadPooledTestSuite)8 HashSet (java.util.HashSet)8 Random (java.util.Random)8 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)8