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

com.github.sbt.junit.jupiter.internal.event.Dispatcher Maven / Gradle / Ivy

The newest version!
/*
 * jupiter-interface
 *
 * Copyright (c) 2017, Michael Aichler.
 * 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.github.sbt.junit.jupiter.internal.event;

import com.github.sbt.junit.jupiter.api.JupiterTestFingerprint;
import com.github.sbt.junit.jupiter.api.JupiterTestListener;
import com.github.sbt.junit.jupiter.internal.Configuration;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.launcher.TestIdentifier;
import sbt.testing.*;

/**
 * Dispatches test events to SBT.
 *
 * @author Michael Aichler
 */
public class Dispatcher implements JupiterTestListener {

  private static final Fingerprint fingerprint = new JupiterTestFingerprint();

  private final EventHandler eventHandler;
  private final Map reportedIds = new ConcurrentHashMap<>();
  private final Map startTimes = new ConcurrentHashMap<>();
  private final String testSuiteName;

  public Dispatcher(Configuration configuration, EventHandler eventHandler) {

    this.eventHandler = eventHandler;
    this.testSuiteName = configuration.getTestSuiteName();
  }

  @Override
  public void executionSkipped(TestIdentifier identifier, String reason) {

    reportedIds.computeIfAbsent(
        identifier,
        key -> {
          final long duration = calculateDuration(key);
          final TaskName taskName = TaskName.of(testSuiteName, identifier);
          eventHandler.handle(new DispatchEvent(taskName, Status.Skipped, duration));
          return true;
        });
  }

  @Override
  public void executionStarted(TestIdentifier identifier) {

    startTimes.computeIfAbsent(identifier, key -> System.currentTimeMillis());
  }

  @Override
  public void executionFailed(String className, Throwable throwable) {

    final TaskName taskName = TaskName.of(testSuiteName, className);
    eventHandler.handle(new DispatchEvent(taskName, Status.Error, 0L, throwable));
  }

  @Override
  public void executionFiltered(TestDescriptor descriptor, String reason) {

    final TaskName taskName = TaskName.of(testSuiteName, TestIdentifier.from(descriptor));
    eventHandler.handle(new DispatchEvent(taskName, Status.Skipped, 0L));
  }

  @Override
  public void executionFinished(TestIdentifier identifier, TestExecutionResult result) {

    reportedIds.computeIfAbsent(
        identifier,
        key -> {
          final Status status;
          final Throwable throwable = result.getThrowable().orElse(null);
          final TaskName taskName = TaskName.of(testSuiteName, identifier);
          final long duration = calculateDuration(identifier);

          // dispatch only tests by default so that number of executed tests
          // match those from junit-interface

          boolean dispatch = identifier.isTest();

          switch (result.getStatus()) {
            case ABORTED:
              status = Status.Canceled;
              dispatch = true;
              break;
            case FAILED:
              status = Status.Failure;
              dispatch = true;
              break;
            case SUCCESSFUL:
              status = Status.Success;
              break;
            default:
              status = Status.Pending;
              dispatch = true;
              break;
          }

          if (dispatch) {
            eventHandler.handle(new DispatchEvent(taskName, status, duration, throwable));
          }

          return true;
        });
  }

  static class DispatchEvent implements Event {

    final Status status;
    final Throwable throwable;
    final long duration;
    final String className;
    final Selector selector;

    DispatchEvent(TaskName name, Status status, long duration) {
      this(name, status, duration, null);
    }

    DispatchEvent(TaskName name, Status status, long duration, Throwable throwable) {

      this.status = status;
      this.throwable = throwable;
      this.duration = duration;
      this.className = name.fullyQualifiedName();
      this.selector = toSelector(name);
    }

    /**
     * Converts the specified {@code taskName} to a selector.
     *
     * @param name The task name.
     * @return An appropriate selector instance.
     */
    static Selector toSelector(TaskName name) {

      String testName = name.testName();
      if (null != testName) {
        if (null != name.invocation()) {
          testName = testName + ":" + name.invocation();
        }
      }

      if (null != name.nestedSuiteId()) {
        if (null != name.testName()) {

          return new NestedTestSelector(name.nestedSuiteId(), name.testName());
        }

        return new NestedSuiteSelector(name.nestedSuiteId());
      }

      if (null != testName) {

        return new TestSelector(testName);
      }

      return new SuiteSelector();
    }

    @Override
    public String fullyQualifiedName() {

      return className;
    }

    @Override
    public Fingerprint fingerprint() {

      return fingerprint;
    }

    @Override
    public Selector selector() {

      return selector;
    }

    @Override
    public Status status() {

      return status;
    }

    @Override
    public OptionalThrowable throwable() {

      return Optional.ofNullable(throwable)
          .map(OptionalThrowable::new)
          .orElseGet(OptionalThrowable::new);
    }

    @Override
    public long duration() {

      return duration;
    }

    @Override
    public String toString() {

      return "DispatchEvent(" + status + ", " + className + ", " + selector + ')';
    }
  }

  private long calculateDuration(TestIdentifier identifier) {

    final long startTime = startTimes.getOrDefault(identifier, 0L);
    return (0L == startTime ? startTime : System.currentTimeMillis() - startTime);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy