// 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.shell;

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

import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import java.io.BufferedOutputStream;
import java.time.Duration;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link ExecutionStatistics}. */
@RunWith(JUnit4.class)
public final class ExecutionStatisticsTest {
  private Path workingDir;

  @Before
  public final void createFileSystem() throws Exception {
    FileSystem testFS = new InMemoryFileSystem(DigestHashFunction.getDefaultUnchecked());
    workingDir = testFS.getPath(TestUtils.makeTempDir().getCanonicalPath());
    workingDir.createDirectoryAndParents();
  }

  private Path createExecutionStatisticsProtoFile(
      com.google.devtools.build.lib.shell.Protos.ExecutionStatistics executionStatisticsProto)
      throws Exception {
    Path encodedProtoFile = workingDir.getRelative("encoded_action_execution_proto");
    try (BufferedOutputStream bufferedOutputStream =
        new BufferedOutputStream(encodedProtoFile.getOutputStream())) {
      executionStatisticsProto.writeTo(bufferedOutputStream);
    }
    return encodedProtoFile;
  }

  @Test
  public void testNoResourceUsage_whenNoResourceUsageProto() throws Exception {
    com.google.devtools.build.lib.shell.Protos.ExecutionStatistics executionStatisticsProto =
        com.google.devtools.build.lib.shell.Protos.ExecutionStatistics.getDefaultInstance();
    Path protoFilename = createExecutionStatisticsProtoFile(executionStatisticsProto);

    Optional<ExecutionStatistics.ResourceUsage> resourceUsage =
        ExecutionStatistics.getResourceUsage(protoFilename);
    assertThat(resourceUsage).isEmpty();
  }

  @Test
  public void testStatiticsProvided_fromProtoFilename() throws Exception {
    Duration riggedUserExecutionTime = Duration.ofSeconds(42).plusNanos(19790000);
    Duration riggedSystemExecutionTime = Duration.ofSeconds(33).plusNanos(290000);
    long riggedMaximumResidentSetSize = 1;
    long riggedIntegralSharedMemorySize = 2;
    long riggedIntegralUnsharedDataSize = 3;
    long riggedIntegralUnsharedStackSize = 4;
    long riggedPageReclaims = 5;
    long riggedPageFaults = 6;
    long riggedSwaps = 7;
    long riggedBlockInputOperations = 8;
    long riggedBlockOutputOperations = 9;
    long riggedIpcMessagesSent = 10;
    long riggedIpcMessagesReceived = 11;
    long riggedSignalsReceived = 12;
    long riggedVoluntaryContextSwitches = 13;
    long riggedInvoluntaryContextSwitches = 14;

    com.google.devtools.build.lib.shell.Protos.ResourceUsage resourceUsageProto =
        com.google.devtools.build.lib.shell.Protos.ResourceUsage.newBuilder()
            .setUtimeSec(riggedUserExecutionTime.getSeconds())
            .setUtimeUsec((long) (riggedUserExecutionTime.getNano() / 1000))
            .setStimeSec(riggedSystemExecutionTime.getSeconds())
            .setStimeUsec((long) (riggedSystemExecutionTime.getNano() / 1000))
            .setMaxrss(riggedMaximumResidentSetSize)
            .setIxrss(riggedIntegralSharedMemorySize)
            .setIdrss(riggedIntegralUnsharedDataSize)
            .setIsrss(riggedIntegralUnsharedStackSize)
            .setMinflt(riggedPageReclaims)
            .setMajflt(riggedPageFaults)
            .setNswap(riggedSwaps)
            .setInblock(riggedBlockInputOperations)
            .setOublock(riggedBlockOutputOperations)
            .setMsgsnd(riggedIpcMessagesSent)
            .setMsgrcv(riggedIpcMessagesReceived)
            .setNsignals(riggedSignalsReceived)
            .setNvcsw(riggedVoluntaryContextSwitches)
            .setNivcsw(riggedInvoluntaryContextSwitches)
            .build();

    com.google.devtools.build.lib.shell.Protos.ExecutionStatistics executionStatisticsProto =
        com.google.devtools.build.lib.shell.Protos.ExecutionStatistics.newBuilder()
            .setResourceUsage(resourceUsageProto)
            .build();
    Path protoFilename = createExecutionStatisticsProtoFile(executionStatisticsProto);

    Optional<ExecutionStatistics.ResourceUsage> maybeResourceUsage =
        ExecutionStatistics.getResourceUsage(protoFilename);
    assertThat(maybeResourceUsage).isPresent();
    ExecutionStatistics.ResourceUsage resourceUsage = maybeResourceUsage.get();

    assertThat(resourceUsage.getUserExecutionTime()).isEqualTo(riggedUserExecutionTime);
    assertThat(resourceUsage.getSystemExecutionTime()).isEqualTo(riggedSystemExecutionTime);
    assertThat(resourceUsage.getMaximumResidentSetSize()).isEqualTo(riggedMaximumResidentSetSize);
    assertThat(resourceUsage.getIntegralSharedMemorySize())
        .isEqualTo(riggedIntegralSharedMemorySize);
    assertThat(resourceUsage.getIntegralUnsharedDataSize())
        .isEqualTo(riggedIntegralUnsharedDataSize);
    assertThat(resourceUsage.getIntegralUnsharedStackSize())
        .isEqualTo(riggedIntegralUnsharedStackSize);
    assertThat(resourceUsage.getPageReclaims()).isEqualTo(riggedPageReclaims);
    assertThat(resourceUsage.getPageFaults()).isEqualTo(riggedPageFaults);
    assertThat(resourceUsage.getSwaps()).isEqualTo(riggedSwaps);
    assertThat(resourceUsage.getBlockInputOperations()).isEqualTo(riggedBlockInputOperations);
    assertThat(resourceUsage.getBlockOutputOperations()).isEqualTo(riggedBlockOutputOperations);
    assertThat(resourceUsage.getIpcMessagesSent()).isEqualTo(riggedIpcMessagesSent);
    assertThat(resourceUsage.getIpcMessagesReceived()).isEqualTo(riggedIpcMessagesReceived);
    assertThat(resourceUsage.getSignalsReceived()).isEqualTo(riggedSignalsReceived);
    assertThat(resourceUsage.getVoluntaryContextSwitches())
        .isEqualTo(riggedVoluntaryContextSwitches);
    assertThat(resourceUsage.getInvoluntaryContextSwitches())
        .isEqualTo(riggedInvoluntaryContextSwitches);
  }
}
