// 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.CallGraph;
import com.android.tools.r8.ir.conversion.callgraph.CallGraphBuilder;
import com.android.tools.r8.ir.conversion.callgraph.Node;
import com.android.tools.r8.ir.conversion.callgraph.PartialCallGraphBuilder;
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.getNodes(), "m1");
    Node m2 = findNode(cg.getNodes(), "m2");
    Node m3 = findNode(cg.getNodes(), "m3");
    Node m4 = findNode(cg.getNodes(), "m4");
    Node m5 = findNode(cg.getNodes(), "m5");
    Node m6 = findNode(cg.getNodes(), "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.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.getNodes(), "m1");
    Node m2 = findNode(pg.getNodes(), "m2");
    Node m4 = findNode(pg.getNodes(), "m4");
    Node m5 = findNode(pg.getNodes(), "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.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");
    }
  }
}
