// Copyright (C) 2013 The Android Open Source Project
//
// 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.googlesource.gerrit.plugins.its.base.testutil;

import junit.framework.TestCase;

import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.After;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.modules.junit4.PowerMockRunner;

import java.util.ArrayList;
import java.util.Collection;

/**
 * Test case with some support for automatically verifying mocks.
 */
public abstract class MockingTestCase extends TestCase {
  private Collection<Object> mocks;
  private Collection<IMocksControl> mockControls;
  private boolean mocksReplayed;
  private boolean usePowerMock;

  /**
   * Create and register a mock control.
   *
   * @return The mock control instance.
   */
  protected final IMocksControl createMockControl() {
    IMocksControl mockControl = EasyMock.createControl();
    assertTrue("Adding mock control failed", mockControls.add(mockControl));
    return mockControl;
  }

  /**
   * Create and register a mock.
   *
   * Creates a mock and registers it in the list of created mocks, so it gets
   * treated automatically upon {@code replay} and {@code verify};
   * @param toMock The class to create a mock for.
   * @return The mock instance.
   */
  protected final <T> T createMock(Class<T> toMock) {
    return createMock(toMock, null);
  }

  /**
   * Create a mock for a mock control and register a mock.
   *
   * Creates a mock and registers it in the list of created mocks, so it gets
   * treated automatically upon {@code replay} and {@code verify};
   * @param toMock The class to create a mock for.
   * @param control The mock control to create the mock on. If null, do not use
   *    a specific control.
   * @return The mock instance.
   */
  protected final <T> T createMock(Class<T> toMock, IMocksControl control) {
    assertFalse("Mocks have already been set to replay", mocksReplayed);
    final T mock;
    if (control == null) {
      if (usePowerMock) {
        mock = PowerMock.createMock(toMock);
      } else {
        mock = EasyMock.createMock(toMock);
      }
      assertTrue("Adding " + toMock.getName() + " mock failed",
          mocks.add(mock));
    } else {
      mock = control.createMock(toMock);
    }
    return mock;
  }

  /**
   * Set all registered mocks to replay
   */
  protected final void replayMocks() {
    assertFalse("Mocks have already been set to replay", mocksReplayed);
    if (usePowerMock) {
      PowerMock.replayAll();
    } else {
      EasyMock.replay(mocks.toArray());
    }
    for (IMocksControl mockControl : mockControls) {
      mockControl.replay();
    }
    mocksReplayed = true;
  }

  /**
   * Verify all registered mocks
   *
   * This method is called automatically at the end of a test. Nevertheless,
   * it is safe to also call it beforehand, if this better meets the
   * verification part of a test.
   */
  // As the PowerMock runner does not pass through runTest, we inject mock
  // verification through @After
  @After
  public final void verifyMocks() {
    if (!mocks.isEmpty() || !mockControls.isEmpty()) {
      assertTrue("Created mocks have not been set to replay. Call replayMocks "
          + "within the test", mocksReplayed);
      if (usePowerMock) {
        PowerMock.verifyAll();
      } else {
        EasyMock.verify(mocks.toArray());
      }
      for (IMocksControl mockControl : mockControls) {
        mockControl.verify();
      }
    }
  }

  @Override
  public void setUp() throws Exception {
    super.setUp();

    usePowerMock = false;
    RunWith runWith = this.getClass().getAnnotation(RunWith.class);
    if (runWith != null) {
      usePowerMock = PowerMockRunner.class.isAssignableFrom(runWith.value());
    }

    mocks = new ArrayList<>();
    mockControls = new ArrayList<>();
    mocksReplayed = false;
  }

  @Override
  protected void runTest() throws Throwable {
    super.runTest();
    // Plain JUnit runner does not pick up @After, so we add it here
    // explicitly. Note, that we cannot put this into tearDown, as failure
    // to verify mocks would bail out and might leave open resources from
    // subclasses open.
    verifyMocks();
  }

  /**
   * Create a new Capture.
   *
   * @return The created Capture.
   */
  protected final <T> Capture<T> createCapture() {
    return new Capture<>();
  }
}
