// Copyright (c) 2019, 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.assumenosideeffects;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.utils.StringUtils;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class AssumenosideeffectsPropagationWithSuperCallTest extends TestBase {
  private static final Class<?> MAIN = DelegatesUser.class;

  // With horizontal class merging enabled the method body for debug is cleared, because the
  // forwarded call to the class specific implementation has no side effects. The call to the
  // function from main persists.
  private static final String EXPECTED_OUTPUT = StringUtils.lines("[Base] message2", "The end");

  enum TestConfig {
    SPECIFIC_RULES,
    NON_SPECIFIC_RULES_WITH_EXTENDS;

    public String getKeepRules() {
      switch (this) {
        case SPECIFIC_RULES:
          return StringUtils.lines(
              "-assumenosideeffects class **.*Sub* {",
              "  *** debug(...);",
              "}"
          );
        case NON_SPECIFIC_RULES_WITH_EXTENDS:
          return StringUtils.lines(
              "-assumenosideeffects class * extends " + BaseClass.class.getTypeName() + " {",
              "  *** debug(...);",
              "}"
          );
        default:
          throw new Unreachable();
      }
    }

    public String expectedOutput(TestParameters parameters) {
      switch (this) {
        case SPECIFIC_RULES:
        case NON_SPECIFIC_RULES_WITH_EXTENDS:
          return EXPECTED_OUTPUT;
        default:
          throw new Unreachable();
      }
    }
  }

  private final TestParameters parameters;
  private final TestConfig config;

  @Parameterized.Parameters(name = "{0} {1}")
  public static Collection<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimesAndApiLevels().build(), TestConfig.values());
  }

  public AssumenosideeffectsPropagationWithSuperCallTest(
      TestParameters parameters, TestConfig config) {
    this.parameters = parameters;
    this.config = config;
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addInnerClasses(AssumenosideeffectsPropagationWithSuperCallTest.class)
        .addKeepMainRule(MAIN)
        .addKeepRules(config.getKeepRules())
        .addDontObfuscate()
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), MAIN)
        .assertSuccessWithOutput(config.expectedOutput(parameters));
  }

  static class BaseClass {
    void debug(String message) {
      System.out.println("[Base] " + message);
    }
  }

  static class DelegateSub1 extends BaseClass {
    // TODO(b/133208961): Should behave same with and without the following definition.
    @Override
    public void debug(String message) {
      super.debug(message);
    }
  }

  static class DelegateSub2 extends BaseClass {
    @Override
    public void debug(String message) {
      System.out.println("[Sub2] " + message);
    }
  }

  static class DelegatesUser {
    static BaseClass createBase() {
      return System.currentTimeMillis() > 0 ? new DelegateSub1() : new DelegateSub2();
    }

    public static void main(String... args) {
      BaseClass instance = createBase();
      instance.debug("message1");
      if (System.currentTimeMillis() > 0) {
        instance = new BaseClass();
      }
      instance.debug("message2");
      System.out.println("The end");
    }
  }
}
