blob: 289e62d81fc6b4190f3fb61e4c531a075980cb49 [file] [log] [blame]
package iso
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
import (
"fmt"
"io"
"os"
"os/exec"
"strings"
"testing"
)
// environment variables used by the mock command
const (
mockCmdEnvInvoke = "GO_HELPER_CMD"
mockCmdEnvError = "GO_HELPER_CMD_FORCE_ERROR"
mockCmdEnvOutput = "GO_HELPER_CMD_OUTPUT"
)
// mockISOCmd returns a modified version of the given Cmd
// so that when run, the command actually invokes the
// TestHelperMockCmd test. See TestHelperMockCmd for
// more details on its behavior.
//
// - If forceError is true, the command will exit a non-0 code and write to STDERR.
// - If cmdOutput is blank, the command will write to STDOUT, otherwise
// it will write its output to the file specified by cmdOutput.
func mockISOCmd(cmd *exec.Cmd, forceError bool, cmdOutput string) *exec.Cmd {
args := []string{
"-test.run=TestHelperMockCmd",
"--",
}
args = append(args, cmd.Args...)
// os.Args[0] is the invokation of this test binary
mocked := exec.Command(os.Args[0], args...)
env := cmd.Env
env = append(cmd.Env, fmt.Sprintf("%s=1", mockCmdEnvInvoke))
if forceError {
env = append(env, fmt.Sprintf("%s=1", mockCmdEnvError))
}
if cmdOutput != "" {
env = append(env, fmt.Sprintf("%s=%s", mockCmdEnvOutput, cmdOutput))
}
mocked.Env = env
return mocked
}
// TestHelperMockCmd is a special test case that is meant to be invoked
// by a subprocess, e.g. go test -run=TestHelperMockCmd.
//
// Described in detail at: https://npf.io/2015/06/testing-exec-command/
//
// In order for the test to act like a subprocess, the GO_HELPER_CMD environment
// variable must be set, otherwise the test is skipped. Use the mockISOCmd to
// assist with modifying an existing exec.Cmd to use this helper.
//
// The test writes to either STDOUT/STDERR/or a file all arguments it receives
// after the '--' argument. In practice, the mockISOCmd passes the original
// command's arguments in this position, essentially echoing back what the
// original command was.
func TestHelperMockCmd(t *testing.T) {
if os.Getenv(mockCmdEnvInvoke) != "1" {
return
}
var (
respCode int
dest io.Writer
)
switch {
case os.Getenv(mockCmdEnvError) == "1":
respCode = 1
dest = os.Stderr
case os.Getenv(mockCmdEnvOutput) != "":
fd, err := os.Create(os.Getenv(mockCmdEnvOutput))
if err == nil {
defer fd.Close()
dest = fd
} else {
respCode = 100
dest = os.Stderr
}
default:
dest = os.Stdout
}
// Set args to all arguments past '--'.
var args []string
for i, v := range os.Args {
if v == "--" {
args = os.Args[i+1:]
break
}
}
fmt.Fprintf(dest, strings.Join(args, " "))
os.Exit(respCode)
}