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

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.dexsplitter.SplitterTestBase;
import com.google.common.collect.ImmutableSet;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * We need to ensure that we distribute the synthetic items in the features where they where
 * generated.
 */
@RunWith(Parameterized.class)
public class Regress181837660 extends SplitterTestBase {

  @Parameters(name = "{0}")
  public static TestParametersCollection params() {
    return getTestParameters().withDexRuntimes().withAllApiLevels().build();
  }

  private final TestParameters parameters;

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

  @Test
  public void testDistribution() throws Exception {
    ProcessResult processResult =
        testR8Splitter(
            parameters,
            ImmutableSet.of(BaseClass.class),
            ImmutableSet.of(FeatureClass.class),
            FeatureClass.class,
            b -> {},
            this::configure);

    assertEquals(1, processResult.exitCode);
    // We can't actually read the field since it is in the feature.
    assertTrue(processResult.stderr.contains("NoClassDefFoundError"));
  }

  @Test
  public void testRegress181571571() throws Exception {
    ProcessResult processResult =
        testR8Splitter(
            parameters,
            ImmutableSet.of(BaseClass.class),
            ImmutableSet.of(FeatureClass.class),
            FeatureClass.class,
            b -> {},
            this::configureNoInlineAnnotations);
    // This should not succeed as illustrated by non inlining case
    assertEquals(1, processResult.exitCode);
    // We can't actually read the field since it is in the feature.
    assertThat(processResult.stderr, containsString("NoClassDefFoundError"));
  }

  @Test
  public void testRegress181571571StillInlineValid() throws Exception {
    ProcessResult processResult =
        testR8Splitter(
            parameters,
            ImmutableSet.of(Base2Class.class),
            ImmutableSet.of(Feature2Class.class),
            Feature2Class.class,
            r8TestCompileResult ->
                r8TestCompileResult.inspect(
                    base -> assertFalse(base.clazz(Base2Class.class).isPresent())),
            this::configureNoInlineAnnotations);
    assertEquals(0, processResult.exitCode);
    assertEquals(processResult.stdout, "42\n");
  }

  private void configure(R8FullTestBuilder testBuilder) throws NoSuchMethodException {
    testBuilder.enableInliningAnnotations().noMinification().setMinApi(parameters.getApiLevel());
  }

  private void configureNoInlineAnnotations(R8FullTestBuilder testBuilder)
      throws NoSuchMethodException {
    testBuilder.noMinification().setMinApi(parameters.getApiLevel());
  }

  public static class BaseClass {

    @NeverInline
    public static String getFromFeature() {
      return FeatureClass.featureString;
    }

    @NeverInline
    public static String getSecondFromFeature() {
      return FeatureClass.getFeatureString();
    }
  }

  public static class FeatureClass implements RunInterface {

    public static String featureString = "22";

    public static String getFeatureString() {
      return "42";
    }

    public static String getAString() {
      return BaseClass.getFromFeature();
    }

    public static String getSecondString() {
      return BaseClass.getSecondFromFeature();
    }

    @Override
    public void run() {
      System.out.println(getAString());
      System.out.println(getSecondString());
    }
  }

  public static class Base2Class {
    public static String getFromFeature() {
      return System.currentTimeMillis() > 2 ? "42" : "-19";
    }
  }

  public static class Feature2Class implements RunInterface {
    public static String getAString() {
      return Base2Class.getFromFeature();
    }

    @Override
    public void run() {
      System.out.println(getAString());
    }
  }
}
