// 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.ir.conversion;

import static com.android.tools.r8.ToolHelper.getMostRecentAndroidJar;
import static com.android.tools.r8.shaking.ProguardConfigurationSourceStrings.createConfigurationForTesting;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.CallGraph.Node;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.ProguardConfigurationParser;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import org.junit.Test;

public class PartialCallGraphTest extends CallGraphTestBase {
  private final AppView<AppInfoWithLiveness> appView;
  private final InternalOptions options;
  private final ExecutorService executorService;

  public PartialCallGraphTest() throws Exception {
    AndroidApp app =
        AndroidApp.builder(testForD8().addProgramClasses(TestClass.class).compile().getApp())
            .addLibraryFile(getMostRecentAndroidJar())
            .build();
    this.appView =
        computeAppViewWithLiveness(
            app,
            factory -> {
              ProguardConfigurationParser parser =
                  new ProguardConfigurationParser(factory, new Reporter());
              parser.parse(
                  createConfigurationForTesting(
                      ImmutableList.of("-keep class ** { void m1(); void m5(); }")));
              return parser.getConfig();
            });
    this.options = appView.options();
    this.executorService = ThreadUtils.getExecutorService(options);
  }

  @Test
  public void testFullGraph() throws Exception {
    CallGraph cg = new CallGraphBuilder(appView).build(executorService, Timing.empty());
    Node m1 = findNode(cg.nodes, "m1");
    Node m2 = findNode(cg.nodes, "m2");
    Node m3 = findNode(cg.nodes, "m3");
    Node m4 = findNode(cg.nodes, "m4");
    Node m5 = findNode(cg.nodes, "m5");
    Node m6 = findNode(cg.nodes, "m6");
    assertNotNull(m1);
    assertNotNull(m2);
    assertNotNull(m3);
    assertNotNull(m4);
    assertNotNull(m5);
    assertNotNull(m6);

    Set<DexEncodedMethod> wave = cg.extractLeaves().toDefinitionSet();
    assertEquals(4, wave.size()); // including <init>
    assertThat(wave, hasItem(m3.getMethod()));
    assertThat(wave, hasItem(m4.getMethod()));
    assertThat(wave, hasItem(m6.getMethod()));

    wave = cg.extractLeaves().toDefinitionSet();
    assertEquals(2, wave.size());
    assertThat(wave, hasItem(m2.getMethod()));
    assertThat(wave, hasItem(m5.getMethod()));

    wave = cg.extractLeaves().toDefinitionSet();
    assertEquals(1, wave.size());
    assertThat(wave, hasItem(m1.getMethod()));
    assertTrue(cg.nodes.isEmpty());
  }

  @Test
  public void testPartialGraph() throws Exception {
    ProgramMethod em1 = findMethod("m1");
    ProgramMethod em2 = findMethod("m2");
    ProgramMethod em4 = findMethod("m4");
    ProgramMethod em5 = findMethod("m5");
    assertNotNull(em1);
    assertNotNull(em2);
    assertNotNull(em4);
    assertNotNull(em5);

    ProgramMethodSet seeds = ProgramMethodSet.create();
    seeds.add(em1);
    seeds.add(em2);
    seeds.add(em4);
    seeds.add(em5);
    CallGraph pg =
        new PartialCallGraphBuilder(appView, seeds).build(executorService, Timing.empty());

    Node m1 = findNode(pg.nodes, "m1");
    Node m2 = findNode(pg.nodes, "m2");
    Node m4 = findNode(pg.nodes, "m4");
    Node m5 = findNode(pg.nodes, "m5");
    assertNotNull(m1);
    assertNotNull(m2);
    assertNotNull(m4);
    assertNotNull(m5);

    Set<DexEncodedMethod> wave = Sets.newIdentityHashSet();

    wave.addAll(pg.extractRoots().toDefinitionSet());
    assertEquals(2, wave.size());
    assertThat(wave, hasItem(m1.getMethod()));
    assertThat(wave, hasItem(m5.getMethod()));
    wave.clear();

    wave.addAll(pg.extractRoots().toDefinitionSet());
    assertEquals(1, wave.size());
    assertThat(wave, hasItem(m2.getMethod()));
    wave.clear();

    wave.addAll(pg.extractRoots().toDefinitionSet());
    assertEquals(1, wave.size());
    assertThat(wave, hasItem(m4.getMethod()));
    assertTrue(pg.nodes.isEmpty());
  }

  private Node findNode(Iterable<Node> nodes, String name) {
    for (Node n : nodes) {
      if (n.getMethod().getReference().name.toString().equals(name)) {
        return n;
      }
    }
    return null;
  }

  private ProgramMethod findMethod(String name) {
    for (DexProgramClass clazz : appView.appInfo().classes()) {
      for (DexEncodedMethod method : clazz.methods()) {
        if (method.getReference().name.toString().equals(name)) {
          return new ProgramMethod(clazz, method);
        }
      }
    }
    return null;
  }

  static class TestClass {
    void m1() {
      System.out.println("m1");
      m2();
    }

    void m2() {
      System.out.println("m2");
      m3();
      m4();
    }

    void m3() {
      System.out.println("m3");
    }

    void m4() {
      System.out.println("m4");
    }

    void m5() {
      System.out.println("m5");
      m6();
      m4();
    }

    void m6() {
      System.out.println("m6");
    }
  }
}
