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

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests the command class with large inputs
 *
 */
@RunWith(JUnit4.class)
public class CommandLargeInputsTest {

  @Before
  public final void configureLogger() throws Exception  {
    // enable all log statements to ensure there are no problems with
    // logging code
    Logger.getLogger("com.google.devtools.build.lib.shell.Command").setLevel(Level.FINEST);
  }

  private byte[] getRandomBytes() {
    byte[] randomBytes;
    final Random rand = new Random(0xdeadbeef);
    randomBytes = new byte[10000];
    rand.nextBytes(randomBytes);
    return randomBytes;
  }

  private byte[] getAllByteValues() {
    byte[] allByteValues = new byte[Byte.MAX_VALUE - Byte.MIN_VALUE];
    for(int i = 0; i < allByteValues.length; i++) {
      allByteValues[i] = (byte) (i + Byte.MIN_VALUE);
    }
    return allByteValues;
  }

  @Test
  public void testCatRandomBinaryToOutputStream() throws Exception {
    final Command command = new Command(new String[] {"cat"});
    byte[] randomBytes = getRandomBytes();
    ByteArrayInputStream in = new ByteArrayInputStream(randomBytes);

    CommandResult result =
        command.executeAsync(in, Command.KILL_SUBPROCESS_ON_INTERRUPT).get();
    assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0);
    TestUtil.assertArrayEquals(randomBytes, result.getStdout());
    assertThat(result.getStderr()).isEmpty();
   }

  @Test
  public void testCatRandomBinaryToErrorStream() throws Exception {
    final Command command = new Command(new String[] {"/bin/sh", "-c", "cat >&2"});
    byte[] randomBytes = getRandomBytes();
    ByteArrayInputStream in = new ByteArrayInputStream(randomBytes);

    CommandResult result =
        command.executeAsync(in, Command.KILL_SUBPROCESS_ON_INTERRUPT).get();
    assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0);
    TestUtil.assertArrayEquals(randomBytes, result.getStderr());
    assertThat(result.getStdout()).isEmpty();
   }

  @Test
  public void testCatRandomBinaryFromInputStreamToOutputStream() throws Exception {
    final Command command = new Command(new String[] {"cat"});
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ByteArrayOutputStream err = new ByteArrayOutputStream();
    byte[] randomBytes = getRandomBytes();
    ByteArrayInputStream in = new ByteArrayInputStream(randomBytes);

    CommandResult result =
        command.executeAsync(in, out, err, Command.KILL_SUBPROCESS_ON_INTERRUPT).get();
    assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0);
    assertThat(err.toByteArray()).isEmpty();
    TestUtil.assertArrayEquals(randomBytes, out.toByteArray());
    assertOutAndErrNotAvailable(result);
  }

  @Test
  public void testCatRandomBinaryFromInputStreamToErrorStream() throws Exception {
    final Command command = new Command(new String[] {"/bin/sh", "-c", "cat >&2"});
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ByteArrayOutputStream err = new ByteArrayOutputStream();
    byte[] randomBytes = getRandomBytes();
    ByteArrayInputStream in = new ByteArrayInputStream(randomBytes);

    CommandResult result =
        command.executeAsync(in, out, err, Command.KILL_SUBPROCESS_ON_INTERRUPT).get();
    assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0);
    assertThat(out.toByteArray()).isEmpty();
    TestUtil.assertArrayEquals(randomBytes, err.toByteArray());
    assertOutAndErrNotAvailable(result);
  }

  @Test
  public void testStdoutInterleavedWithStdErr() throws Exception {
    final Command command = new Command(new String[]{"/bin/bash",
      "-c", "for i in $( seq 0 999); do (echo OUT$i >&1) && (echo ERR$i  >&2); done"
    });
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ByteArrayOutputStream err = new ByteArrayOutputStream();
    command.execute(out, err);
    StringBuilder expectedOut = new StringBuilder();
    StringBuilder expectedErr = new StringBuilder();
    for (int i = 0; i < 1000; i++) {
      expectedOut.append("OUT").append(i).append("\n");
      expectedErr.append("ERR").append(i).append("\n");
    }
    assertThat(out.toString("UTF-8")).isEqualTo(expectedOut.toString());
    assertThat(err.toString("UTF-8")).isEqualTo(expectedErr.toString());
  }

  private void assertOutAndErrNotAvailable(final CommandResult result) {
    assertThrows(IllegalStateException.class, () -> result.getStdout());
    assertThrows(IllegalStateException.class, () -> result.getStderr());
  }

  @Test
  public void testCatAllByteValues() throws Exception {
    final Command command = new Command(new String[] {"cat"});
    byte[] allByteValues = getAllByteValues();
    ByteArrayInputStream in = new ByteArrayInputStream(allByteValues);

    CommandResult result =
        command.executeAsync(in, Command.KILL_SUBPROCESS_ON_INTERRUPT).get();
    assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0);
    assertThat(result.getStderr()).isEmpty();
    TestUtil.assertArrayEquals(allByteValues, result.getStdout());
  }
}
