github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/test/integration/exec_int_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"regexp"
     8  	"runtime"
     9  	"testing"
    10  
    11  	"github.com/ActiveState/cli/internal/testhelpers/suite"
    12  
    13  	"github.com/ActiveState/cli/internal/constants"
    14  	"github.com/ActiveState/cli/internal/fileutils"
    15  	"github.com/ActiveState/cli/internal/testhelpers/e2e"
    16  	"github.com/ActiveState/cli/internal/testhelpers/tagsuite"
    17  )
    18  
    19  type ExecIntegrationTestSuite struct {
    20  	tagsuite.Suite
    21  }
    22  
    23  func (suite *ExecIntegrationTestSuite) createProjectFile(ts *e2e.Session) {
    24  	ts.PrepareProject("ActiveState-CLI/Python3", "fbc613d6-b0b1-4f84-b26e-4aa5869c4e54")
    25  }
    26  
    27  func (suite *ExecIntegrationTestSuite) TestExec_Environment() {
    28  	suite.OnlyRunForTags(tagsuite.Exec)
    29  	ts := e2e.New(suite.T(), false)
    30  	defer ts.Close()
    31  
    32  	suite.createProjectFile(ts)
    33  
    34  	scriptBlock := `echo ${PATH:0:500}`
    35  	filename := fmt.Sprintf("%s/%s.sh", ts.Dirs.Work, suite.T().Name())
    36  	if runtime.GOOS == "windows" {
    37  		scriptBlock = `echo %PATH:~0,500%`
    38  		filename = fmt.Sprintf("%s/%s.bat", ts.Dirs.Work, suite.T().Name())
    39  	}
    40  
    41  	testScript := filepath.Join(filename)
    42  	err := fileutils.WriteFile(testScript, []byte(scriptBlock))
    43  	suite.Require().NoError(err)
    44  
    45  	err = os.Chmod(testScript, 0777)
    46  	suite.Require().NoError(err)
    47  
    48  	cp := ts.SpawnWithOpts(
    49  		e2e.OptArgs("exec", testScript),
    50  	)
    51  	cp.ExpectExitCode(0)
    52  	output := cp.Output()
    53  	suite.Contains(output, ts.Dirs.Bin, "PATH was not updated to contain cache directory, original PATH:", os.Getenv("PATH"))
    54  }
    55  
    56  func (suite *ExecIntegrationTestSuite) TestExec_ExitCode() {
    57  	suite.OnlyRunForTags(tagsuite.Exec)
    58  	ts := e2e.New(suite.T(), false)
    59  	defer ts.Close()
    60  
    61  	suite.createProjectFile(ts)
    62  
    63  	scriptBlock := `exit 42`
    64  	filename := fmt.Sprintf("%s/%s.sh", ts.Dirs.Work, suite.T().Name())
    65  	if runtime.GOOS == "windows" {
    66  		scriptBlock = `EXIT 42`
    67  		filename = fmt.Sprintf("%s/%s.bat", ts.Dirs.Work, suite.T().Name())
    68  	}
    69  
    70  	testScript := filepath.Join(filename)
    71  	err := fileutils.WriteFile(testScript, []byte(scriptBlock))
    72  	suite.Require().NoError(err)
    73  
    74  	err = os.Chmod(testScript, 0777)
    75  	suite.Require().NoError(err)
    76  
    77  	cp := ts.SpawnWithOpts(
    78  		e2e.OptArgs("exec", "--", testScript),
    79  	)
    80  	cp.ExpectExitCode(42)
    81  }
    82  
    83  func (suite *ExecIntegrationTestSuite) TestExec_Args() {
    84  	suite.OnlyRunForTags(tagsuite.Exec)
    85  	ts := e2e.New(suite.T(), false)
    86  	defer ts.Close()
    87  
    88  	suite.createProjectFile(ts)
    89  
    90  	scriptBlock := `
    91  for i; do
    92      echo $i
    93  done
    94  echo "Number of arguments: $#"
    95  `
    96  
    97  	filename := fmt.Sprintf("%s/%s.sh", ts.Dirs.Work, suite.T().Name())
    98  	if runtime.GOOS == "windows" {
    99  		scriptBlock = `
   100  		set argCount=0
   101  		for %%a in (%*) do (
   102  			echo %%a
   103  			set /A argCount+=1
   104  		)
   105  		echo Number of arguments: %argCount%`
   106  		filename = fmt.Sprintf("%s/%s.bat", ts.Dirs.Work, suite.T().Name())
   107  	}
   108  
   109  	testScript := filepath.Join(filename)
   110  	err := fileutils.WriteFile(testScript, []byte(scriptBlock))
   111  	suite.Require().NoError(err)
   112  
   113  	err = os.Chmod(testScript, 0777)
   114  	suite.Require().NoError(err)
   115  
   116  	args := []string{
   117  		"firstArgument",
   118  		"secondArgument",
   119  		"thirdArgument",
   120  	}
   121  
   122  	cp := ts.SpawnWithOpts(
   123  		e2e.OptArgs("exec", "--", testScript, args[0], args[1], args[2]),
   124  	)
   125  	cp.Expect(args[0])
   126  	cp.Expect(args[1])
   127  	cp.Expect(args[2])
   128  	cp.Expect(fmt.Sprintf("Number of arguments: %d", len(args)))
   129  	cp.ExpectExitCode(0)
   130  }
   131  
   132  func (suite *ExecIntegrationTestSuite) TestExec_Input() {
   133  	suite.OnlyRunForTags(tagsuite.Exec)
   134  	ts := e2e.New(suite.T(), false)
   135  	defer ts.Close()
   136  
   137  	suite.createProjectFile(ts)
   138  
   139  	scriptBlock := `
   140  echo "Enter your name: "
   141  read name
   142  echo "Hello $name!"
   143  `
   144  
   145  	filename := fmt.Sprintf("%s/%s.sh", ts.Dirs.Work, suite.T().Name())
   146  	if runtime.GOOS == "windows" {
   147  		scriptBlock = `set /P name="Enter your name: "
   148  		echo Hello %name%!`
   149  		filename = fmt.Sprintf("%s/%s.bat", ts.Dirs.Work, suite.T().Name())
   150  	}
   151  
   152  	testScript := filepath.Join(filename)
   153  	err := fileutils.WriteFile(testScript, []byte(scriptBlock))
   154  	suite.Require().NoError(err)
   155  
   156  	err = os.Chmod(testScript, 0777)
   157  	suite.Require().NoError(err)
   158  
   159  	cp := ts.SpawnWithOpts(
   160  		e2e.OptArgs("exec", "--", testScript),
   161  	)
   162  	cp.SendLine("ActiveState")
   163  	cp.Expect("Hello ActiveState!")
   164  	cp.ExpectExitCode(0)
   165  }
   166  
   167  func (suite *ExecIntegrationTestSuite) TestExecWithPath() {
   168  	if runtime.GOOS == "windows" {
   169  		suite.T().Skip("Windows does not have `which` command")
   170  	}
   171  	suite.OnlyRunForTags(tagsuite.Exec)
   172  
   173  	ts := e2e.New(suite.T(), false)
   174  	defer ts.Close()
   175  
   176  	pythonDir := filepath.Join(ts.Dirs.Work, "MyPython3")
   177  
   178  	cp := ts.SpawnWithOpts(e2e.OptArgs("checkout", "ActiveState-CLI/Python-3.9", pythonDir))
   179  	cp.Expect("Skipping runtime setup")
   180  	cp.Expect("Checked out project")
   181  	cp.ExpectExitCode(0)
   182  
   183  	cp = ts.SpawnWithOpts(
   184  		e2e.OptArgs("exec", "--path", pythonDir, "which", "python3"),
   185  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   186  	)
   187  	cp.Expect("Operating on project ActiveState-CLI/Python-3.9", e2e.RuntimeSourcingTimeoutOpt)
   188  	cp.ExpectRe(regexp.MustCompile("cache/[0-9A-Fa-f]+/usr/bin/python3").String())
   189  	cp.ExpectExitCode(0)
   190  
   191  	cp = ts.SpawnWithOpts(
   192  		e2e.OptArgs("exec", "echo", "python3", "--path", pythonDir, "--", "--path", "doesNotExist", "--", "extra"),
   193  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   194  	)
   195  	cp.Expect("python3 --path doesNotExist -- extra")
   196  	cp.ExpectExitCode(0)
   197  
   198  }
   199  
   200  func (suite *ExecIntegrationTestSuite) TestExecPerlArgs() {
   201  	suite.OnlyRunForTags(tagsuite.Exec)
   202  	ts := e2e.New(suite.T(), false)
   203  	defer ts.Close()
   204  
   205  	cp := ts.Spawn("checkout", "ActiveState-CLI/Perl-5.32", ".")
   206  	cp.Expect("Skipping runtime setup")
   207  	cp.Expect("Checked out")
   208  	cp.ExpectExitCode(0)
   209  
   210  	suite.NoError(fileutils.WriteFile(filepath.Join(ts.Dirs.Work, "testargs.pl"), []byte(`
   211  printf "Argument: '%s'.\n", $ARGV[0];
   212  `)))
   213  
   214  	cp = ts.SpawnWithOpts(
   215  		e2e.OptArgs("exec", "perl", "testargs.pl", "<3"),
   216  		e2e.OptAppendEnv(constants.DisableRuntime+"=false"),
   217  	)
   218  	cp.Expect("Argument: '<3'", e2e.RuntimeSourcingTimeoutOpt)
   219  	cp.ExpectExitCode(0)
   220  }
   221  
   222  func TestExecIntegrationTestSuite(t *testing.T) {
   223  	suite.Run(t, new(ExecIntegrationTestSuite))
   224  }