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

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 testCatRandomBinary() throws Exception {
    final Command command = new Command(new String[] {"cat"});
    byte[] randomBytes = getRandomBytes();
    final CommandResult result = command.execute(randomBytes);
    assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0);
    TestUtil.assertArrayEquals(randomBytes, result.getStdout());
    assertThat(result.getStderr()).isEmpty();
   }

  @Test
  public void testCatRandomBinaryToOutputStream() throws Exception {
    final Command command = new Command(new String[] {"cat"});
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ByteArrayOutputStream err = new ByteArrayOutputStream();
    byte[] randomBytes = getRandomBytes();
    final CommandResult result = command.execute(randomBytes,
                                                 Command.NO_OBSERVER, out, err);
    assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0);
    TestUtil.assertArrayEquals(randomBytes, out.toByteArray());
    assertThat(err.toByteArray()).isEmpty();
    assertOutAndErrNotAvailable(result);
  }

  @Test
  public void testCatRandomBinaryToErrorStream() 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();
    final CommandResult result = command.execute(randomBytes,
                                                 Command.NO_OBSERVER, out, err);
    assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0);
    assertThat(out.toByteArray()).isEmpty();
    TestUtil.assertArrayEquals(randomBytes, err.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);

    final CommandResult result = command.execute(in,
                                                 Command.NO_OBSERVER, out, err);
    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(Command.NO_INPUT, Command.NO_OBSERVER, 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) {
    try {
      result.getStdout();
      fail();
    } catch (IllegalStateException e){}
    try {
      result.getStderr();
      fail();
    } catch (IllegalStateException e){}
  }

  @Test
  public void testCatAllByteValues() throws Exception {
    final Command command = new Command(new String[] {"cat"});
    byte[] allByteValues = getAllByteValues();
    final CommandResult result = command.execute(allByteValues);
    assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0);
    assertThat(result.getStderr()).isEmpty();
    TestUtil.assertArrayEquals(allByteValues, result.getStdout());
  }

}
