private void onTestFinished(ITestResult iTestResult, TestResult.ResultType resultType) {
   Object testId;
   TestStartEvent startEvent = null;
   synchronized (lock) {
     testId = tests.remove(iTestResult);
     if (testId == null) {
       // This can happen when a method fails which this method depends on
       testId = idGenerator.generateId();
       Object parentId = testMethodToSuiteMapping.get(iTestResult.getMethod());
       startEvent = new TestStartEvent(iTestResult.getStartMillis(), parentId);
     }
   }
   if (startEvent != null) {
     // Synthesize a start event
     resultProcessor.started(
         new DefaultTestMethodDescriptor(
             testId, iTestResult.getTestClass().getName(), iTestResult.getName()),
         startEvent);
   }
   if (resultType == TestResult.ResultType.FAILURE) {
     resultProcessor.failure(testId, iTestResult.getThrowable());
   }
   resultProcessor.completed(
       testId, new TestCompleteEvent(iTestResult.getEndMillis(), resultType));
 }
 public void onStart(ITestContext iTestContext) {
   TestDescriptorInternal testInternal;
   synchronized (lock) {
     testInternal =
         new DefaultTestSuiteDescriptor(idGenerator.generateId(), iTestContext.getName());
     suites.put(testInternal.getName(), testInternal.getId());
     for (ITestNGMethod method : iTestContext.getAllTestMethods()) {
       testMethodToSuiteMapping.put(method, testInternal.getId());
     }
   }
   resultProcessor.started(
       testInternal, new TestStartEvent(iTestContext.getStartDate().getTime()));
 }
 public void onConfigurationFailure(ITestResult testResult) {
   if (failedConfigurations.put(testResult, true) != null) {
     // workaround for bug in TestNG 6.2 (apparently fixed in some 6.3.x): listener is notified
     // twice per event
     return;
   }
   // Synthesise a test for the broken configuration method
   TestDescriptorInternal test =
       new DefaultTestMethodDescriptor(
           idGenerator.generateId(),
           testResult.getMethod().getTestClass().getName(),
           testResult.getMethod().getMethodName());
   resultProcessor.started(test, new TestStartEvent(testResult.getStartMillis()));
   resultProcessor.failure(test.getId(), testResult.getThrowable());
   resultProcessor.completed(
       test.getId(),
       new TestCompleteEvent(testResult.getEndMillis(), TestResult.ResultType.FAILURE));
 }
  public void onTestStart(ITestResult iTestResult) {
    TestDescriptorInternal testInternal;
    Object parentId;
    synchronized (lock) {
      testInternal =
          new DefaultTestMethodDescriptor(
              idGenerator.generateId(),
              iTestResult.getTestClass().getName(),
              iTestResult.getName());
      Object oldTestId = tests.put(iTestResult, testInternal.getId());
      assert oldTestId == null
          : "Apparently some other test has started but it hasn't finished. "
              + "Expect the resultProcessor to break. "
              + "Don't expect to see this assertion stack trace due to the current architecture";

      parentId = testMethodToSuiteMapping.get(iTestResult.getMethod());
      assert parentId != null;
    }
    resultProcessor.started(
        testInternal, new TestStartEvent(iTestResult.getStartMillis(), parentId));
  }