/* * Copyright (C) 2015 SoftIndex LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.datakernel.async; import io.datakernel.eventloop.Eventloop; import org.junit.Test; import java.util.HashMap; import java.util.Map; import static io.datakernel.eventloop.FatalErrorHandlers.rethrowOnAnyError; import static org.junit.Assert.assertEquals; public class ParallelAsyncExecutorTest { private static class ExecutionInfo { private final long startTimestamp; private final long endTimestamp; public ExecutionInfo(long startTimestamp, long endTimestamp) { this.startTimestamp = startTimestamp; this.endTimestamp = endTimestamp; } } @Test public void testSequential() throws Exception { AsyncExecutor executor = AsyncExecutors.sequentialExecutor(); Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError()); Map<Integer, ExecutionInfo> executionInfoMap = new HashMap<>(); int tasks = 5; for (int i = 0; i < tasks; ++i) { submitTestTask(executor, eventloop, executionInfoMap, i); } assertEquals(1, eventloop.getStats().getTasks().getScheduled().getCount()); eventloop.run(); for (int i = 1; i < tasks; ++i) { ExecutionInfo previous = executionInfoMap.get(i - 1); ExecutionInfo current = executionInfoMap.get(i); assertEquals(previous.endTimestamp, current.startTimestamp); } } @Test public void testParallel() throws Exception { int maxParallelism = 3; AsyncExecutor executor = AsyncExecutors.parallelExecutor(maxParallelism, 5); Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError()); Map<Integer, ExecutionInfo> executionInfoMap = new HashMap<>(); int tasks = 9; for (int i = 0; i < tasks; ++i) { submitTestTask(executor, eventloop, executionInfoMap, i); } assertEquals(true, executor.isSaturated()); assertEquals(maxParallelism, eventloop.getStats().getTasks().getScheduled().getCount()); eventloop.run(); for (int j = 0; j < tasks; j += maxParallelism) { for (int i = 1; i < maxParallelism; ++i) { ExecutionInfo previous = executionInfoMap.get(i + j - 1); ExecutionInfo current = executionInfoMap.get(i + j); assertEquals(previous.startTimestamp, current.startTimestamp); } } } private static void submitTestTask(AsyncExecutor executor, Eventloop eventloop, Map<Integer, ExecutionInfo> executionInfoMap, int n) { executor.submit(getTestTask(eventloop, n, executionInfoMap), IgnoreCompletionCallback.create()); } private static AsyncRunnable getTestTask(final Eventloop eventloop, final int n, final Map<Integer, ExecutionInfo> executionInfoMap) { return new AsyncRunnable() { @Override public void run(final CompletionCallback callback) { final long startTimestamp = eventloop.currentTimeMillis(); eventloop.schedule(eventloop.currentTimeMillis() + 10, new Runnable() { @Override public void run() { long endTimestamp = eventloop.currentTimeMillis(); executionInfoMap.put(n, new ExecutionInfo(startTimestamp, endTimestamp)); callback.setComplete(); } }); } }; } }