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

import static org.junit.Assert.assertEquals;

import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.bisect.BisectOptions.Result;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.smali.SmaliBuilder;
import com.android.tools.r8.smali.SmaliBuilder.MethodSignature;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

public class BisectTest {

  private final String[] CLASSES = {"A", "B", "C", "D", "E", "F", "G", "H"};
  private final String ERRONEOUS_CLASS = "F";
  private final String ERRONEOUS_METHOD = "foo";
  private final String VALID_METHOD = "bar";

  // Set during build to more easily inspect later.
  private MethodSignature erroneousMethodSignature = null;

  @Rule
  public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();

  @Test
  public void bisect() throws Exception {
    InternalOptions options = new InternalOptions();
    Timing timing = new Timing("bisect-test");

    // Build "good" application with no method in "F".
    SmaliBuilder builderGood = new SmaliBuilder();
    for (String clazz : CLASSES) {
      builderGood.addClass(clazz);
      builderGood.addStaticMethod(
          "void", VALID_METHOD, ImmutableList.of(), 0, "return-void");
    }
    AndroidApp inputGood =
        AndroidApp.builder().addDexProgramData(builderGood.compile(), Origin.unknown()).build();
    DexApplication appGood = new ApplicationReader(inputGood, options, timing).read();

    // Build "bad" application with a method "foo" in "F".
    SmaliBuilder builderBad = new SmaliBuilder();
    for (String clazz : CLASSES) {
      builderBad.addClass(clazz);
      if (clazz.equals(ERRONEOUS_CLASS)) {
        erroneousMethodSignature = builderBad.addStaticMethod(
            "void", ERRONEOUS_METHOD, ImmutableList.of(), 0, "return-void");
      } else {
        builderBad.addStaticMethod(
            "void", VALID_METHOD, ImmutableList.of(), 0, "return-void");
      }
    }
    AndroidApp inputBad =
        AndroidApp.builder().addDexProgramData(builderBad.compile(), Origin.unknown()).build();
    DexApplication appBad = new ApplicationReader(inputBad, options, timing).read();

    ExecutorService executor = Executors.newWorkStealingPool();
    try {
      BisectState state = new BisectState(appGood, appBad, null);
      DexProgramClass clazz = Bisect.run(state, this::command, temp.newFolder().toPath(), executor);
      System.out.println("Found bad class: " + clazz);
      assertEquals(clazz.type.toString(), ERRONEOUS_CLASS);
    } finally {
      executor.shutdown();
    }
  }

  private Result command(DexApplication application) {
    CodeInspector inspector = new CodeInspector(application);
    if (inspector
        .clazz(ERRONEOUS_CLASS)
        .method(erroneousMethodSignature.returnType,
            erroneousMethodSignature.name,
            erroneousMethodSignature.parameterTypes)
        .isPresent()) {
      return Result.BAD;
    }
    return Result.GOOD;
  }
}
