Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2015 The Bazel Authors. All rights reserved. |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | package com.google.devtools.build.lib.shell; |
| 15 | |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 16 | import static com.google.common.truth.Truth.assertThat; |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 17 | import static org.junit.Assert.fail; |
| 18 | |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 19 | import java.io.ByteArrayInputStream; |
| 20 | import java.io.ByteArrayOutputStream; |
| 21 | import java.util.Random; |
| 22 | import java.util.logging.Level; |
| 23 | import java.util.logging.Logger; |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 24 | import org.junit.Before; |
| 25 | import org.junit.Test; |
| 26 | import org.junit.runner.RunWith; |
| 27 | import org.junit.runners.JUnit4; |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 28 | |
| 29 | /** |
| 30 | * Tests the command class with large inputs |
| 31 | * |
| 32 | */ |
| 33 | @RunWith(JUnit4.class) |
| 34 | public class CommandLargeInputsTest { |
| 35 | |
| 36 | @Before |
Florian Weikert | 2c71a82 | 2015-12-02 17:22:38 +0000 | [diff] [blame] | 37 | public final void configureLogger() throws Exception { |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 38 | // enable all log statements to ensure there are no problems with |
| 39 | // logging code |
| 40 | Logger.getLogger("com.google.devtools.build.lib.shell.Command").setLevel(Level.FINEST); |
| 41 | } |
| 42 | |
| 43 | private byte[] getRandomBytes() { |
| 44 | byte[] randomBytes; |
| 45 | final Random rand = new Random(0xdeadbeef); |
| 46 | randomBytes = new byte[10000]; |
| 47 | rand.nextBytes(randomBytes); |
| 48 | return randomBytes; |
| 49 | } |
| 50 | |
| 51 | private byte[] getAllByteValues() { |
| 52 | byte[] allByteValues = new byte[Byte.MAX_VALUE - Byte.MIN_VALUE]; |
| 53 | for(int i = 0; i < allByteValues.length; i++) { |
| 54 | allByteValues[i] = (byte) (i + Byte.MIN_VALUE); |
| 55 | } |
| 56 | return allByteValues; |
| 57 | } |
| 58 | |
| 59 | @Test |
ulfjack | f2d4595 | 2017-08-09 15:27:49 +0200 | [diff] [blame^] | 60 | public void testCatRandomBinaryToOutputStream() throws Exception { |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 61 | final Command command = new Command(new String[] {"cat"}); |
| 62 | byte[] randomBytes = getRandomBytes(); |
ulfjack | f2d4595 | 2017-08-09 15:27:49 +0200 | [diff] [blame^] | 63 | ByteArrayInputStream in = new ByteArrayInputStream(randomBytes); |
| 64 | |
| 65 | CommandResult result = |
| 66 | command.executeAsync(in, Command.KILL_SUBPROCESS_ON_INTERRUPT).get(); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 67 | assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0); |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 68 | TestUtil.assertArrayEquals(randomBytes, result.getStdout()); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 69 | assertThat(result.getStderr()).isEmpty(); |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 70 | } |
| 71 | |
| 72 | @Test |
ulfjack | f2d4595 | 2017-08-09 15:27:49 +0200 | [diff] [blame^] | 73 | public void testCatRandomBinaryToErrorStream() throws Exception { |
| 74 | final Command command = new Command(new String[] {"/bin/sh", "-c", "cat >&2"}); |
| 75 | byte[] randomBytes = getRandomBytes(); |
| 76 | ByteArrayInputStream in = new ByteArrayInputStream(randomBytes); |
| 77 | |
| 78 | CommandResult result = |
| 79 | command.executeAsync(in, Command.KILL_SUBPROCESS_ON_INTERRUPT).get(); |
| 80 | assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0); |
| 81 | TestUtil.assertArrayEquals(randomBytes, result.getStderr()); |
| 82 | assertThat(result.getStdout()).isEmpty(); |
| 83 | } |
| 84 | |
| 85 | @Test |
| 86 | public void testCatRandomBinaryFromInputStreamToOutputStream() throws Exception { |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 87 | final Command command = new Command(new String[] {"cat"}); |
| 88 | ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| 89 | ByteArrayOutputStream err = new ByteArrayOutputStream(); |
| 90 | byte[] randomBytes = getRandomBytes(); |
ulfjack | f2d4595 | 2017-08-09 15:27:49 +0200 | [diff] [blame^] | 91 | ByteArrayInputStream in = new ByteArrayInputStream(randomBytes); |
| 92 | |
| 93 | CommandResult result = |
| 94 | command.executeAsync(in, out, err, Command.KILL_SUBPROCESS_ON_INTERRUPT).get(); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 95 | assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 96 | assertThat(err.toByteArray()).isEmpty(); |
ulfjack | f2d4595 | 2017-08-09 15:27:49 +0200 | [diff] [blame^] | 97 | TestUtil.assertArrayEquals(randomBytes, out.toByteArray()); |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 98 | assertOutAndErrNotAvailable(result); |
| 99 | } |
| 100 | |
| 101 | @Test |
ulfjack | f2d4595 | 2017-08-09 15:27:49 +0200 | [diff] [blame^] | 102 | public void testCatRandomBinaryFromInputStreamToErrorStream() throws Exception { |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 103 | final Command command = new Command(new String[] {"/bin/sh", "-c", "cat >&2"}); |
| 104 | ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| 105 | ByteArrayOutputStream err = new ByteArrayOutputStream(); |
| 106 | byte[] randomBytes = getRandomBytes(); |
| 107 | ByteArrayInputStream in = new ByteArrayInputStream(randomBytes); |
| 108 | |
ulfjack | f2d4595 | 2017-08-09 15:27:49 +0200 | [diff] [blame^] | 109 | CommandResult result = |
| 110 | command.executeAsync(in, out, err, Command.KILL_SUBPROCESS_ON_INTERRUPT).get(); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 111 | assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0); |
| 112 | assertThat(out.toByteArray()).isEmpty(); |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 113 | TestUtil.assertArrayEquals(randomBytes, err.toByteArray()); |
| 114 | assertOutAndErrNotAvailable(result); |
| 115 | } |
| 116 | |
| 117 | @Test |
| 118 | public void testStdoutInterleavedWithStdErr() throws Exception { |
| 119 | final Command command = new Command(new String[]{"/bin/bash", |
| 120 | "-c", "for i in $( seq 0 999); do (echo OUT$i >&1) && (echo ERR$i >&2); done" |
| 121 | }); |
| 122 | ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| 123 | ByteArrayOutputStream err = new ByteArrayOutputStream(); |
ulfjack | f2d4595 | 2017-08-09 15:27:49 +0200 | [diff] [blame^] | 124 | command.execute(out, err); |
Ulf Adams | 795895a | 2015-03-06 15:58:35 +0000 | [diff] [blame] | 125 | StringBuilder expectedOut = new StringBuilder(); |
| 126 | StringBuilder expectedErr = new StringBuilder(); |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 127 | for (int i = 0; i < 1000; i++) { |
Ulf Adams | 795895a | 2015-03-06 15:58:35 +0000 | [diff] [blame] | 128 | expectedOut.append("OUT").append(i).append("\n"); |
| 129 | expectedErr.append("ERR").append(i).append("\n"); |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 130 | } |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 131 | assertThat(out.toString("UTF-8")).isEqualTo(expectedOut.toString()); |
| 132 | assertThat(err.toString("UTF-8")).isEqualTo(expectedErr.toString()); |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 133 | } |
| 134 | |
| 135 | private void assertOutAndErrNotAvailable(final CommandResult result) { |
| 136 | try { |
| 137 | result.getStdout(); |
| 138 | fail(); |
| 139 | } catch (IllegalStateException e){} |
| 140 | try { |
| 141 | result.getStderr(); |
| 142 | fail(); |
| 143 | } catch (IllegalStateException e){} |
| 144 | } |
| 145 | |
| 146 | @Test |
| 147 | public void testCatAllByteValues() throws Exception { |
| 148 | final Command command = new Command(new String[] {"cat"}); |
| 149 | byte[] allByteValues = getAllByteValues(); |
ulfjack | f2d4595 | 2017-08-09 15:27:49 +0200 | [diff] [blame^] | 150 | ByteArrayInputStream in = new ByteArrayInputStream(allByteValues); |
| 151 | |
| 152 | CommandResult result = |
| 153 | command.executeAsync(in, Command.KILL_SUBPROCESS_ON_INTERRUPT).get(); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 154 | assertThat(result.getTerminationStatus().getRawExitCode()).isEqualTo(0); |
| 155 | assertThat(result.getStderr()).isEmpty(); |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 156 | TestUtil.assertArrayEquals(allByteValues, result.getStdout()); |
| 157 | } |
Han-Wen Nienhuys | b0e387b | 2015-02-12 13:27:06 +0000 | [diff] [blame] | 158 | } |