= MicroProfile Reactive Streams Operators TCK
The MicroProfile Reactive Streams Operators TCK is provided to test compliance of implementations to the specification.
It provides a mechanism both for testing implementations independent from a MicroProfile container, as well as implementations provided by a container.
Any MicroProfile Reactive Streams Operators implementation must pass this test suite. The TCK uses TestNG or Arquillian.

== Hardware Requirements

All systems should meet the following recommended hardware requirements:

* CPU running at 2.0 GHz or higher
* 4 GB of RAM or more
* Network access to the Internet

== Software Requirements

You can run MicroProfile Reactive Streams Operators TCK on platforms running the Solaris, Linux, Windows, and Mac OS with the following software installed:

* Apache Maven
* JDK8+

== TCK Structure

There are two parts to the TCK, an API TCK, and an SPI TCK.
In addition, the whole TCK can either be run directly against an SPI implementation, or against a container with an Arquillian adapter.

The TCK uses TestNG for testing, and contains many test classes.
These test classes are brought together using TestNG `@Factory` annotated methods, so that running the TCK can be done by simply running a single test class that is a factory for the rest of the test classes.

Additionally, this TCK also uses the https://github.com/reactive-streams/reactive-streams-jvm/tree/master/tck[Reactive Streams TCK].
The Reactive Streams TCK is used to test Reactive Streams `Publishers`, `Subscribers` and `Processors` to ensure that they conform to the Reactive Streams spec.
Wherever possible, this TCK will use it to verify the `Publishers`, `Subscribers` and `Processors` built by the API.
For example, the returned `Processor` built by building a simple `map` stage is run through the Reactive Streams `Processor` TCK verification.

It should be noted that the Reactive Streams TCK is structured in such a way that each numbered requirement in the Reactive Streams specification has a test, even if that requirement is untestable by the TCK, or if its optional. In the case where requirements are optional or untested, the Reactive Streams TCK skips the test. Consequently, when running this TCK, there are a significant number of skipped tests.

=== API TCK

This tests the API, to ensure that every API call results in the a graph with the right stages being built.
It also tests that the necessary validation, for example for nulls, is done on each API call.
The API TCK is particularly useful for clean room implementations that don't depend on the Eclipse MicroProfile Reactive Streams Operators API artifact.
Passing the API TCK ensures that different implementations of the SPI will be compatible with different implementations of the API.

The API TCK doesn't need an implementation of the SPI to run, and so can be run against any implementation of the API.
It is run as part of MicroProfile Reactive Streams Operators API's continuous integration.

=== Running the API TCK

The API TCK can be run by running the `org.eclipse.microprofile.reactive.streams.operators.tck.api.ReactiveStreamsApiVerification` class.
For convenience, implementations might decide to subclass this in their `src/test/java` folder, so that it gets automatically picked up and run by build tools like Maven.

=== SPI TCK

This tests implementations of the SPI, to ensure that each different stage defined by the SPI behaves correctly, and to ensure that the implementation of that stage conforms to the Reactive Streams specification.
In general, each stage has a verification test, which tests the behavior of that stage, error, completion and cancellation propagation, and anything else that is necessary for each stage.
Additionally, each stage defines one or more Reactive Streams TCK verification classes, which tests that the `Publisher`, `Processor` or `Subscriber` built by a graph that contains just that stage conforms to the Reactive Streams specification.

=== Running the SPI TCK

The SPI TCK can be run by running the whole TCK (this includes running the API TCK, since the SPI TCK uses the API to create the stages, it doesn't make sense to verify an SPI without verifying that the API on top of it is doing the right thing too).

The whole TCK can be run by creating a subclass of `org.eclipse.microprofile.reactive.streams.operators.tck.ReactiveStreamsTck`.
This requires passing an instance of `org.reactivestreams.tck.TestEnvironment` to the super constructor, which contains configuration like timeouts.
Typically, the timeouts set by using the default constructor for `TestEnvironment` should be satisfactory.
The `createEngine` method also needs to be implemented, this must create and return a `ReactiveStreamsEngine` for the TCK to test against.
Optionally, a `shutdownEngine` method can be overridden to shutdown the engine if it holds any resources like thread pools.

==== Using TestNG
To execute the TCK, implementors must:

1. Depend on the TCK artifact
2. Extend the  `org.eclipse.microprofile.reactive.streams.operators.tck.ReactiveStreamsTck` class


The TCK artifact is the following:

[source, xml]
----
<dependency>
    <groupId>org.eclipse.microprofile.reactive-streams-operators</groupId>
    <artifactId>microprofile-reactive-streams-operators-tck</artifactId>
    <version>${microprofile-reactive-streams.version}</version>
    <scope>test</scope>
</dependency>
----

In your test classes, add a class extending the `org.eclipse.microprofile.reactive.streams.operators.tck.ReactiveStreamsTck` class, such as:

[source, java]
----
package ...;

import org.eclipse.microprofile.reactive.streams.operators.tck.ReactiveStreamsTck;
import org.reactivestreams.tck.TestEnvironment;

// ...

/**
 * Executes the TCK again the implementation.
 */
public class ReactiveStreamsEngineImplTck extends ReactiveStreamsTck<MyEngine> {

    static TestEnvironment ENV = new TestEnvironment();

    public ReactiveStreamsEngineImplTck() {
        super(ENV);
    }

    @Override
    protected MyEngine createEngine() {
        return new MyEngine();
    }
     
    @Override
    protected void shutdownEngine(MyEngine engine) {
        engine.shutdown();
    }

}
----

For Maven project not using TestNG as their main test framework, the following configuration would allow running the regular tests and the TCK:

[source, xml]
----
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <executions>
        <execution>
            <id>default-test</id>
            <goals>
                <goal>test</goal>
            </goals>
            <configuration>
                <!-- Non TCK tests -->
                <excludes>
                    <exclude>**/tck/*</exclude>
                </excludes>
                <testNGArtifactName>none:none</testNGArtifactName>
            </configuration>
        </execution>
        <execution>
            <!-- TCK tests -->
            <id>tck</id>
            <goals>
                <goal>test</goal>
            </goals>
            <configuration>
                <includes>
                    <!-- Include your class extending ReactiveStreamsEngine -->
                    <include>**/tck/ReactiveStreamsEngineImplTck</include>
                </includes>
                <junitArtifactName>none:none</junitArtifactName>
            </configuration>
        </execution>
    </executions>
</plugin>
----

==== Using Arquillian

A test class for running the TCK in a MicroProfile container is provided so that containers can verify compliance with the spec.
This container verification comes also in the `org.eclipse.microprofile.reactive.streams:microprofile-reactive-streams-operators-tck` artifact, but the TCK is located in the `org.eclipse.microprofile.reactive.streams.operators.tck.arquillian` package.

To run this TCK, the container must provide a `ReactiveStreamsEngine` to be tested as an injectable `ApplicationScoped` bean, and the MicroProfile Reactive Streams Operators API must be on the classpath.
Having ensured this, the TCK can then be run by executing `org.eclipse.microprofile.reactive.streams.operators.tck.arquillian.ReactiveStreamsArquillianTck`.
This class deploys the TCK to an Arquillian compatible container, and then runs all the tests in the container in its own configured TestNG suite on the container.
