/*
 * Copyright 2013 Google Inc.
 *
 * 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.google.gwt.junit.client;

import com.google.gwt.core.client.impl.Impl;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.core.shared.SerializableThrowable;
import com.google.gwt.junit.client.WithProperties.Property;

import junit.framework.AssertionFailedError;

import javaemul.internal.annotations.DoNotInline;

/**
 * This class tests stack traces generated by GWTTestCase.
 */
public class GWTTestCaseStackTraceTest extends GWTTestCaseTestBase {

  private static final int LINE_NUMBER_1 = 42;
  private static final int LINE_NUMBER_2 = LINE_NUMBER_1 + 2;

  private static final String FILE_NAME = "GWTTestCaseStackTraceTest.java";
  private static final String CLASS_NAME = GWTTestCaseStackTraceTest.class.getName();

  @DoNotInline
  private static void throwException(boolean withCause) {
    // the next line should be LINE_NUMBER_1
    AssertionFailedError exception = new AssertionFailedError("stack_trace_msg");
    if (withCause) {
      exception.initCause(new RuntimeException("the_cause"));
    }
    throw exception;
  }

  private static void assertStackTrace(
      Throwable t, String methodName, int lineNumber, boolean hasCause) {
    assertSame(AssertionFailedError.class, t.getClass());
    assertTrue(t.getMessage().startsWith("stack_trace_msg"));
    StackTraceElement[] trace = t.getStackTrace();
    assertStackTrace(trace, CLASS_NAME, "throwException", FILE_NAME, LINE_NUMBER_1);
    assertStackTrace(trace, CLASS_NAME, methodName, FILE_NAME, lineNumber);
    assertCause(t, hasCause);
  }

  private static void assertCause(Throwable t, boolean hasCause) {
    Throwable cause = t.getCause();
    if (hasCause) {
      assertNotNull(cause);
      assertCauseDetails(cause);
    } else {
      assertNull(cause);
    }
  }

  private static void assertCauseDetails(Throwable t) {
    assertSame(SerializableThrowable.class, t.getClass());
    String type = ((SerializableThrowable) t).getDesignatedType();
    assertEquals(RuntimeException.class.getName(), type);
    assertTrue(t.getMessage().startsWith("the_cause"));
    StackTraceElement[] trace = t.getStackTrace();
    assertStackTrace(trace, CLASS_NAME, "throwException", FILE_NAME, LINE_NUMBER_2);
  }

  private static void assertStackTrace(StackTraceElement[] stackTrace, String className,
      String methodName, String fileName, int lineNumber) {
    for (StackTraceElement stackTraceElement : stackTrace) {
      if (stackTraceElement.getClassName().equals(className)
          && stackTraceElement.getMethodName().equals(methodName)) {
        assertEquals(fileName, stackTraceElement.getFileName());
        assertEquals(lineNumber, stackTraceElement.getLineNumber());
        return; // Found!!!
      }
    }
    fail("Stack trace element not found " + className + "#" + methodName);
  }

  /** Asserts stack trace generated by {@link #testStackTrace} */
  public static class StackTraceAsserter implements ExceptionAsserter {
    public void assertException(ExpectedFailure annotation, Throwable actual) {
      final int lineNumber = 101;
      assertStackTrace(actual, "testStackTrace", lineNumber, false);
    }
  }

  @ExpectedFailure(withAsserter = StackTraceAsserter.class)
  public void testStackTrace() {
    throwException(false);
  }

  /** Asserts stack trace generated by {@link #testStackTrace_withCause} */
  public static class StackTraceAsserterWithCause implements ExceptionAsserter {
    public void assertException(ExpectedFailure annotation, Throwable actual) {
      final int lineNumber = 114;
      assertStackTrace(actual, "testStackTrace_withCause", lineNumber, true);
    }
  }

  @ExpectedFailure(withAsserter = StackTraceAsserterWithCause.class)
  public void testStackTrace_withCause() {
    throwException(true);
  }

  /** Asserts stack trace generated by {@link #testStackTrace_fromDifferentModule} */
  public static class StackTraceAsserterFromDifferentModule implements ExceptionAsserter {
    public void assertException(ExpectedFailure annotation, Throwable actual) {
      final int lineNumber = 129;
      assertStackTrace(actual, "testStackTrace_fromDifferentModule", lineNumber, false);
    }
  }

  // @Property added just to introduce a different module name for the test
  @WithProperties(@Property(name = "locale", value = "tr"))
  @ExpectedFailure(withAsserter = StackTraceAsserterFromDifferentModule.class)
  public void testStackTrace_fromDifferentModule() {
    throwException(false);
  }

  /** Asserts stack trace generated by {@link #testStackTrace_jsni} */
  public static class StackTraceAsserterForJsni implements ExceptionAsserter {
    public void assertException(ExpectedFailure annotation, Throwable actual) {
      assertEquals(1, actual.getStackTrace().length);
      StackTraceElement ste = actual.getStackTrace()[0];
      assertEquals("setUp", ste.getMethodName());
      assertEquals(FILE_NAME, ste.getFileName());
      assertEquals(9999, ste.getLineNumber());
    }
  }

  /**
   * This is asserting that {@code StacktraceDeobfuscator} trusts the stack trace emulation with the
   * file name and line number (emulation knows it better for anonymous functions in JSNI).
   */
  @ExpectedFailure(withAsserter = StackTraceAsserterForJsni.class)
  public void testStackTrace_jsni() {
    // A method name from a different file so that deobfuscator will resolve to a different file.
    String methodName = !GWT.isScript() ? "setUp"
        : Impl.getNameOf("com.google.gwt.junit.client.GWTTestCase::setUp()");
    StackTraceElement ste = new StackTraceElement("Unknown", methodName, FILE_NAME, 9999);

    AssertionFailedError exception = new AssertionFailedError("stack_trace_msg");
    exception.setStackTrace(new StackTraceElement[] {ste});
    throw exception;
  }
}
