// Copyright (c) 2018 the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.shaking;

import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

class B112517039ReturnType extends Exception {
}

interface B112517039I {
  B112517039ReturnType m();
  void flaf(Exception e);
}

class B112517039Caller {
  public void call(B112517039I i) {
    System.out.println("Ewwo!");
    i.flaf(i.m());
  }
}

class B112517039Main {
  public static void main(String[] args) {
    try {
      B112517039Caller caller = new B112517039Caller();
      caller.call(null);
    } catch (NullPointerException e) {
      System.out.println("NullPointerException");
    }
  }
}

@RunWith(Parameterized.class)
public class ReturnTypeTest extends TestBase {
  private static final String JAVA_OUTPUT = StringUtils.lines(
      "Ewwo!",
      "NullPointerException"
  );
  private static final Class<?> MAIN = B112517039Main.class;

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimes().build();
  }

  private final TestParameters parameters;

  public ReturnTypeTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  @Test
  public void testJVMOutput() throws Exception {
    assumeTrue("Only run JVM reference on CF runtimes", parameters.isCfRuntime());
    testForJvm()
        .addTestClasspath()
        .run(parameters.getRuntime(), MAIN)
        .assertSuccessWithOutput(JAVA_OUTPUT);
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addProgramClasses(
            B112517039ReturnType.class, B112517039I.class, B112517039Caller.class, MAIN)
        .addKeepMainRule(MAIN)
        .setMinApi(parameters.getRuntime())
        .addOptionsModification(o -> {
          // No actual implementation of B112517039I, rather invoked with `null`.
          // Call site optimization propagation will conclude that the input of B...Caller#call is
          // always null, and replace the last call with null-throwing instruction.
          // However, we want to test return type and parameter type are kept in this scenario.
          o.enablePropagationOfDynamicTypesAtCallSites = false;
          o.enableInlining = false;
        })
        .run(parameters.getRuntime(), MAIN)
        .assertSuccessWithOutput(JAVA_OUTPUT)
        .inspect(inspector -> {
          ClassSubject returnType = inspector.clazz(B112517039ReturnType.class);
          assertThat(returnType, isRenamed());
        });
  }
}
