// Verify that the test method level events for the test methods declared in the specified class
  // run in the same
  // thread for each instance of the test class for the specified suite and test
  public static void verifyEventsForTestMethodsRunInTheSameThread(
      Class<?> testClass, String suiteName, String testName) {

    for (Method method : testClass.getMethods()) {
      if (method.getDeclaringClass().equals(testClass)) {
        Multimap<Object, EventLog> testMethodEventLogs =
            getTestMethodEventLogsForMethod(
                suiteName, testName, testClass.getCanonicalName(), method.getName());

        for (Object instanceKey : testMethodEventLogs.keySet()) {
          long threadId = -1;

          for (EventLog eventLog : testMethodEventLogs.get(instanceKey)) {
            if (threadId == -1) {
              threadId = eventLog.getThreadId();
            } else {
              assertEquals(
                  eventLog.getThreadId(),
                  threadId,
                  "All of the method level events for the test "
                      + "method "
                      + method.getName()
                      + " in the test class "
                      + testClass.getCanonicalName()
                      + " for the test "
                      + suiteName
                      + " should be run in the same thread");
            }
          }
        }
      }
    }
  }
  // Verify that the list of event logs all have different thread IDS. Print the specified failure
  // message if the
  // assertion on the thread IDs fails.
  public static void verifyDifferentThreadIdsForEvents(
      List<EventLog> eventLogs, String failMessage) {
    List<Long> threadIds = new ArrayList<>();

    for (EventLog eventLog : eventLogs) {
      assertFalse(threadIds.contains(eventLog.getThreadId()), failMessage);
      threadIds.add(eventLog.getThreadId());
    }
  }
 // Verify that the list of event logs all have the same thread ID. Print the specified failure
 // message if the
 // assertion on the event type fails.
 public static void verifySameThreadIdForAllEvents(List<EventLog> eventLogs, String failMessage) {
   long threadId = -1;
   for (EventLog eventLog : eventLogs) {
     if (threadId == -1) {
       threadId = eventLog.getThreadId();
     } else {
       assertEquals(eventLog.getThreadId(), threadId, failMessage);
     }
   }
 }
 // Verify that the specified event logs all have timestamps between the specified earlier and
 // later event logs.
 // Print the specified failure message if the assertion on the timestamps fails.
 public static void verifyEventsOccurBetween(
     EventLog earlierEventLog,
     List<EventLog> inBetweenEventLogs,
     EventLog laterEventLog,
     String failMessage) {
   for (EventLog eventLog : inBetweenEventLogs) {
     assertTrue(
         eventLog.getTimeOfEvent() > earlierEventLog.getTimeOfEvent()
             && eventLog.getTimeOfEvent() < laterEventLog.getTimeOfEvent(),
         failMessage);
   }
 }
  // Helper which verifies that the specified lists of test method level events are associated with
  // the same methods
  private static void verifyEventsBelongToSameMethods(
      List<EventLog> firstEventLogs, List<EventLog> secondEventLogs, String faiMessage) {

    List<String> methodNames = new ArrayList<>();

    for (EventLog eventLog : firstEventLogs) {
      methodNames.add(
          (String) eventLog.getData(CLASS_NAME) + (String) eventLog.getData(METHOD_NAME));
    }

    for (EventLog eventLog : secondEventLogs) {

      assertTrue(
          methodNames.contains(
              (String) eventLog.getData(CLASS_NAME) + (String) eventLog.getData(METHOD_NAME)),
          faiMessage);
    }
  }
 // Verify that the list of event logs have the specified event type. Print the specified failure
 // message if the
 // assertion on the event type fails.
 public static void verifyEventTypeForEventsLogs(
     List<EventLog> eventLogs, TestNgRunEvent event, String failMessage) {
   for (EventLog eventLog : eventLogs) {
     assertTrue(eventLog.getEvent() == event, failMessage);
   }
 }
  public static void verifyParallelSuitesWithUnequalExecutionTimes(
      List<EventLog> suiteLevelEventLogs, int threadPoolSize) {

    Map<String, EventLog> suitesExecuting = new HashMap<>();
    Map<String, EventLog> suitesCompleted = new HashMap<>();

    List<Long> executingSuiteThreadIds = new ArrayList<>();

    if (suiteLevelEventLogs.size() > 2) {
      int offset =
          suiteLevelEventLogs.size() >= 2 * threadPoolSize
              ? threadPoolSize
              : suiteLevelEventLogs.size() / 2;

      List<EventLog> suiteListenerStartEventLogs = suiteLevelEventLogs.subList(0, offset);

      verifyFirstBlockOfSimultaneouslyExecutingSuites(suiteListenerStartEventLogs, threadPoolSize);

      for (EventLog eventLog : suiteListenerStartEventLogs) {
        suitesExecuting.put((String) eventLog.getData(SUITE_NAME), eventLog);
        executingSuiteThreadIds.add(eventLog.getThreadId());
      }

      for (int i = offset; i < suiteLevelEventLogs.size(); i++) {

        EventLog eventLog = suiteLevelEventLogs.get(i);
        String suiteName = (String) eventLog.getData(SUITE_NAME);

        if (eventLog.getEvent() == LISTENER_SUITE_START) {
          if (suitesExecuting.keySet().size() == threadPoolSize) {
            fail(
                "The thread pool size is "
                    + threadPoolSize
                    + ", so there should be no more than "
                    + threadPoolSize
                    + " suites executing at the same time: "
                    + suiteLevelEventLogs);
          }

          assertFalse(
              suitesExecuting.get(suiteName) != null || suitesCompleted.get(suiteName) != null,
              "There should only be one execution of any given suite");
          assertFalse(
              executingSuiteThreadIds.contains(eventLog.getThreadId()),
              "Event logs for currently " + "executing suites should have different thread IDs");

          suitesExecuting.put(suiteName, eventLog);
          executingSuiteThreadIds.add(eventLog.getThreadId());

          if (suitesCompleted.size() > 0) {
            EventLog priorEventLog = suiteLevelEventLogs.get(i - 1);

            assertEquals(
                priorEventLog.getEvent(),
                LISTENER_SUITE_FINISH,
                "When suites are executing in "
                    + "parallel and a new suite begins execution when the active thread count was last "
                    + "known to be equal to the maximum thread pool size, the previously logged suite "
                    + "level event should be a suite listener onFinish event.");
          }
        }

        if (suitesExecuting.keySet().size() < threadPoolSize
            && suiteLevelEventLogs.size() - i + 1 > threadPoolSize) {
          fail(
              "The thread pool size is "
                  + threadPoolSize
                  + ", so there should be at least "
                  + threadPoolSize
                  + " suites executing at the same time unless there are no suites left to "
                  + "queue and the final block of suites is currently in execution: "
                  + suiteLevelEventLogs);
        }

        if (eventLog.getEvent() == LISTENER_SUITE_FINISH) {

          assertTrue(
              suitesExecuting.get(suiteName) != null,
              "Found an event log for a suite listener "
                  + "onFinish event that does not have a corresponding event log for a suite listener "
                  + "onStart event");
          assertTrue(
              suitesExecuting.get(suiteName).getThreadId() == eventLog.getThreadId(),
              "All the "
                  + "suite level event logs for a given suite should have the same thread ID");

          suitesExecuting.remove(suiteName);
          executingSuiteThreadIds.remove(eventLog.getThreadId());
          suitesCompleted.put((String) eventLog.getData(SUITE_NAME), eventLog);
        }
      }
    }
  }
 // Verify that the threads from the specified list of event logs are all greater than the
 // specified thread ID. Print
 // the specified failure message if the assertion on the thread IDs fails.
 public static void verifyEventThreadsSpawnedAfter(
     Long earlierThreadId, List<EventLog> eventsFromLaterThread, String failMessage) {
   for (EventLog eventLog : eventsFromLaterThread) {
     assertTrue(eventLog.getThreadId() > earlierThreadId, failMessage);
   }
 }