// 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.DEFAULT_HASH_FOR_TESTS);
    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);
  }
}
