// Copyright 2015 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;

import static com.google.common.truth.Truth.assertThat;

import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.profiler.Profiler.ProfiledTaskKinds;
import com.google.devtools.build.lib.profiler.analysis.ProfileInfo;
import com.google.devtools.build.lib.profiler.chart.AggregatingChartCreator;
import com.google.devtools.build.lib.profiler.chart.Chart;
import com.google.devtools.build.lib.profiler.chart.ChartBar;
import com.google.devtools.build.lib.profiler.chart.ChartBarType;
import com.google.devtools.build.lib.profiler.chart.ChartColumn;
import com.google.devtools.build.lib.profiler.chart.ChartCreator;
import com.google.devtools.build.lib.profiler.chart.ChartLine;
import com.google.devtools.build.lib.profiler.chart.ChartRow;
import com.google.devtools.build.lib.profiler.chart.ChartVisitor;
import com.google.devtools.build.lib.profiler.chart.Color;
import com.google.devtools.build.lib.profiler.chart.DetailedChartCreator;
import com.google.devtools.build.lib.profiler.chart.HtmlChartVisitor;
import com.google.devtools.build.lib.testutil.FoundationTestCase;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.testutil.Suite;
import com.google.devtools.build.lib.testutil.TestSpec;
import com.google.devtools.build.lib.vfs.Path;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Locale;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Unit tests for the profiler chart generation. */
@TestSpec(size = Suite.MEDIUM_TESTS)
@RunWith(JUnit4.class)
public class ProfilerChartTest extends FoundationTestCase {
  private static final int COMMON_CHART_TYPES = ProfilePhase.values().length;
  private static final int DETAILED_CHART_TYPES = ProfilerTask.values().length;
  private static final int AGGREGATED_CHART_TYPES = 4;
  private static final int AGGREGATED_CHART_NO_VFS_TYPES = 3;

  @Test
  public void testChartCreators() throws Exception {
    Runnable run = new Runnable() {
      @Override
      public void run() {
        Profiler.instance().profile(ProfilerTask.ACTION, "action").close();
      }
    };
    int threads = 4; // there is one extra thread due due the event that finalizes the profiler
    ProfileInfo info = createProfileInfo(run, threads - 1);
    ChartCreator aggregatingCreator = new AggregatingChartCreator(info, true);
    Chart aggregatedChart = aggregatingCreator.create();
    assertThat(aggregatedChart.getRowCount()).isEqualTo(threads);
    assertThat(aggregatedChart.getSortedRows().get(0).getBars()).hasSize(1);

    ChartCreator detailedCreator = new DetailedChartCreator(info);
    Chart detailedChart = detailedCreator.create();
    assertThat(detailedChart.getSortedTypes()).hasSize(COMMON_CHART_TYPES + DETAILED_CHART_TYPES);
    assertThat(detailedChart.getRowCount()).isEqualTo(threads);
    assertThat(detailedChart.getSortedRows().get(0).getBars()).hasSize(1);
  }

  @Test
  public void testAggregatingChartCreator() throws Exception {
    Runnable run = new Runnable() {
      @Override
      public void run() {
        Profiler profiler = Profiler.instance();
        try (SilentCloseable c = profiler.profile(ProfilerTask.ACTION, "action")) { // Stays
          task(profiler, ProfilerTask.REMOTE_EXECUTION, "remote execution"); // Removed
          task(profiler, ProfilerTask.ACTION_CHECK, "check"); // Removed
          task(profiler, ProfilerTask.ACTION_LOCK, "lock"); // Stays
        }
        task(profiler, ProfilerTask.INFO, "info"); // Stays
        task(profiler, ProfilerTask.VFS_STAT, "stat"); // Stays, if showVFS
        task(profiler, ProfilerTask.WAIT, "wait"); // Stays
      }
    };
    ProfileInfo info = createProfileInfo(run, 1);

    ChartCreator aggregatingCreator = new AggregatingChartCreator(info, true);
    Chart aggregatedChart = aggregatingCreator.create();
    assertThat(aggregatedChart.getSortedTypes())
        .hasSize(COMMON_CHART_TYPES + AGGREGATED_CHART_TYPES);
    assertThat(aggregatedChart.getSortedRows().get(0).getBars()).hasSize(5);

    ChartCreator aggregatingNoVfsCreator = new AggregatingChartCreator(info, false);
    Chart aggregatedNoVfsChart = aggregatingNoVfsCreator.create();
    assertThat(aggregatedNoVfsChart.getSortedTypes())
        .hasSize(COMMON_CHART_TYPES + AGGREGATED_CHART_NO_VFS_TYPES);
    assertThat(aggregatedNoVfsChart.getSortedRows().get(0).getBars()).hasSize(4);

    ChartCreator detailedCreator = new DetailedChartCreator(info);
    Chart detailedChart = detailedCreator.create();
    assertThat(detailedChart.getSortedTypes())
        .hasSize(COMMON_CHART_TYPES + ProfilerTask.values().length);
    assertThat(detailedChart.getSortedRows().get(0).getBars()).hasSize(7);
  }

  @Test
  public void testChart() throws Exception {
    Chart chart = new Chart();

    ChartBarType type3 = chart.createType("name3", Color.GREEN);
    ChartBarType type2 = chart.createType("name2", Color.RED);
    ChartBarType type1 = chart.createType("name1", Color.BLACK);
    List<ChartBarType> types = chart.getSortedTypes();
    assertThat(types).hasSize(3);
    assertThat(types.get(0).getName()).isEqualTo(type1.getName());
    assertThat(types.get(0).getColor()).isEqualTo(type1.getColor());
    assertThat(types.get(1).getName()).isEqualTo(type2.getName());
    assertThat(types.get(1).getColor()).isEqualTo(type2.getColor());
    assertThat(types.get(2).getName()).isEqualTo(type3.getName());
    assertThat(types.get(2).getColor()).isEqualTo(type3.getColor());

    assertThat(chart.lookUpType("name3")).isSameAs(type3);
    assertThat(chart.lookUpType("name2")).isSameAs(type2);
    assertThat(chart.lookUpType("name1")).isSameAs(type1);

    assertThat(chart.lookUpType("wergl")).isSameAs(Chart.UNKNOWN_TYPE);
    types = chart.getSortedTypes();
    assertThat(types).hasSize(4);

    chart.addBar(1, 2, 3, type1, "label1");
    chart.addBar(2, 3, 4, type2, "label2");
    chart.addBar(2, 4, 5, type3, "label3");
    chart.addBar(3, 3, 4, type2, "label4");
    chart.addBar(3, 4, 5, type3, "label5");
    chart.addBar(3, 5, 6, type3, "label6");

    assertThat(chart.getMaxStop()).isEqualTo(6);
    assertThat(chart.getRowCount()).isEqualTo(3);

    List<ChartRow> rows = chart.getSortedRows();
    assertThat(rows).hasSize(3);
    assertThat(rows.get(0).getBars()).hasSize(1);
    assertThat(rows.get(1).getBars()).hasSize(2);
    assertThat(rows.get(2).getBars()).hasSize(3);

    ChartBar bar = rows.get(0).getBars().get(0);
    assertThat(bar.getStart()).isEqualTo(2);
    assertThat(bar.getStop()).isEqualTo(3);
    assertThat(bar.getType()).isSameAs(type1);
    assertThat(bar.getLabel()).isEqualTo("label1");
  }

  @Test
  public void testChartRows() throws Exception {
    ChartRow row1 = new ChartRow("1", 0);
    ChartRow row2 = new ChartRow("2", 1);
    ChartRow row3 = new ChartRow("3", 1);

    assertThat(row1.getId()).isEqualTo("1");
    assertThat(row1.getIndex()).isEqualTo(0);

    assertThat(row1.compareTo(row2)).isEqualTo(-1);
    assertThat(row2.compareTo(row1)).isEqualTo(1);
    assertThat(row2.compareTo(row3)).isEqualTo(0);

    row1.addBar(new ChartBar(row1, 1, 2, new ChartBarType("name1", Color.BLACK), false, "label1"));
    row1.addBar(new ChartBar(row1, 2, 3, new ChartBarType("name2", Color.RED), false, "label2"));

    assertThat(row1.getBars()).hasSize(2);
    assertThat(row1.getBars().get(0).getLabel()).isEqualTo("label1");
    assertThat(row1.getBars().get(1).getLabel()).isEqualTo("label2");
  }

  @Test
  public void testChartBarTypes() throws Exception {
    ChartBarType type1 = new ChartBarType("name1", Color.BLACK);
    ChartBarType type2 = new ChartBarType("name2", Color.RED);
    ChartBarType type3 = new ChartBarType("name2", Color.GREEN);

    assertThat(type1.compareTo(type2)).isEqualTo(-1);
    assertThat(type2.compareTo(type1)).isEqualTo(1);
    assertThat(type2.compareTo(type3)).isEqualTo(0);

    assertThat(type2).isEqualTo(type3);
    assertThat(type1.equals(type3)).isFalse();
    assertThat(type1.equals(type2)).isFalse();

    assertThat(type2.hashCode()).isEqualTo(type3.hashCode());
    assertThat(type1.hashCode() == type2.hashCode()).isFalse();
    assertThat(type1.hashCode() == type3.hashCode()).isFalse();
  }

  @Test
  public void testChartBar() throws Exception {
    ChartRow row1 = new ChartRow("1", 0);
    ChartBarType type = new ChartBarType("name1", Color.BLACK);
    ChartBar bar1 = new ChartBar(row1, 1, 2, type, false, "label1");
    assertThat(bar1.getRow()).isEqualTo(row1);
    assertThat(bar1.getStart()).isEqualTo(1);
    assertThat(bar1.getStop()).isEqualTo(2);
    assertThat(bar1.getType()).isSameAs(type);
    assertThat(bar1.getLabel()).isEqualTo("label1");
  }

  @Test
  public void testVisitor() throws Exception {
    Chart chart = new Chart();
    ChartBarType type3 = chart.createType("name3", Color.GREEN);
    ChartBarType type2 = chart.createType("name2", Color.RED);
    ChartBarType type1 = chart.createType("name1", Color.BLACK);
    chart.addBar(1, 2, 3, type1, "label1");
    chart.addBar(2, 3, 4, type2, "label2");
    chart.addBar(2, 4, 5, type3, "label3");
    chart.addBar(3, 3, 4, type2, "label4");
    chart.addBar(3, 4, 5, type3, "label5");
    chart.addBar(3, 5, 6, type3, "label6");

    TestingChartVisitor visitor = new TestingChartVisitor();
    chart.accept(visitor);
    assertThat(visitor.beginChartCount).isEqualTo(1);
    assertThat(visitor.endChartCount).isEqualTo(1);
    assertThat(visitor.rowCount).isEqualTo(3);
    assertThat(visitor.barCount).isEqualTo(6);
    assertThat(visitor.columnCount).isEqualTo(0);
    assertThat(visitor.lineCount).isEqualTo(0);
  }

  @Test
  public void testHtmlChartVisitorFormatColor() {
    Locale defaultLocale = Locale.getDefault();

    Locale.setDefault(Locale.GERMANY);
    String black = HtmlChartVisitor.formatColor(Color.GRAY);
    String[] grayComponents = black.split(",");
    assertThat(grayComponents.length).isEqualTo(4);

    Locale.setDefault(defaultLocale);
  }

  private ProfileInfo createProfileInfo(Runnable runnable, int noOfRows) throws Exception {
    Scratch scratch = new Scratch();
    Path cacheDir = scratch.dir("/tmp");
    Path cacheFile = cacheDir.getRelative("profile1.dat");
    Profiler profiler = Profiler.instance();
    try (OutputStream out = cacheFile.getOutputStream()) {
      profiler.start(
          ProfiledTaskKinds.ALL,
          out,
          Profiler.Format.BINARY_BAZEL_FORMAT,
          "basic test",
          false,
          BlazeClock.instance(),
          BlazeClock.instance().nanoTime(),
          /* enabledCpuUsageProfiling= */ false);

      // Write from multiple threads to generate multiple rows in the chart.
      for (int i = 0; i < noOfRows; i++) {
        Thread t = new Thread(runnable);
        t.start();
        t.join();
      }

      profiler.stop();
    }
    try (InputStream in = cacheFile.getInputStream()) {
      return ProfileInfo.loadProfile(in);
    }
  }

  private void task(final Profiler profiler, ProfilerTask task, String name) {
    try (SilentCloseable c = profiler.profile(task, name)) {
      Thread.sleep(100);
    } catch (InterruptedException e) {
      // ignore
    }
  }

  private static final class TestingChartVisitor implements ChartVisitor {
    private int rowCount;
    private int endChartCount;
    private int barCount;
    private int beginChartCount;
    private int columnCount;
    private int lineCount;

    @Override
    public void visit(Chart chart) {
      beginChartCount++;
    }

    @Override
    public void visit(ChartRow chartRow) {
      rowCount++;
    }

    @Override
    public void visit(ChartBar chartBar) {
      barCount++;
    }

    @Override
    public void visit(ChartColumn chartColumn) {
      columnCount++;
    }

    @Override
    public void visit(ChartLine chartLine) {
      lineCount++;
    }

    @Override
    public void endVisit(Chart chart) {
      endChartCount++;
    }
  }
}
