// 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.hooks.testutil;

import junit.framework.TestCase;

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<Object>();
    mockControls = new ArrayList<IMocksControl>();
    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();
  }
}
