// 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.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.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
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.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
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 = testForD8().addProgramClasses(TestClass.class).compile().app;
    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().getRules();
            });
    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();
    assertEquals(4, wave.size()); // including <init>
    assertThat(wave, hasItem(m3.method));
    assertThat(wave, hasItem(m4.method));
    assertThat(wave, hasItem(m6.method));

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

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

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

    CallGraph pg =
        new PartialCallGraphBuilder(appView, ImmutableSet.of(em1, em2, em4, em5))
            .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());
    assertEquals(2, wave.size());
    assertThat(wave, hasItem(m1.method));
    assertThat(wave, hasItem(m5.method));
    wave.clear();

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

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

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

  private DexEncodedMethod findMethod(String name) {
    for (DexClass clazz : appView.appInfo().classes()) {
      for (DexEncodedMethod method : clazz.methods()) {
        if (method.method.name.toString().equals(name)) {
          return 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");
    }
  }
}
