/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.ignite.internal.testframework;

import static java.lang.Thread.sleep;
import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.WRITE;
import static java.util.function.Function.identity;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.fail;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.function.BooleanSupplier;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.apache.ignite.internal.lang.IgniteInternalException;
import org.apache.ignite.internal.lang.IgniteStringFormatter;
import org.apache.ignite.internal.lang.RunnableX;
import org.apache.ignite.internal.logger.IgniteLogger;
import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.thread.IgniteThreadFactory;
import org.apache.ignite.internal.thread.NamedThreadFactory;
import org.apache.ignite.internal.thread.ThreadOperation;
import org.apache.ignite.internal.util.ExceptionUtils;
import org.apache.ignite.lang.IgniteException;
import org.hamcrest.CustomMatcher;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.function.Executable;

/**
 * Utility class for tests.
 */
public final class IgniteTestUtils {
    private static final IgniteLogger LOG = Loggers.forClass(IgniteTestUtils.class);

    private static final int TIMEOUT_SEC = 30;

    /**
     * Set object field value via reflection.
     *
     * @param obj       Object to set field value to.
     * @param fieldName Field name to set value for.
     * @param val       New field value.
     * @throws IgniteInternalException In case of error.
     */
    public static void setFieldValue(Object obj, String fieldName, @Nullable Object val) throws IgniteInternalException {
        assert obj != null;
        assert fieldName != null;

        try {
            Class<?> cls = obj instanceof Class ? (Class<?>) obj : obj.getClass();

            Field field = cls.getDeclaredField(fieldName);

            boolean isFinal = (field.getModifiers() & Modifier.FINAL) != 0;

            boolean isStatic = (field.getModifiers() & Modifier.STATIC) != 0;

            /*
             * http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.5.3
             * If a final field is initialized to a compile-time constant in the field declaration,
             *   changes to the final field may not be observed.
             */
            if (isFinal && isStatic) {
                throw new IgniteInternalException("Modification of static final field through reflection.");
            }

            if (!field.canAccess(obj)) {
                field.setAccessible(true);
            }

            field.set(obj, val);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new IgniteInternalException("Failed to set object field [obj=" + obj + ", field=" + fieldName + ']', e);
        }
    }

    /**
     * Set object field value via reflection.
     *
     * @param obj       Object to set field value to.
     * @param cls       Class to get field from.
     * @param fieldName Field name to set value for.
     * @param val       New field value.
     * @throws IgniteInternalException In case of error.
     */
    public static void setFieldValue(Object obj, Class<?> cls, String fieldName, Object val) throws IgniteInternalException {
        assert fieldName != null;

        try {
            Field field = cls.getDeclaredField(fieldName);

            if (!field.canAccess(obj)) {
                field.setAccessible(true);
            }

            boolean isFinal = (field.getModifiers() & Modifier.FINAL) != 0;

            boolean isStatic = (field.getModifiers() & Modifier.STATIC) != 0;

            /*
             * http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.5.3
             * If a final field is initialized to a compile-time constant in the field declaration,
             *   changes to the final field may not be observed.
             */
            if (isFinal && isStatic) {
                throw new IgniteInternalException("Modification of static final field through reflection.");
            }

            field.set(obj, val);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new IgniteInternalException("Failed to set object field [obj=" + obj + ", field=" + fieldName + ']', e);
        }
    }

    /**
     * Finds a field in the given {@code target} object of the {@code declaredClass} type.
     *
     * @param target        target object from which to get field ({@code null} for static methods)
     * @param declaredClass class on which the field is declared
     * @param fieldName     name of the field
     * @return field
     */
    public static Field getField(@Nullable Object target, Class<?> declaredClass, String fieldName) {
        Field field;
        try {
            field = declaredClass.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            throw new IgniteInternalException("Did not find a field", e);
        }

        if (!field.canAccess(target)) {
            field.setAccessible(true);
        }

        return field;
    }

    /**
     * Returns field value.
     *
     * @param target        target object from which to get field value ({@code null} for static methods)
     * @param declaredClass class on which the field is declared
     * @param fieldName     name of the field
     * @return field value
     */
    public static <T> T getFieldValue(@Nullable Object target, Class<?> declaredClass, String fieldName) {
        try {
            return (T) getField(target, declaredClass, fieldName).get(target);
        } catch (IllegalAccessException e) {
            throw new IgniteInternalException("Cannot get field value", e);
        }
    }

    /**
     * Get object field value via reflection.
     *
     * @param obj Object or class to get field value from.
     * @param fieldNames Field names to get value for: obj->field1->field2->...->fieldN.
     * @param <T> Expected field class.
     * @return Field value.
     * @throws IgniteInternalException In case of error.
     */
    public static <T> T getFieldValue(@Nullable Object obj, String... fieldNames) {
        assert obj != null;
        assert fieldNames != null;
        assert fieldNames.length >= 1;

        for (String fieldName : fieldNames) {
            Class<?> cls = obj instanceof Class ? (Class<?>) obj : obj.getClass();

            try {
                obj = getFieldValue(obj, cls, fieldName);
            } catch (IgniteInternalException e) {
                // Resolve inner class, if not an inner field.
                Class<?> innerCls = getInnerClass(cls, fieldName);

                if (innerCls == null) {
                    throw new IgniteInternalException("Failed to get object field [obj=" + obj
                            + ", fieldNames=" + Arrays.toString(fieldNames) + ']', e);
                }

                obj = innerCls;
            }
        }

        return (T) obj;
    }

    /**
     * Get inner class by its name from the enclosing class.
     *
     * @param parentCls Parent class to resolve inner class for.
     * @param innerClsName Name of the inner class.
     * @return Inner class.
     */
    @Nullable public static <T> Class<T> getInnerClass(Class<?> parentCls, String innerClsName) {
        for (Class<?> cls : parentCls.getDeclaredClasses()) {
            if (innerClsName.equals(cls.getSimpleName())) {
                return (Class<T>) cls;
            }
        }

        return null;
    }

    /**
     * Checks whether runnable throws exception, which is itself of a specified class.
     *
     * @param cls Expected exception class.
     * @param run Runnable to check.
     * @param errorMessageFragment Fragment of the error text in the expected exception, {@code null} if not to be checked.
     * @return Thrown throwable.
     */
    public static Throwable assertThrows(
            Class<? extends Throwable> cls,
            Executable run,
            @Nullable String errorMessageFragment
    ) {
        Throwable throwable = Assertions.assertThrows(cls, run);

        if (errorMessageFragment != null) {
            assertThat(throwable.getMessage(), containsString(errorMessageFragment));
        }

        return throwable;
    }

    /**
     * Checks whether runnable throws the correct {@link IgniteException}, which is itself of a specified class.
     *
     * @param expectedClass Expected exception class.
     * @param expectedErrorCode Expected error code of the {@link IgniteException}.
     * @param run Runnable to check.
     * @param errorMessageFragment Fragment of the error text in the expected exception, {@code null} if not to be checked.
     * @return Thrown throwable.
     */
    public static Throwable assertThrowsWithCode(
            Class<? extends IgniteException> expectedClass,
            int expectedErrorCode,
            Executable run,
            @Nullable String errorMessageFragment
    ) {
        try {
            run.execute();
        } catch (Throwable throwable) {
            try {
                assertInstanceOf(expectedClass, throwable);
            } catch (AssertionError err) {
                // An AssertionError from assertInstanceOf has nothing but a class name of the original exception.
                AssertionError assertionError = new AssertionError(err);

                assertionError.addSuppressed(throwable);

                throw assertionError;
            }

            IgniteException igniteException = (IgniteException) throwable;
            assertEquals(expectedErrorCode, igniteException.code(), "Invalid error code: " + igniteException.codeAsString());

            if (errorMessageFragment != null) {
                assertThat(throwable.getMessage(), containsString(errorMessageFragment));
            }

            return throwable;
        }

        throw new AssertionError("Exception has not been thrown.");
    }

    /**
     * Checks whether runnable throws exception, which is itself of a specified class, or has a cause of the specified class.
     *
     * @param run Runnable to check.
     * @param cls Expected exception class.
     * @return Thrown throwable.
     */
    public static Throwable assertThrowsWithCause(
            RunnableX run,
            Class<? extends Throwable> cls
    ) {
        return assertThrowsWithCause(run, cls, null);
    }

    /**
     * Checks whether runnable throws exception, which is itself of a specified class, or has a cause of the specified class.
     *
     * @param run Runnable to check.
     * @param cls Expected exception class.
     * @param msg Message text that should be in cause (if {@code null}, message won't be checked).
     * @return Thrown throwable.
     */
    public static Throwable assertThrowsWithCause(
            RunnableX run,
            Class<? extends Throwable> cls,
            @Nullable String msg
    ) {
        try {
            run.run();
        } catch (Throwable e) {
            if (!hasCause(e, cls, msg)) {
                fail("Exception is neither of a specified class, nor has a cause of the specified class: " + cls, e);
            }

            return e;
        }

        throw new AssertionError("Exception has not been thrown.");
    }

    /**
     * Checks if passed in {@code 'Throwable'} has given class in {@code 'cause'} hierarchy
     * <b>including</b> that throwable itself.
     *
     * <p>Note that this method follows includes {@link Throwable#getSuppressed()} into check.
     *
     * @param t   Throwable to check.
     * @param cls Cause classes to check.
     * @param messageFragment Fragment that must be a substring of a cause message (if {@code null}, message won't be checked).
     * @return {@code True} if one of the causing exception is an instance of passed in classes, {@code false} otherwise.
     */
    public static boolean hasCause(
            Throwable t,
            Class<?> cls,
            @Nullable String messageFragment
    ) {
        for (Throwable th = t; th != null; th = th.getCause()) {
            if (cls.isAssignableFrom(th.getClass())) {
                if (messageFragment == null) {
                    return true;
                }

                if (th.getMessage() != null && th.getMessage().contains(messageFragment)) {
                    return true;
                }
            }

            for (Throwable n : th.getSuppressed()) {
                if (hasCause(n, cls, messageFragment)) {
                    return true;
                }
            }

            if (th.getCause() == th) {
                break;
            }
        }

        return false;
    }

    /**
     * Checks if passed in {@code 'Throwable'} has given class in {@code 'cause'} hierarchy
     * <b>including</b> that throwable itself.
     *
     * <p>Note that this method follows includes {@link Throwable#getSuppressed()} into check.
     *
     * @param t   Throwable to check.
     * @param cls Cause classes to check.
     * @return reference to the cause error if found, otherwise returns {@code null}.
     */
    public static <T extends Throwable> @Nullable T cause(Throwable t, Class<T> cls) {
        return cause(t, cls, null);
    }

    /**
     * Checks if passed in {@code 'Throwable'} has given class in {@code 'cause'} hierarchy
     * <b>including</b> that throwable itself.
     *
     * <p>Note that this method follows includes {@link Throwable#getSuppressed()} into check.
     *
     * @param t   Throwable to check.
     * @param cls Cause classes to check.
     * @param msg Message text that should be in cause (if {@code null}, message won't be checked).
     * @return reference to the cause error if found, otherwise returns {@code null}.
     */
    public static <T extends Throwable> @Nullable T cause(
            Throwable t,
            Class<T> cls,
            @Nullable String msg
    ) {
        for (Throwable th = t; th != null; th = th.getCause()) {
            if (cls.isAssignableFrom(th.getClass())) {
                if (msg != null) {
                    if (th.getMessage() != null && th.getMessage().contains(msg)) {
                        return (T) th;
                    } else {
                        continue;
                    }
                }

                return (T) th;
            }

            if (th.getCause() == th) {
                break;
            }
        }

        return null;
    }

    /**
     * Runs runnable task asyncronously.
     *
     * @param task Runnable.
     * @return Future with task result.
     */
    public static CompletableFuture<Void> runAsync(RunnableX task) {
        return runAsync(task, "async-runnable-runner");
    }

    /**
     * Runs runnable task asyncronously.
     *
     * @param task Runnable.
     * @return Future with task result.
     */
    public static CompletableFuture<Void> runAsync(RunnableX task, String threadName) {
        return runAsync(() -> {
            try {
                task.run();
            } catch (Throwable e) {
                sneakyThrow(e);
            }

            return null;
        }, threadName);
    }

    /**
     * Runs callable task asyncronously.
     *
     * @param task Callable.
     * @return Future with task result.
     */
    public static <T> CompletableFuture<T> runAsync(Callable<T> task) {
        return runAsync(task, "async-callable-runner");
    }

    /**
     * Runs callable task asyncronously.
     *
     * @param task Callable.
     * @param threadName Thread name.
     * @return Future with task result.
     */
    public static <T> CompletableFuture<T> runAsync(Callable<T> task, String threadName) {
        ThreadFactory thrFactory = IgniteThreadFactory.withPrefix(threadName, LOG, ThreadOperation.values());

        CompletableFuture<T> fut = new CompletableFuture<T>();

        thrFactory.newThread(() -> {
            try {
                // Execute task.
                T res = task.call();

                fut.complete(res);
            } catch (Throwable e) {
                fut.completeExceptionally(e);
            }
        }).start();

        return fut;
    }

    /**
     * Executes an asynchronous operation in a thread that is allowed to execute any thread operation.
     *
     * @param operation Operation to execute.
     * @return Whatever the operation returns.
     */
    public static <T> CompletableFuture<T> bypassingThreadAssertionsAsync(Supplier<CompletableFuture<T>> operation) {
        return runAsync(operation::get).thenCompose(identity());
    }

    /**
     * Executes a synchronous operation in a thread that is allowed to execute any thread operation.
     *
     * @param operation Operation to execute.
     * @return Whatever the operation returns.
     */
    public static <T> T bypassingThreadAssertions(Supplier<T> operation) {
        return await(runAsync(operation::get));
    }

    /**
     * Executes a synchronous operation in a thread that is allowed to execute any thread operation.
     *
     * @param operation Operation to execute.
     */
    public static void bypassingThreadAssertions(Runnable operation) {
        await(runAsync(operation::run));
    }

    /**
     * Runs callable tasks each in separate threads.
     *
     * @param calls Callable tasks.
     * @param threadFactory Thread factory.
     * @return Execution time in milliseconds.
     * @throws Exception If failed.
     */
    public static long runMultiThreaded(Iterable<Callable<?>> calls, ThreadFactory threadFactory) throws Exception {
        Collection<Thread> threads = new ArrayList<>();

        Collection<CompletableFuture<?>> futures = new ArrayList<>();

        for (Callable<?> task : calls) {
            CompletableFuture<?> fut = new CompletableFuture<>();

            futures.add(fut);

            threads.add(threadFactory.newThread(() -> {
                try {
                    // Execute task.
                    task.call();

                    fut.complete(null);
                } catch (Throwable e) {
                    fut.completeExceptionally(e);
                }
            }));
        }

        long time = System.currentTimeMillis();

        for (Thread t : threads) {
            t.start();
        }

        // Wait threads finish their job.
        try {
            for (Thread t : threads) {
                t.join();
            }
        } catch (InterruptedException e) {
            for (Thread t : threads) {
                t.interrupt();
            }

            throw e;
        }

        time = System.currentTimeMillis() - time;

        for (CompletableFuture<?> fut : futures) {
            fut.join();
        }

        return time;
    }

    /**
     * Runs callable tasks in specified number of threads.
     *
     * @param call Callable.
     * @param threadNum Number of threads.
     * @param threadName Thread names.
     * @return Execution time in milliseconds.
     * @throws Exception If failed.
     */
    public static long runMultiThreaded(Callable<?> call, int threadNum, String threadName) throws Exception {
        List<Callable<?>> calls = Collections.nCopies(threadNum, call);

        NamedThreadFactory threadFactory = new NamedThreadFactory(threadName, LOG);

        return runMultiThreaded(calls, threadFactory);
    }

    /**
     * Runs runnable object in specified number of threads.
     *
     * @param run Target runnable.
     * @param threadNum Number of threads.
     * @param threadName Thread name.
     * @return Future for the run. Future returns execution time in milliseconds.
     */
    public static CompletableFuture<Long> runMultiThreadedAsync(Runnable run, int threadNum, String threadName) {
        return runMultiThreadedAsync(() -> {
            run.run();

            return null;
        }, threadNum, threadName);
    }

    /**
     * Runs callable object in specified number of threads.
     *
     * @param call Callable.
     * @param threadNum Number of threads.
     * @param threadName Thread names.
     * @return Future for the run. Future returns execution time in milliseconds.
     */
    public static CompletableFuture<Long> runMultiThreadedAsync(Callable<?> call, int threadNum, String threadName) {
        List<Callable<?>> calls = Collections.<Callable<?>>nCopies(threadNum, call);

        NamedThreadFactory threadFactory = new NamedThreadFactory(threadName, LOG);

        return runAsync(() -> runMultiThreaded(calls, threadFactory));
    }

    /**
     * Waits for the condition.
     *
     * @param cond Condition.
     * @param timeoutMillis Timeout in milliseconds.
     * @return {@code True} if the condition was satisfied within the timeout.
     * @throws InterruptedException If waiting was interrupted.
     */
    public static boolean waitForCondition(BooleanSupplier cond, long timeoutMillis) throws InterruptedException {
        return waitForCondition(cond, 10, timeoutMillis);
    }

    /**
     * Waits for the condition.
     *
     * @param cond Condition.
     * @param sleepMillis Sleep im milliseconds.
     * @param timeoutMillis Timeout in milliseconds.
     * @return {@code True} if the condition was satisfied within the timeout.
     * @throws InterruptedException If waiting was interrupted.
     */
    @SuppressWarnings("BusyWait")
    public static boolean waitForCondition(BooleanSupplier cond, long sleepMillis, long timeoutMillis) throws InterruptedException {
        long stop = System.currentTimeMillis() + timeoutMillis;

        while (System.currentTimeMillis() < stop) {
            if (cond.getAsBoolean()) {
                return true;
            }

            sleep(sleepMillis);
        }

        return false;
    }

    /**
     * Returns random BitSet.
     *
     * @param rnd  Random generator.
     * @param bits Amount of bits in bitset.
     * @return Random BitSet.
     */
    public static BitSet randomBitSet(Random rnd, int bits) {
        BitSet set = new BitSet();

        for (int i = 0; i < bits; i++) {
            if (rnd.nextBoolean()) {
                set.set(i);
            }
        }

        return set;
    }

    /**
     * Returns random byte array.
     *
     * @param rnd Random generator.
     * @param len Byte array length.
     * @return Random byte array.
     */
    public static byte[] randomBytes(Random rnd, int len) {
        byte[] data = new byte[len];
        rnd.nextBytes(data);

        return data;
    }

    /**
     * Returns random string.
     *
     * @param rnd Random generator.
     * @param len String length.
     * @return Random string.
     */
    public static String randomString(Random rnd, int len) {
        StringBuilder sb = new StringBuilder();

        while (sb.length() < len) {
            char pt = (char) rnd.nextInt(Character.MAX_VALUE + 1);

            if (Character.isDefined(pt)
                    && Character.getType(pt) != Character.PRIVATE_USE
                    && !Character.isSurrogate(pt)
            ) {
                sb.append(pt);
            }
        }

        return sb.toString();
    }

    /**
     * Creates a unique Ignite node name for the given test.
     *
     * @param testInfo Test info.
     * @param idx Node index.
     *
     * @return Node name.
     */
    public static String testNodeName(TestInfo testInfo, int idx) {
        String testMethodName = testInfo.getTestMethod().map(Method::getName).orElse("null");
        String testClassName = testInfo.getTestClass().map(Class::getSimpleName).orElse("null");

        return IgniteStringFormatter.format("{}_{}_{}",
                        shortTestMethodName(testClassName),
                        shortTestMethodName(testMethodName),
                        idx);
    }

    /**
     * Returns a short version of the method name, such as "testShortMethodName" to "tsmn".
     *
     * @param methodName Method name for example "testShortMethodName".
     */
    public static String shortTestMethodName(String methodName) {
        assert !methodName.isBlank() : methodName;

        StringBuilder sb = new StringBuilder();

        char[] chars = methodName.trim().toCharArray();

        sb.append(chars[0]);

        for (int i = 1; i < chars.length; i++) {
            char c = chars[i];

            if (Character.isUpperCase(c)) {
                sb.append(c);
            }
        }

        return sb.toString().toLowerCase();
    }

    /**
     * Throw an exception as if it were unchecked.
     *
     * <p>This method erases type of the exception in the thrown clause, so checked exception could be thrown without need to wrap it with
     * unchecked one or adding a similar throws clause to the upstream methods.
     */
    public static <E extends Throwable> void sneakyThrow(Throwable e) throws E {
        throw (E) e;
    }

    /**
     * Awaits completion of the given stage and returns its result.
     *
     * @param stage The stage.
     * @param timeout Maximum time to wait.
     * @param unit Time unit of the timeout argument.
     * @param <T> Type of the result returned by the stage.
     * @return A result of the stage.
     */
    @SuppressWarnings("UnusedReturnValue")
    public static <T> T await(CompletionStage<T> stage, long timeout, TimeUnit unit) {
        try {
            return stage.toCompletableFuture().get(timeout, unit);
        } catch (Throwable e) {
            // In tests, we generally interested in original exception,
            // rather than ExecutionException generated by the future's
            // contract. But topmost frame keeps important information
            // about failed operation in clients code. So, let's keep
            // this information in a kinda unusual yet sufficient for
            // further debug way
            Throwable original = ExceptionUtils.unwrapCause(e);

            if (original != e) {
                original.addSuppressed(new RuntimeException("This is a trimmed root"));
            }

            sneakyThrow(original);
        }

        throw new AssertionError("Should not get here");
    }

    /**
     * Awaits completion of the given stage and returns its result.
     *
     * @param stage The stage.
     * @param <T> Type of the result returned by the stage.
     * @return A result of the stage.
     */
    @SuppressWarnings("UnusedReturnValue")
    public static <T> T await(CompletionStage<T> stage) {
        return await(stage, TIMEOUT_SEC, TimeUnit.SECONDS);
    }

    /**
     * {@link #runRace(long, RunnableX...)} with default timeout of 10 seconds.
     */
    public static void runRace(RunnableX... actions) {
        runRace(TimeUnit.SECONDS.toMillis(10), actions);
    }

    /**
     * Runs all actions, each in a separate thread, having a {@link CyclicBarrier} before calling {@link RunnableX#run()}.
     * Waits for threads completion or fails with the assertion if timeout exceeded.
     *
     * @throws AssertionError In case of timeout or if any of the runnables thrown an exception.
     */
    public static void runRace(long timeoutMillis, RunnableX... actions) {
        int length = actions.length;

        if (length == 0) {
            return; // Nothing to run.
        }

        CyclicBarrier barrier = new CyclicBarrier(length);

        Set<Throwable> throwables = ConcurrentHashMap.newKeySet();

        Thread[] threads = IntStream.range(0, length).mapToObj(i -> new Thread(() -> {
            try {
                barrier.await();

                actions[i].run();
            } catch (Throwable e) {
                throwables.add(e);
            }
        })).toArray(Thread[]::new);

        Stream.of(threads).forEach(Thread::start);

        long endTs = System.currentTimeMillis() + timeoutMillis;

        try {
            for (Thread thread : threads) {
                thread.join(Math.max(1, endTs - System.currentTimeMillis()));

                if (thread.isAlive()) {
                    throw new InterruptedException(); // Interrupt all actions and fail the race.
                }
            }
        } catch (InterruptedException e) {
            for (Thread thread : threads) {
                thread.interrupt();
            }

            fail("Race operations took too long.");
        }

        if (!throwables.isEmpty()) {
            AssertionError assertionError = new AssertionError("One or several threads have failed.");

            for (Throwable throwable : throwables) {
                assertionError.addSuppressed(throwable);
            }

            throw assertionError;
        }
    }

    /**
     * Returns a file system path for a resource name.
     *
     * @param cls A class.
     * @param resourceName A resource name.
     * @return A file system path matching the path component of the resource URL.
     */
    public static String getResourcePath(Class<?> cls, String resourceName) {
        return getPath(cls.getClassLoader().getResource(resourceName)).toString();
    }

    /**
     * Converts a URL to a file system path.
     *
     * <p>This method is needed to get a proper file system name on the Windows platform. For portable code
     * it should be used instead of URL::getPath().
     *
     * <p>For example, given a URL <i>file:///C:/dir/file.ext</i>, this method returns a Windows-specific
     * path: <i>C:\dir\file.ext</i>.
     *
     * <p>While the URL::getPath() method returns a path that will not work for file system API on Windows:
     * <i>/C:/dir/file.ext</i>.
     *
     * <p>There is no such problem on UNIX-like systems where given an URL <i>file:///dir/file.ext</i>,
     * both methods return the same result: <i>/dir/file.ext</i>
     *
     * @param url A resource URL.
     * @return A file system path matching the path component of the URL.
     */
    public static Path getPath(URL url) {
        try {
            return Path.of(url.toURI());
        } catch (URISyntaxException e) {
            throw new RuntimeException(e); // Shouldn't happen if the URL is obtained from the class loader.
        }
    }

    /**
     * Adds escape characters before backslashes in a path (on Windows), e.g. for the HOCON config parser.
     *
     * <p>For example, given a path argument <i>C:\dir\file.ext</i>, this method returns <i>C:\\dir\\file.ext</i>.
     *
     * @param path A path string.
     * @return A path string with escaped backslashes.
     */
    public static String escapeWindowsPath(String path) {
        return path.replace("\\", "\\\\");
    }

    /**
     * Generate file with dummy content with provided size.
     *
     * @param file File path.
     * @param fileSize File size in bytes.
     * @throws IOException if an I/O error is thrown.
     */
    public static void fillDummyFile(Path file, long fileSize) throws IOException {
        try (SeekableByteChannel channel = Files.newByteChannel(file, WRITE, CREATE)) {
            channel.position(fileSize - 4);

            ByteBuffer buf = ByteBuffer.allocate(4).putInt(2);
            buf.rewind();
            channel.write(buf);
        }
    }

    /**
     * Predicate matcher.
     *
     * @param <DataT> Data type.
     */
    public static class PredicateMatcher<DataT> extends CustomMatcher<DataT> {
        /** Predicate. */
        private final Predicate<DataT> predicate;

        /**
         * Constructor.
         *
         * @param pred Predicate.
         * @param msg Error description.
         */
        public PredicateMatcher(Predicate<DataT> pred, String msg) {
            super(msg);

            predicate = pred;
        }

        /** {@inheritDoc} */
        @Override
        public boolean matches(Object o) {
            return predicate.test((DataT) o);
        }
    }
}
