use of java.util.function.Supplier in project pravega by pravega.
the class Futures method doWhileLoop.
/**
* Executes a code fragment returning a CompletableFutures while a condition on the returned value is satisfied.
*
* @param condition Predicate that indicates whether to proceed with the loop or not.
* @param loopBody A Supplier that returns a CompletableFuture which represents the body of the loop. This
* supplier is invoked every time the loopBody needs to execute.
* @param executor An Executor that is used to execute the condition and the loop support code.
* @param <T> Return type of the executor.
* @return A CompletableFuture that, when completed, indicates the loop terminated without any exception. If
* either the loopBody or condition throw/return Exceptions, these will be set as the result of this returned Future.
*/
public static <T> CompletableFuture<Void> doWhileLoop(Supplier<CompletableFuture<T>> loopBody, Predicate<T> condition, Executor executor) {
CompletableFuture<Void> result = new CompletableFuture<>();
// We implement the do-while loop using a regular loop, but we execute one iteration before we create the actual Loop object.
// Since this method has slightly different arguments than loop(), we need to make one adjustment:
// * After each iteration, we get the result and run it through 'condition' and use that to decide whether to continue.
AtomicBoolean canContinue = new AtomicBoolean();
Consumer<T> iterationResultHandler = ir -> canContinue.set(condition.test(ir));
loopBody.get().thenAccept(iterationResultHandler).thenRunAsync(() -> {
Loop<T> loop = new Loop<>(canContinue::get, loopBody, iterationResultHandler, result, executor);
executor.execute(loop);
}, executor).exceptionally(ex -> {
// Handle exceptions from the first iteration.
result.completeExceptionally(ex);
return null;
});
return result;
}
use of java.util.function.Supplier in project pravega by pravega.
the class RevisionDataOutputStreamTests method testImpl.
private void testImpl(RevisionDataOutputStream impl, Supplier<ByteArraySegment> getWrittenData) throws Exception {
final byte b = 123;
final short sn = 1234;
final int n = 123456;
final long l = (long) Integer.MAX_VALUE + 1;
final String s = getUTFString();
final byte[] array = s.getBytes();
int expectedLength = Byte.BYTES + Short.BYTES + Integer.BYTES + Long.BYTES + impl.getUTFLength(s) + array.length;
if (impl.requiresExplicitLength()) {
// Verify a few methods that shouldn't be allowed to run without setting length beforehand.
Arrays.<AssertExtensions.RunnableWithException>asList(() -> impl.write(1), () -> impl.write(new byte[1], 0, 1), () -> impl.writeInt(1), () -> impl.writeShort(1), () -> impl.writeLong(1), () -> impl.writeUTF("test")).forEach(r -> AssertExtensions.assertThrows("write was allowed without setting length first.", r, ex -> ex instanceof IllegalStateException));
}
impl.length(expectedLength);
impl.writeByte(b);
impl.writeShort(sn);
impl.writeInt(n);
impl.writeLong(l);
impl.writeUTF(s);
impl.write(array);
// Need to close so we flush any remaining stuff to the underlying stream.
impl.close();
// Verify the written data can be read back.
@Cleanup val inputStream = RevisionDataInputStream.wrap(getWrittenData.get().getReader());
Assert.assertEquals("Unexpected length read back.", expectedLength, inputStream.getLength());
Assert.assertEquals("Unexpected byte read back.", b, inputStream.read());
Assert.assertEquals("Unexpected short read back.", sn, inputStream.readShort());
Assert.assertEquals("Unexpected int read back.", n, inputStream.readInt());
Assert.assertEquals("Unexpected long read back.", l, inputStream.readLong());
Assert.assertEquals("Unexpected string read back.", s, inputStream.readUTF());
byte[] readArray = new byte[array.length];
int readBytes = inputStream.read(readArray);
Assert.assertEquals("Unexpected number of bytes read for array.", readArray.length, readBytes);
Assert.assertArrayEquals("Unexpected array read back.", array, readArray);
Assert.assertEquals("Not expecting any more data. ", -1, inputStream.read());
AssertExtensions.assertThrows("Expecting EOF.", () -> inputStream.readFully(new byte[1]), ex -> ex instanceof EOFException);
}
use of java.util.function.Supplier in project pravega by pravega.
the class AsyncReadResultProcessorTests method testCatchUpReads.
/**
* Tests the AsyncReadResultProcessor on catch-up reads (that are already available in memory).
*/
@Test
public void testCatchUpReads() throws Exception {
// Pre-generate some entries.
ArrayList<byte[]> entries = new ArrayList<>();
int totalLength = generateEntries(entries);
// Setup an entry provider supplier.
AtomicInteger currentIndex = new AtomicInteger();
StreamSegmentReadResult.NextEntrySupplier supplier = (offset, length) -> {
int idx = currentIndex.getAndIncrement();
if (idx >= entries.size()) {
return null;
}
return new CacheReadResultEntry(offset, entries.get(idx), 0, entries.get(idx).length);
};
// Start an AsyncReadResultProcessor.
@Cleanup StreamSegmentReadResult rr = new StreamSegmentReadResult(0, totalLength, supplier, "");
TestReadResultHandler testReadResultHandler = new TestReadResultHandler(entries);
try (AsyncReadResultProcessor rp = AsyncReadResultProcessor.process(rr, testReadResultHandler, executorService())) {
// Wait for it to complete, and then verify that no errors have been recorded via the callbacks.
testReadResultHandler.completed.get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
if (testReadResultHandler.error.get() != null) {
Assert.fail("Read failure: " + testReadResultHandler.error.get().toString());
}
Assert.assertEquals("Unexpected number of reads processed.", entries.size(), testReadResultHandler.readCount.get());
}
Assert.assertTrue("ReadResult was not closed when the AsyncReadResultProcessor was closed.", rr.isClosed());
}
use of java.util.function.Supplier in project pravega by pravega.
the class AsyncReadResultProcessorTests method testReadFailures.
/**
* Tests the AsyncReadResultProcessor when it encounters read failures.
*/
@Test
public void testReadFailures() throws Exception {
// Pre-generate some entries.
final int totalLength = 1000;
final Semaphore barrier = new Semaphore(0);
// Setup an entry provider supplier that returns Future Reads, which will eventually fail.
StreamSegmentReadResult.NextEntrySupplier supplier = (offset, length) -> {
Supplier<ReadResultEntryContents> entryContentsSupplier = () -> {
barrier.acquireUninterruptibly();
throw new IntentionalException("Intentional");
};
return new TestFutureReadResultEntry(offset, length, entryContentsSupplier, executorService());
};
// Start an AsyncReadResultProcessor.
@Cleanup StreamSegmentReadResult rr = new StreamSegmentReadResult(0, totalLength, supplier, "");
TestReadResultHandler testReadResultHandler = new TestReadResultHandler(new ArrayList<>());
try (AsyncReadResultProcessor rp = AsyncReadResultProcessor.process(rr, testReadResultHandler, executorService())) {
barrier.release();
// Wait for it to complete, and then verify that no errors have been recorded via the callbacks.
AssertExtensions.assertThrows("Processor did not complete with the expected failure.", () -> testReadResultHandler.completed.get(TIMEOUT.toMillis(), TimeUnit.MILLISECONDS), ex -> Exceptions.unwrap(ex) instanceof IntentionalException);
Assert.assertEquals("Unexpected number of reads processed.", 0, testReadResultHandler.readCount.get());
Assert.assertNotNull("No read failure encountered.", testReadResultHandler.error.get());
Assert.assertTrue("Unexpected type of exception was raised: " + testReadResultHandler.error.get(), testReadResultHandler.error.get() instanceof IntentionalException);
}
Assert.assertTrue("ReadResult was not closed when the AsyncReadResultProcessor was closed.", rr.isClosed());
}
use of java.util.function.Supplier in project pravega by pravega.
the class ServiceBuilderConfigTests method testGetConfig.
/**
* Verifies the include(ConfigBuilder) and getConfig() work properly. This test follows a bit of an unusual approach
* in that it picks a few known config classes, populates them using their builders and reflection, then uses reflection
* once again to compare expected output (generated using their builders) with output from the ServiceBuilderConfig.getConfig().
* <p>
* This verifies that the namespacing inside ServiceBuilderConfig.builder() works correctly, as well as the constructors
* for various configs.
*/
@Test
@SuppressWarnings("unchecked")
public void testGetConfig() throws Exception {
// Select a few classes to test dynamically.
val testClasses = new HashMap<Class<?>, Supplier<ConfigBuilder<?>>>();
testClasses.put(ReadIndexConfig.class, ReadIndexConfig::builder);
testClasses.put(WriterConfig.class, WriterConfig::builder);
testClasses.put(MetricsConfig.class, MetricsConfig::builder);
testClasses.put(DurableLogConfig.class, DurableLogConfig::builder);
testClasses.put(ServiceConfig.class, ServiceConfig::builder);
// Value generator.
val nextValue = new AtomicInteger(1000 * 1000 * 1000);
// Create instances of each test class and dynamically assign their properties some arbitrary values
val expectedValues = new HashMap<Class<?>, Object>();
val b = ServiceBuilderConfig.builder();
for (Map.Entry<Class<?>, Supplier<ConfigBuilder<?>>> e : testClasses.entrySet()) {
Class<?> c = e.getKey();
ConfigBuilder<?> configBuilder = e.getValue().get();
for (Field f : c.getDeclaredFields()) {
// type contains one of the supported types.
if (Modifier.isStatic(f.getModifiers()) && f.getType().isAssignableFrom(Property.class) && isSupportedType(f.getGenericType().getTypeName())) {
Property p = (Property) f.get(null);
if (p.getDefaultValue() != null && p.getDefaultValue() instanceof Boolean) {
configBuilder.with(p, nextValue.incrementAndGet() % 2 == 0);
} else {
// Any number can be interpreted as a string or number.
configBuilder.with(p, Integer.toString(nextValue.incrementAndGet()));
}
}
}
// Collect the built config object for later use.
expectedValues.put(c, configBuilder.build());
// Include the builder in the main builder.
b.include(configBuilder);
}
// Create the ServiceBuilderConfig, and verify that the created Config classes (using getConfig()) match the
// expected ones.
val builderConfig = b.build();
for (Map.Entry<Class<?>, Supplier<ConfigBuilder<?>>> e : testClasses.entrySet()) {
Class<?> c = e.getKey();
Object expectedConfig = expectedValues.get(c);
Object actualConfig = builderConfig.getConfig(e.getValue());
// All the properties we care about are public getters with no arguments - only check those.
for (Method m : c.getDeclaredMethods()) {
if (m.getName().startsWith("get") && m.getParameterCount() == 0 && !Modifier.isStatic(m.getModifiers()) && Modifier.isPublic(m.getModifiers())) {
Object expectedValue = m.invoke(expectedConfig);
Object actualValue = m.invoke(actualConfig);
if (expectedValue == null) {
Assert.assertNull("Expected a null value for " + getPropName(c, m), actualValue);
} else {
Assert.assertNotNull("Not expected a null value for " + getPropName(c, m), actualValue);
}
if (isSupportedType(expectedValue)) {
Assert.assertEquals("Unexpected value for " + getPropName(c, m), expectedValue, actualValue);
}
}
}
}
}
Aggregations