// Copyright 2016-2018, Pulumi Corporation. // // 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 integration import ( "fmt" "os" "os/exec" "path/filepath" "strings" "testing" "time" "github.com/pulumi/pulumi/sdk/v2/go/common/util/cmdutil" ) // RunCommand executes the specified command and additional arguments, wrapping any output in the // specialized test output streams that list the location the test is running in. func RunCommand(t *testing.T, name string, args []string, wd string, opts *ProgramTestOptions) error { path := args[0] command := strings.Join(args, " ") t.Logf("**** Invoke '%v' in '%v'", command, wd) env := os.Environ() if opts.Env != nil { env = append(env, opts.Env...) } env = append(env, "PULUMI_DEBUG_COMMANDS=true") env = append(env, "PULUMI_RETAIN_CHECKPOINTS=true") env = append(env, "PULUMI_CONFIG_PASSPHRASE=correct horse battery staple") cmd := exec.Cmd{ Path: path, Dir: wd, Args: args, Env: env, } startTime := time.Now() var runout []byte var runerr error if opts.Verbose || os.Getenv("PULUMI_VERBOSE_TEST") != "" { cmd.Stdout = opts.Stdout cmd.Stderr = opts.Stderr runerr = cmd.Run() } else { runout, runerr = cmd.CombinedOutput() } endTime := time.Now() if opts.ReportStats != nil { // Note: This data is archived and used by external analytics tools. Take care if changing the schema or format // of this data. opts.ReportStats.ReportCommand(TestCommandStats{ StartTime: startTime.Format("2006/01/02 15:04:05"), EndTime: endTime.Format("2006/01/02 15:04:05"), ElapsedSeconds: float64((endTime.Sub(startTime)).Nanoseconds()) / 1000000000, StepName: name, CommandLine: command, StackName: string(opts.GetStackName()), TestID: wd, TestName: filepath.Base(opts.Dir), IsError: runerr != nil, CloudURL: opts.CloudURL, }) } if runerr != nil { t.Logf("Invoke '%v' failed: %s\n", command, cmdutil.DetailedError(runerr)) if !opts.Verbose { // Make sure we write the output in case of a failure to stderr so // tests can assert the shape of the error message. _, _ = fmt.Fprintf(opts.Stderr, "%s\n", string(runout)) } } // If we collected any program output, write it to a log file -- success or failure. if len(runout) > 0 { if logFile, err := writeCommandOutput(name, wd, runout); err != nil { t.Logf("Failed to write output: %v", err) } else { t.Logf("Wrote output to %s", logFile) } } else { t.Log("Command completed without output") } return runerr } func withOptionalYarnFlags(args []string) []string { flags := os.Getenv("YARNFLAGS") if flags != "" { return append(args, flags) } return args } // addFlagIfNonNil will take a set of command-line flags, and add a new one if the provided flag value is not empty. func addFlagIfNonNil(args []string, flag, flagValue string) []string { if flagValue != "" { args = append(args, flag, flagValue) } return args }