All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.jet.pipeline.test.Assertions Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * Copyright (c) 2008-2021, Hazelcast, Inc. All Rights Reserved.
 *
 * 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 com.hazelcast.jet.pipeline.test;

import com.hazelcast.function.ConsumerEx;
import com.hazelcast.function.FunctionEx;
import com.hazelcast.jet.pipeline.BatchStage;
import com.hazelcast.jet.pipeline.StreamStage;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;

/**
 * Various assertions which can be used to assert items passing through the
 * pipeline for correctness. Each assertion also returns the stage it is
 * attached to so the assertions could be used in-line.
 * 

* The assertions in this class are to be used together with the {@code apply()} * operator on the pipeline. For assertions that can be used directly * as sinks, see {@link AssertionSinks}. * * @since Jet 3.2 */ public final class Assertions { private Assertions() { } /** * Asserts that the previous stage emitted the exact sequence of expected * items and nothing else. If the assertion fails, the job will fail with an * {@link AssertionError} with the given message. *

* Example: *

{@code
     * p.readFrom(TestSources.items(1, 2, 3, 4))
     *  .apply(Assertions.assertOrdered("unexpected values", Arrays.asList(1, 2, 3, 4)))
     *  .writeTo(Sinks.logger());
     * }
* * Note: Since Jet jobs are distributed, input from multiple upstream * processors is merged in a non-deterministic way. Therefore this assertion * is recommended only for testing of non-distributed sources. */ @Nonnull public static FunctionEx, BatchStage> assertOrdered( @Nullable String message, @Nonnull Collection expected ) { return stage -> { stage.writeTo(AssertionSinks.assertOrdered(message, expected)); return stage; }; } /** * Asserts that the previous stage emitted the exact sequence of expected * items and nothing else. If the assertion fails, the job will fail with an * {@link AssertionError}. *

* Example: *

{@code
     * p.readFrom(TestSources.items(1, 2, 3, 4))
     *  .apply(Assertions.assertOrderedArrays.asList(1, 2, 3, 4)))
     *  .writeTo(Sinks.logger());
     * }
* * Note: Since Jet jobs are distributed, input from multiple upstream * processors is merged in a non-deterministic way. Therefore this assertion * is recommended only for testing of non-distributed sources. */ @Nonnull public static FunctionEx, BatchStage> assertOrdered( @Nonnull Collection expected ) { return assertOrdered(null, expected); } /** * Asserts that the previous stage emitted the expected items in any order, * but nothing else. If the assertion fails, the job will fail with an * {@link AssertionError} with the given message. *

* Example: *

{@code
     * p.readFrom(TestSources.items(4, 3, 2, 1))
     *  .apply(Assertions.assertAnyOrder("unexpected values", Arrays.asList(1, 2, 3, 4)))
     *  .writeTo(Sinks.logger())
     * }
*/ @Nonnull public static FunctionEx, BatchStage> assertAnyOrder( @Nullable String message, @Nonnull Collection expected ) { return stage -> { stage.writeTo(AssertionSinks.assertAnyOrder(message, expected)); return stage; }; } /** * Asserts that the previous stage emitted the expected items in any order, * but nothing else. If the assertion fails, the job will fail with an * {@link AssertionError}. *

* Example: *

{@code
     * p.readFrom(TestSources.items(4, 3, 2, 1))
     *  .apply(Assertions.assertAnyOrder(Arrays.asList(1, 2, 3, 4)))
     *  .writeTo(Sinks.logger())
     * }
*/ @Nonnull public static FunctionEx, BatchStage> assertAnyOrder( @Nonnull Collection expected ) { return assertAnyOrder(null, expected); } /** * Asserts that the previous stage emitted all of the given items in any order. * If the assertion fails, the job will fail with an {@link AssertionError} with * the given message. *

* Example: *

{@code
     * p.readFrom(TestSources.items(4, 3, 2, 1))
     *  .apply(Assertions.assertAnyOrder(Arrays.asList(1, 3)))
     *  .writeTo(Sinks.logger())
     * }
*/ @Nonnull public static FunctionEx, BatchStage> assertContains( @Nullable String message, @Nonnull Collection expected ) { return stage -> { stage.writeTo(AssertionSinks.assertContains(message, expected)); return stage; }; } /** * Asserts that the previous stage emitted all of the given items in any order. * If the assertion fails, the job will fail with a {@link AssertionError} with * the given message. *

* Example: *

{@code
     * p.readFrom(TestSources.items(4, 3, 2, 1))
     *  .apply(Assertions.assertContains(Arrays.asList(1, 3)))
     *  .writeTo(Sinks.logger())
     * }
*/ @Nonnull public static FunctionEx, BatchStage> assertContains( @Nonnull Collection expected ) { return assertContains(null, expected); } /** * Collects all the received items in a list and once the upstream stage is * completed, it executes the assertion supplied by {@code assertFn}. If no * items were collected, it will be called with empty list. *

* Example: *

{@code
     * p.readFrom(TestSources.items(1, 2, 3, 4))
     *  .apply(Assertions.assertCollected(items ->
     *          assertTrue("expected minimum of 4 items", items.size() >= 4)))
     *  .writeTo(Sinks.logger())
     * }
* * Note: This assertion is not usable in streaming jobs. For the streaming * equivalent see {@link #assertCollectedEventually}. */ @Nonnull public static FunctionEx, BatchStage> assertCollected( @Nonnull ConsumerEx> assertFn ) { return stage -> { stage.writeTo(AssertionSinks.assertCollected(assertFn)); return stage; }; } /** * Collects all the received items into a list and runs the {@code assertFn} * every time a new item is received. An {@link AssertionError} thrown from * the {@code assertFn} will be ignored until {@code timeoutSeconds} have * passed, after which the last {@code AssertionError} will be rethrown. * If {@code assertFn} throws any other exception, it will be rethrown * immediately. *

* When {@code assertFn} completes without any error, the sink will throw * an {@link AssertionCompletedException} to indicate success. Exception is * used to terminate the job so that you can {@code join()} it. *

* Example: *

{@code
     * p.readFrom(TestSources.itemStream(10))
     *  .withoutTimestamps()
     *  .apply(assertCollectedEventually(5, c -> assertTrue("did not receive at least 20 items", c.size() > 20)));
     * }
* To use this assertion in a test, you need to catch the thrown exception and validate * that it's of the expected type as follows: *
{@code
     * try {
     *     jetInstance.newJob(p).join();
     *     Assert.fail("Job should have completed with an AssertionCompletedException, " +
     *             "but completed normally");
     * } catch (CompletionException e) {
     *     String errorMsg = e.getCause().getMessage();
     *     Assert.assertTrue(
     *             "Job was expected to complete with AssertionCompletedException, but completed with: " + e.getCause(),
     *             errorMsg.contains(AssertionCompletedException.class.getName())
     *     );
     * }
     * }
* * Note: This assertions requires that there are no other assertions in the * job as this one can complete the job before the other ones succeeded. */ @Nonnull public static FunctionEx, StreamStage> assertCollectedEventually( int timeout, @Nonnull ConsumerEx> assertFn ) { return stage -> { stage.writeTo(AssertionSinks.assertCollectedEventually(timeout, assertFn)); return stage; }; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy