github.com/mponton/terratest@v0.44.0/modules/shell/command_test.go (about)

     1  package shell
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"regexp"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  
    12  	"github.com/mponton/terratest/modules/logger"
    13  	"github.com/mponton/terratest/modules/random"
    14  )
    15  
    16  func TestRunCommandAndGetOutput(t *testing.T) {
    17  	t.Parallel()
    18  
    19  	text := "Hello, World"
    20  	cmd := Command{
    21  		Command: "echo",
    22  		Args:    []string{text},
    23  	}
    24  
    25  	out := RunCommandAndGetOutput(t, cmd)
    26  	assert.Equal(t, text, strings.TrimSpace(out))
    27  }
    28  
    29  func TestRunCommandAndGetOutputOrder(t *testing.T) {
    30  	t.Parallel()
    31  
    32  	stderrText := "Hello, Error"
    33  	stdoutText := "Hello, World"
    34  	expectedText := "Hello, Error\nHello, World\nHello, Error\nHello, World\nHello, Error\nHello, Error"
    35  	bashCode := fmt.Sprintf(`
    36  echo_stderr(){
    37  	(>&2 echo "%s")
    38  	# Add sleep to stabilize the test
    39  	sleep .01s
    40  }
    41  echo_stdout(){
    42  	echo "%s"
    43  	# Add sleep to stabilize the test
    44  	sleep .01s
    45  }
    46  echo_stderr
    47  echo_stdout
    48  echo_stderr
    49  echo_stdout
    50  echo_stderr
    51  echo_stderr
    52  `,
    53  		stderrText,
    54  		stdoutText,
    55  	)
    56  	cmd := Command{
    57  		Command: "bash",
    58  		Args:    []string{"-c", bashCode},
    59  	}
    60  
    61  	out := RunCommandAndGetOutput(t, cmd)
    62  	assert.Equal(t, expectedText, strings.TrimSpace(out))
    63  }
    64  
    65  func TestRunCommandGetExitCode(t *testing.T) {
    66  	t.Parallel()
    67  
    68  	cmd := Command{
    69  		Command: "bash",
    70  		Args:    []string{"-c", "exit 42"},
    71  		Logger:  logger.Discard,
    72  	}
    73  
    74  	out, err := RunCommandAndGetOutputE(t, cmd)
    75  	assert.Equal(t, "", out)
    76  	assert.NotNil(t, err)
    77  	code, err := GetExitCodeForRunCommandError(err)
    78  	assert.Nil(t, err)
    79  	assert.Equal(t, code, 42)
    80  }
    81  
    82  func TestRunCommandAndGetOutputConcurrency(t *testing.T) {
    83  	t.Parallel()
    84  
    85  	uniqueStderr := random.UniqueId()
    86  	uniqueStdout := random.UniqueId()
    87  
    88  	bashCode := fmt.Sprintf(`
    89  echo_stderr(){
    90  	sleep .0$[ ( $RANDOM %% 10 ) + 1 ]s
    91  	(>&2 echo "%s")
    92  }
    93  echo_stdout(){
    94  	sleep .0$[ ( $RANDOM %% 10 ) + 1 ]s
    95  	echo "%s"
    96  }
    97  for i in {1..500}
    98  do
    99  	echo_stderr &
   100  	echo_stdout &
   101  done
   102  wait
   103  `,
   104  		uniqueStderr,
   105  		uniqueStdout,
   106  	)
   107  	cmd := Command{
   108  		Command: "bash",
   109  		Args:    []string{"-c", bashCode},
   110  		Logger:  logger.Discard,
   111  	}
   112  
   113  	out := RunCommandAndGetOutput(t, cmd)
   114  	stdoutReg := regexp.MustCompile(uniqueStdout)
   115  	stderrReg := regexp.MustCompile(uniqueStderr)
   116  	assert.Equal(t, 500, len(stdoutReg.FindAllString(out, -1)))
   117  	assert.Equal(t, 500, len(stderrReg.FindAllString(out, -1)))
   118  }
   119  
   120  func TestRunCommandWithHugeLineOutput(t *testing.T) {
   121  	t.Parallel()
   122  
   123  	// generate a ~100KB line
   124  	bashCode := fmt.Sprintf(`
   125  for i in {0..35000}
   126  do
   127    echo -n foo
   128  done
   129  echo
   130  `)
   131  
   132  	cmd := Command{
   133  		Command: "bash",
   134  		Args:    []string{"-c", bashCode},
   135  		Logger:  logger.Discard, // don't print that line to stdout
   136  	}
   137  
   138  	out, err := RunCommandAndGetOutputE(t, cmd)
   139  	assert.NoError(t, err)
   140  
   141  	var buffer bytes.Buffer
   142  	for i := 0; i <= 35000; i++ {
   143  		buffer.WriteString("foo")
   144  	}
   145  
   146  	assert.Equal(t, out, buffer.String())
   147  }
   148  
   149  // TestRunCommandOutputError ensures that getting the output never panics, even if no command was ever run.
   150  func TestRunCommandOutputError(t *testing.T) {
   151  	t.Parallel()
   152  
   153  	cmd := Command{
   154  		Command: "thisbinarydoesnotexistbecausenobodyusesnamesthatlong",
   155  		Args:    []string{"-no-flag"},
   156  		Logger:  logger.Discard,
   157  	}
   158  
   159  	out, err := RunCommandAndGetOutputE(t, cmd)
   160  	assert.Equal(t, "", out)
   161  	assert.NotNil(t, err)
   162  }
   163  
   164  func TestCommandOutputType(t *testing.T) {
   165  	t.Parallel()
   166  
   167  	stdout := "hello world"
   168  	stderr := "this command has failed"
   169  
   170  	_, err := RunCommandAndGetOutputE(t, Command{
   171  		Command: "sh",
   172  		Args:    []string{"-c", `echo "` + stdout + `" && echo "` + stderr + `" >&2 && exit 1`},
   173  		Logger:  logger.Discard,
   174  	})
   175  
   176  	if err != nil {
   177  		o, ok := err.(*ErrWithCmdOutput)
   178  		if !ok {
   179  			t.Fatalf("did not get correct type. got=%T", err)
   180  		}
   181  		assert.Len(t, o.Output.Stdout(), len(stdout))
   182  		assert.Len(t, o.Output.Stderr(), len(stderr))
   183  		assert.Len(t, o.Output.Combined(), len(stdout)+len(stderr)+1) // +1 for newline
   184  	}
   185  }