// 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.unix.UnixFileSystem;
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 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 FileSystem testFS;
  private Path workingDir;

  @Before
  public final void createFileSystem() throws Exception {
    testFS = new UnixFileSystem(DigestHashFunction.DEFAULT_HASH_FOR_TESTS);
    workingDir = testFS.getPath(TestUtils.makeTempDir().getCanonicalPath());
  }

  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);
  }
}
