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

com.github.dakusui.actionunit.actions.TestAction Maven / Gradle / Ivy

package com.github.dakusui.actionunit.actions;

import com.github.dakusui.actionunit.core.Action;
import com.github.dakusui.actionunit.core.Context;
import com.github.dakusui.actionunit.exceptions.ActionAssertionError;
import com.github.dakusui.actionunit.helpers.InternalUtils;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public interface TestAction extends Action, Context {
  Action given();

  Action when();

  Action then();

  class Builder {
    private final int            id;
    private       Supplier    input;
    private       Function operation;
    private       Predicate   check;

    public Builder(int id) {
      this.id = id;
    }

    public Builder given(String description, Supplier input) {
      Objects.requireNonNull(input);
      this.input = new Supplier() {
        @Override
        public I get() {
          return input.get();
        }

        @Override
        public String toString() {
          return description;
        }
      };
      return this;
    }

    public Builder when(String description, Function operation) {
      Objects.requireNonNull(operation);
      this.operation = new Function() {
        @Override
        public O apply(I i) {
          return operation.apply(i);
        }

        @Override
        public String toString() {
          return description;
        }

      };
      return this;
    }

    public TestAction then(String description, Predicate check) {
      Objects.requireNonNull(check);
      this.check = new Predicate() {
        @Override
        public boolean test(O o) {
          return check.test(o);
        }

        @Override
        public String toString() {
          return description;
        }
      };
      Objects.requireNonNull(this.input);
      Objects.requireNonNull(this.operation);
      Objects.requireNonNull(this.check);
      return new Base<>(id, this);
    }

  }

  class Base extends ActionBase implements TestAction {
    private final AtomicReference> input  = new AtomicReference<>(
        () -> {
          throw new IllegalStateException("input is not set yet.");
        });
    private final AtomicReference> output = new AtomicReference<>(
        () -> {
          throw new IllegalStateException("output is not set yet.");
        });
    private final Builder builder;

    public Base(int id, Builder builder) {
      super(id);
      this.builder = builder;
    }

    public I input() {
      return input.get().get();
    }

    O output() {
      return output.get().get();
    }

    Function operation() {
      return builder.operation;
    }

    Predicate check() {
      return builder.check;
    }

    @Override
    public Action given() {
      return Context.Internal.named(0, "Given",
          Context.Internal.simple(
              0,
              builder.input.toString(),
              () -> Base.this.input.set(InternalUtils.describable(builder.input.toString(), builder.input.get())))
      );
    }

    @Override
    public Action when() {
      return Context.Internal.named(1, "When",
          Context.Internal.simple(
              0,
              builder.operation.toString(),
              () -> output.set(
                  () -> builder.operation.apply(Base.this.input())
              )
          ));
    }


    @Override
    public Action then() {
      return Context.Internal.named(2, "Then",
          Context.Internal.simple(0,
              check().toString(),
              () -> {
                if (!check().test(output()))
                  throw new ActionAssertionError(String.format(
                      "%s(x) %s was not satisfied because %s(x)=<%s>; x=<%s>",
                      operation(),
                      check(),
                      operation(),
                      output(),
                      input()
                  ));
              }
          ));
    }

    @Override
    public void accept(Visitor visitor) {
      visitor.visit(this);
    }
  }
}