// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.profiler.memory;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleFunction;
import com.google.devtools.build.lib.profiler.memory.AllocationTracker.RuleBytes;
import com.google.devtools.build.lib.syntax.Callstack;
import com.google.devtools.build.lib.syntax.Expression;
import com.google.devtools.build.lib.syntax.ParserInput;
import com.google.devtools.build.lib.syntax.StarlarkCallable;
import com.google.devtools.build.lib.syntax.SyntaxError;
import com.google.perftools.profiles.ProfileProto.Function;
import com.google.perftools.profiles.ProfileProto.Profile;
import com.google.perftools.profiles.ProfileProto.Sample;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link AllocationTracker}. */
@RunWith(JUnit4.class)
public final class AllocationTrackerTest {

  private AllocationTracker allocationTracker;

  // makeExpr returns an expression located at the specified file and line.
  private static Expression makeExpr(String file, int line) throws SyntaxError {
    ParserInput input =
        ParserInput.create(new String(new char[line - 1]).replace('\u0000', '\n') + "None", file);
    return Expression.parse(input);
  }

  private static class TestFunction implements StarlarkCallable {
    private final String name;
    private final Location location;

    TestFunction(String file, String name, int line) {
      this.name = name;
      this.location = Location.fromFileLineColumn(file, line, 0);
    }

    @Override
    public String getName() {
      return name;
    }

    @Override
    public Location getLocation() {
      return location;
    }
  }

  static class TestRuleFunction extends TestFunction implements RuleFunction {

    private final RuleClass ruleClass;

    TestRuleFunction(String file, String name, int line) {
      super(file, name, line);
      this.ruleClass = mock(RuleClass.class);
      when(ruleClass.getName()).thenReturn(name);
      when(ruleClass.getKey()).thenReturn(name);
    }

    @Override
    public RuleClass getRuleClass() {
      return ruleClass;
    }
  }

  @Before
  public void setup() {
    Callstack.setEnabled(true);
    CurrentRuleTracker.setEnabled(true);
    allocationTracker = new AllocationTracker(1, 0);
  }

  @After
  public void tearDown() {
    Callstack.resetStateForTest();
    CurrentRuleTracker.setEnabled(false);
  }

  @Test
  public void testSimpleMemoryProfile() throws Exception {
    Object allocation = new Object();
    Callstack.push(new TestFunction("fileA", "fn", 120));
    Callstack.push(makeExpr("fileA", 10));
    allocationTracker.sampleAllocation(1, "", allocation, 12);
    Callstack.pop();
    Callstack.pop();

    Map<String, RuleBytes> rules = new HashMap<>();
    Map<String, RuleBytes> aspects = new HashMap<>();
    allocationTracker.getRuleMemoryConsumption(rules, aspects);
    assertThat(rules).isEmpty();
    assertThat(aspects).isEmpty();

    Profile profile = allocationTracker.buildMemoryProfile();
    assertThat(profile.getSampleList()).hasSize(1);
    assertThat(sampleToCallstack(profile, profile.getSample(0))).containsExactly("fileA:fn:10");
  }

  @Test
  public void testLongerCallstack() throws Exception {
    Object allocation = new Object();
    Callstack.push(new TestFunction("fileB", "fnB", 120));
    Callstack.push(makeExpr("fileB", 10));
    Callstack.push(makeExpr("fileB", 12));
    Callstack.push(makeExpr("fileB", 14));
    Callstack.push(makeExpr("fileB", 18));
    Callstack.push(new TestFunction("fileA", "fnA", 120));
    Callstack.push(makeExpr("fileA", 10));
    allocationTracker.sampleAllocation(1, "", allocation, 12);
    for (int i = 0; i < 7; ++i) {
      Callstack.pop();
    }

    Profile profile = allocationTracker.buildMemoryProfile();
    assertThat(profile.getSampleList()).hasSize(1);
    assertThat(sampleToCallstack(profile, profile.getSample(0)))
        .containsExactly("fileB:fnB:18", "fileA:fnA:10");
  }

  @Test
  public void testConfiguredTargetsMemoryAllocation() throws Exception {
    RuleClass ruleClass = mock(RuleClass.class);
    when(ruleClass.getName()).thenReturn("rule");
    when(ruleClass.getKey()).thenReturn("rule");
    CurrentRuleTracker.beginConfiguredTarget(ruleClass);
    Object ruleAllocation0 = new Object();
    Object ruleAllocation1 = new Object();
    allocationTracker.sampleAllocation(1, "", ruleAllocation0, 10);
    allocationTracker.sampleAllocation(1, "", ruleAllocation1, 20);
    CurrentRuleTracker.endConfiguredTarget();

    CurrentRuleTracker.beginConfiguredAspect(() -> "aspect");
    Object aspectAllocation = new Object();
    allocationTracker.sampleAllocation(1, "", aspectAllocation, 12);
    CurrentRuleTracker.endConfiguredAspect();

    Map<String, RuleBytes> rules = new HashMap<>();
    Map<String, RuleBytes> aspects = new HashMap<>();
    allocationTracker.getRuleMemoryConsumption(rules, aspects);
    assertThat(rules).containsExactly("rule", new RuleBytes("rule").addBytes(30L));
    assertThat(aspects).containsExactly("aspect", new RuleBytes("aspect").addBytes(12L));

    Profile profile = allocationTracker.buildMemoryProfile();
    assertThat(profile.getSampleList()).isEmpty(); // No callstacks
  }

  @Test
  public void testLoadingPhaseRuleAllocations() throws Exception {
    Object allocation = new Object();
    Callstack.push(new TestFunction("fileB", "fnB", 120));
    Callstack.push(makeExpr("fileB", 18));
    Callstack.push(new TestFunction("fileA", "fnA", 120));
    Callstack.push(makeExpr("fileA", 10));
    Callstack.push(new TestRuleFunction("<native>", "proto_library", -1));
    allocationTracker.sampleAllocation(1, "", allocation, 128);
    for (int i = 0; i < 5; ++i) {
      Callstack.pop();
    }

    Map<String, RuleBytes> rules = new HashMap<>();
    Map<String, RuleBytes> aspects = new HashMap<>();
    allocationTracker.getRuleMemoryConsumption(rules, aspects);
    assertThat(rules)
        .containsExactly("proto_library", new RuleBytes("proto_library").addBytes(128L));
  }

  /** Formats a callstack as (file):(method name):(line) */
  private List<String> sampleToCallstack(Profile profile, Sample sample) {
    List<String> result = new ArrayList<>();
    for (long locationId : sample.getLocationIdList()) {
      com.google.perftools.profiles.ProfileProto.Location location =
          profile.getLocation((int) locationId - 1);
      assertThat(location.getLineList()).hasSize(1);
      long functionId = location.getLine(0).getFunctionId();
      long line = location.getLine(0).getLine();
      Function function = profile.getFunction((int) functionId - 1);
      long fileId = function.getFilename();
      long methodId = function.getName();
      String file = profile.getStringTable((int) fileId);
      String method = profile.getStringTable((int) methodId);
      result.add(String.format("%s:%s:%d", file, method, line));
    }
    return result;
  }
}
