github.com/attic-labs/noms@v0.0.0-20210827224422-e5fa29d95e8b/tools/runner/serial_test.go (about)

     1  // Copyright 2016 Attic Labs, Inc. All rights reserved.
     2  // Licensed under the Apache License, version 2.0:
     3  // http://www.apache.org/licenses/LICENSE-2.0
     4  
     5  package runner
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io"
    11  	"io/ioutil"
    12  	"os"
    13  	"path/filepath"
    14  	"runtime"
    15  	"strings"
    16  	"testing"
    17  
    18  	"github.com/stretchr/testify/suite"
    19  )
    20  
    21  const (
    22  	boilerplate = `
    23  from __future__ import print_function
    24  import os, sys
    25  
    26  %s
    27  `
    28  	buildFileBasename = "build.py"
    29  )
    30  
    31  func TestSerialRunnerTestSuite(t *testing.T) {
    32  	suite.Run(t, &SerialRunnerTestSuite{})
    33  }
    34  
    35  type SerialRunnerTestSuite struct {
    36  	suite.Suite
    37  	dir   string
    38  	index int
    39  }
    40  
    41  func (suite *SerialRunnerTestSuite) SetupTest() {
    42  	var err error
    43  	suite.dir, err = ioutil.TempDir(os.TempDir(), "")
    44  	suite.NoError(err)
    45  }
    46  
    47  func (suite *SerialRunnerTestSuite) TearDownTest() {
    48  	os.Remove(suite.dir)
    49  }
    50  
    51  func (suite *SerialRunnerTestSuite) TestForceRunInDir() {
    52  	scriptPath := filepath.Join(suite.dir, buildFileBasename)
    53  	suite.makeTestBuildFile(scriptPath, []string{"print(os.getcwd(), file=sys.stdout)"})
    54  
    55  	old := os.Stdout // keep backup of the real stdout
    56  	r, w, err := os.Pipe()
    57  	suite.NoError(err)
    58  	os.Stdout = w
    59  	defer func() { os.Stdout = old }()
    60  	defer r.Close()
    61  
    62  	outC := make(chan string)
    63  	// copy the output in a separate goroutine so printing can't block indefinitely
    64  	go func() {
    65  		buf := &bytes.Buffer{}
    66  		io.Copy(buf, r)
    67  		outC <- buf.String()
    68  	}()
    69  
    70  	ForceRunInDir(suite.dir, nil, "python", scriptPath)
    71  
    72  	w.Close()
    73  	out := strings.TrimSpace(<-outC)
    74  	actualSuiteDir, err := filepath.EvalSymlinks(suite.dir)
    75  	suite.NoError(err)
    76  	suite.Equal(actualSuiteDir, out)
    77  }
    78  
    79  func (suite *SerialRunnerTestSuite) TestRunInDir() {
    80  	scriptPath := filepath.Join(suite.dir, buildFileBasename)
    81  	suite.makeTestBuildFile(scriptPath, []string{
    82  		"print(os.getcwd(), file=sys.stdout)",
    83  		"print('error', file=sys.stderr)",
    84  	})
    85  
    86  	stdout := &bytes.Buffer{}
    87  	stderr := &bytes.Buffer{}
    88  	RunInDir(stdout, stderr, suite.dir, "python", scriptPath)
    89  	actualSuiteDir, err := filepath.EvalSymlinks(suite.dir)
    90  	suite.NoError(err)
    91  	suite.Equal(actualSuiteDir, strings.TrimSpace(string(stdout.Bytes())))
    92  	suite.Equal("error", strings.TrimSpace(string(stderr.Bytes())))
    93  }
    94  
    95  func (suite *SerialRunnerTestSuite) TestEnvVars() {
    96  	makeEnvVarPrintBuildFile := func(path, varname string) {
    97  		fmtStatement := fmt.Sprintf(`print(os.environ['%s'], file=sys.stdout)`, varname)
    98  		suite.makeTestBuildFile(path, []string{fmtStatement})
    99  	}
   100  
   101  	type testCase struct {
   102  		path, varname, expected string
   103  	}
   104  	env := Env{
   105  		"PATH":                os.Getenv("PATH"),
   106  		"GOPATH":              os.Getenv("GOPATH"),
   107  		"NOMS_CHECKOUT_PATH":  "/where/noms/is",
   108  		"ATTIC_CHECKOUT_PATH": "/where/attic/is",
   109  	}
   110  	tests := []testCase{}
   111  	for n, v := range env {
   112  		tc := testCase{suite.uniqueBuildFile(), n, v}
   113  		makeEnvVarPrintBuildFile(tc.path, tc.varname)
   114  		tests = append(tests, tc)
   115  	}
   116  	gorootTestCase := testCase{suite.uniqueBuildFile(), "GOROOT", runtime.GOROOT()}
   117  	makeEnvVarPrintBuildFile(gorootTestCase.path, gorootTestCase.varname)
   118  	tests = append(tests, gorootTestCase)
   119  
   120  	log := &bytes.Buffer{}
   121  	if suite.True(Serial(log, log, env, suite.dir, buildFileBasename), "Serial() should have succeeded! logs:\n%s", string(log.Bytes())) {
   122  		logText := string(log.Bytes())
   123  		for _, tc := range tests {
   124  			suite.Contains(logText, tc.expected)
   125  		}
   126  	}
   127  }
   128  
   129  func (suite *SerialRunnerTestSuite) TestFailure() {
   130  	type testCase struct {
   131  		path, expected string
   132  	}
   133  	tests := []testCase{
   134  		{suite.uniqueBuildFile(), "Scoobaz"},
   135  		{suite.uniqueBuildFile(), "at the disco"},
   136  	}
   137  	goodOne := testCase{suite.uniqueBuildFile(), "All's well"}
   138  
   139  	suite.makeTestBuildFile(tests[0].path, []string{"Scoobaz() # Won't compile."})
   140  	suite.makeTestBuildFile(tests[1].path, []string{`assert(False, "at the disco") # Won't run.`})
   141  	suite.makeTestBuildFile(goodOne.path, []string{fmt.Sprintf(`print "%s"`, goodOne.expected)})
   142  
   143  	log := &bytes.Buffer{}
   144  	suite.False(Serial(log, log, Env{}, suite.dir, buildFileBasename))
   145  	logText := string(log.Bytes())
   146  	suite.Contains(logText, tests[0].expected)
   147  	suite.Contains(logText, tests[1].expected)
   148  }
   149  
   150  func (suite *SerialRunnerTestSuite) uniqueBuildFile() string {
   151  	suite.index++
   152  	return filepath.Join(suite.dir, fmt.Sprintf("%d", suite.index), buildFileBasename)
   153  }
   154  
   155  func (suite *SerialRunnerTestSuite) makeTestBuildFile(path string, statements []string) {
   156  	buf := &bytes.Buffer{}
   157  	fmt.Fprintf(buf, boilerplate, strings.Join(statements, "\n"))
   158  	err := os.MkdirAll(filepath.Dir(path), 0777)
   159  	suite.NoError(err)
   160  	err = ioutil.WriteFile(path, buf.Bytes(), 0755)
   161  	suite.NoError(err)
   162  }