// 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 com.google.common.collect.Lists;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.googlesource.gerrit.plugins.its.base.testutil.log.LogUtil;
import java.sql.Timestamp;
import java.util.Iterator;
import java.util.logging.LogRecord;
import junit.framework.TestCase;
import org.apache.log4j.Level;
import org.junit.After;

public abstract class LoggingMockingTestCase extends TestCase {

  protected final Change.Key testChangeKey =
      Change.key("Ic19f7bf6c8b4685c363a8204c32d827ffda52ec0");
  protected final Change.Id testChangeId = Change.id(1);
  protected final Account.Id testAccountId = Account.id(1);

  private java.util.Collection<LogRecord> records;

  protected final void assertLogMessageContains(String needle, Level level) {
    LogRecord hit = null;
    Iterator<LogRecord> iter = records.iterator();
    while (hit == null && iter.hasNext()) {
      LogRecord record = iter.next();
      if (record.getMessage().contains(needle)) {
        if (level == null || LogUtil.equalLevels(record.getLevel(), level)) {
          hit = record;
        }
      }
    }
    assertNotNull("Could not find log message containing '" + needle + "'", hit);
    assertTrue("Could not remove log message containing '" + needle + "'", records.remove(hit));
  }

  protected final void assertLogMessageContains(String needle) {
    assertLogMessageContains(needle, null);
  }

  protected final void assertLogThrowableMessageContains(String needle) {
    LogRecord hit = null;
    Iterator<LogRecord> iter = records.iterator();
    while (hit == null && iter.hasNext()) {
      LogRecord record = iter.next();

      Throwable t = record.getThrown();
      if (t != null && t.toString().contains(needle)) {
        hit = record;
      }
    }
    assertNotNull("Could not find log message with a Throwable containing '" + needle + "'", hit);
    assertTrue(
        "Could not remove log message with a Throwable containing '" + needle + "'",
        records.remove(hit));
  }

  // As the PowerMock runner does not pass through runTest, we inject log
  // verification through @After
  @After
  public final void assertNoUnassertedLogEvents() {
    if (records.size() > 0) {
      LogRecord record = records.iterator().next();
      String msg = "Found untreated logged events. First one is:\n";
      msg += record.getMessage();
      Throwable t = record.getThrown();
      if (t != null) {
        msg += "\n" + t;
      }
      fail(msg);
    }
  }

  @Override
  public void setUp() throws Exception {
    super.setUp();
    records = Lists.newArrayList();

    // The logger we're interested is class name without the trailing "Test".
    // While this is not the most general approach it is sufficient for now,
    // and we can improve later to allow tests to specify which loggers are
    // to check.
    String logName = this.getClass().getCanonicalName();
    logName = logName.substring(0, logName.length() - 4);
    LogUtil.logToCollection(logName, records, Level.DEBUG);
  }

  @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.
    assertNoUnassertedLogEvents();
  }

  protected Change testChange(String project, String branch) {
    return new Change(
        testChangeKey,
        testChangeId,
        testAccountId,
        BranchNameKey.create(Project.nameKey(project), branch),
        new Timestamp(System.currentTimeMillis()));
  }
}
