github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/test/integration/use_int_test.go (about) 1 package integration 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "runtime" 8 "testing" 9 10 "github.com/ActiveState/cli/internal/config" 11 "github.com/ActiveState/cli/internal/constants" 12 "github.com/ActiveState/cli/internal/fileutils" 13 "github.com/ActiveState/cli/internal/osutils" 14 "github.com/ActiveState/cli/internal/subshell" 15 "github.com/ActiveState/cli/internal/testhelpers/e2e" 16 "github.com/ActiveState/cli/internal/testhelpers/suite" 17 "github.com/ActiveState/cli/internal/testhelpers/tagsuite" 18 ) 19 20 type UseIntegrationTestSuite struct { 21 tagsuite.Suite 22 } 23 24 func (suite *UseIntegrationTestSuite) TestUse() { 25 suite.OnlyRunForTags(tagsuite.Use) 26 27 ts := e2e.New(suite.T(), false) 28 defer ts.Close() 29 30 // Checkout. 31 cp := ts.SpawnWithOpts(e2e.OptArgs("checkout", "ActiveState-CLI/Python3")) 32 cp.Expect("Skipping runtime setup") 33 cp.Expect("Checked out project") 34 cp.ExpectExitCode(0) 35 36 // Use. 37 cp = ts.SpawnWithOpts( 38 e2e.OptArgs("use", "ActiveState-CLI/Python3"), 39 e2e.OptAppendEnv(constants.DisableRuntime+"=false"), 40 ) 41 cp.Expect("Switched to project", e2e.RuntimeSourcingTimeoutOpt) 42 cp.ExpectExitCode(0) 43 44 // Verify runtime works. 45 pythonExe := filepath.Join(ts.Dirs.DefaultBin, "python3"+osutils.ExeExtension) 46 cp = ts.SpawnCmd(pythonExe, "--version") 47 cp.Expect("Python 3") 48 cp.ExpectExitCode(0) 49 50 // Checkout another project. 51 cp = ts.SpawnWithOpts(e2e.OptArgs("checkout", "ActiveState-CLI/Python-3.9")) 52 cp.Expect("Skipping runtime setup") 53 cp.Expect("Checked out project") 54 cp.ExpectExitCode(0) 55 56 // Use it. 57 cp = ts.SpawnWithOpts( 58 e2e.OptArgs("use", "ActiveState-CLI/Python-3.9"), 59 e2e.OptAppendEnv(constants.DisableRuntime+"=false"), 60 ) 61 cp.Expect("Switched to project", e2e.RuntimeSourcingTimeoutOpt) 62 cp.ExpectExitCode(0) 63 64 // Verify the new runtime works. 65 cp = ts.SpawnCmdWithOpts(pythonExe, e2e.OptArgs("--version")) 66 cp.Expect("Python 3") 67 cp.ExpectExitCode(0) 68 69 // Switch back using just the project name. 70 cp = ts.SpawnWithOpts( 71 e2e.OptArgs("use", "Python3"), 72 e2e.OptAppendEnv(constants.DisableRuntime+"=false"), 73 ) 74 cp.Expect("Switched to project", e2e.RuntimeSourcingTimeoutOpt) 75 cp.ExpectExitCode(0) 76 77 // Verify the first runtime is set up correctly and usable. 78 cp = ts.SpawnCmdWithOpts(pythonExe, e2e.OptArgs("--version")) 79 cp.Expect("Python 3") 80 cp.ExpectExitCode(0) 81 82 // Test failure switching to project name that was not checked out. 83 cp = ts.SpawnWithOpts(e2e.OptArgs("use", "NotCheckedOut")) 84 cp.Expect("Cannot find the NotCheckedOut project.") 85 cp.ExpectExitCode(1) 86 ts.IgnoreLogErrors() 87 } 88 89 func (suite *UseIntegrationTestSuite) TestUseCwd() { 90 suite.OnlyRunForTags(tagsuite.Use) 91 92 ts := e2e.New(suite.T(), false) 93 defer ts.Close() 94 95 pythonDir := filepath.Join(ts.Dirs.Work, "MyPython3") 96 97 cp := ts.SpawnWithOpts(e2e.OptArgs("checkout", "ActiveState-CLI/Python3", pythonDir)) 98 cp.Expect("Skipping runtime setup") 99 cp.Expect("Checked out project") 100 cp.ExpectExitCode(0) 101 102 cp = ts.SpawnWithOpts( 103 e2e.OptArgs("use"), 104 e2e.OptWD(pythonDir), 105 e2e.OptAppendEnv(constants.DisableRuntime+"=false"), 106 ) 107 cp.Expect("Switched to project", e2e.RuntimeSourcingTimeoutOpt) 108 cp.ExpectExitCode(0) 109 110 emptyDir := filepath.Join(ts.Dirs.Work, "EmptyDir") 111 suite.Require().NoError(fileutils.Mkdir(emptyDir)) 112 cp = ts.SpawnWithOpts( 113 e2e.OptArgs("use"), 114 e2e.OptWD(emptyDir), 115 ) 116 cp.Expect("Unable to use project") 117 cp.ExpectExitCode(1) 118 ts.IgnoreLogErrors() 119 } 120 121 func (suite *UseIntegrationTestSuite) TestReset() { 122 suite.OnlyRunForTags(tagsuite.Use) 123 124 ts := e2e.New(suite.T(), false) 125 defer ts.Close() 126 127 ts.SetupRCFile() 128 suite.T().Setenv("ACTIVESTATE_HOME", ts.Dirs.HomeDir) 129 130 cp := ts.SpawnWithOpts(e2e.OptArgs("checkout", "ActiveState-CLI/Python3")) 131 cp.Expect("Skipping runtime setup") 132 cp.Expect("Checked out project") 133 cp.ExpectExitCode(0) 134 135 cp = ts.SpawnWithOpts( 136 e2e.OptArgs("use", "ActiveState-CLI/Python3"), 137 e2e.OptAppendEnv(constants.DisableRuntime+"=false"), 138 ) 139 cp.Expect("Switched to project", e2e.RuntimeSourcingTimeoutOpt) 140 cp.ExpectExitCode(0) 141 142 python3Exe := filepath.Join(ts.Dirs.DefaultBin, "python3"+osutils.ExeExtension) 143 suite.True(fileutils.TargetExists(python3Exe), python3Exe+" not found") 144 145 cfg, err := config.New() 146 suite.NoError(err) 147 rcfile, err := subshell.New(cfg).RcFile() 148 if runtime.GOOS != "windows" && fileutils.FileExists(rcfile) { 149 suite.NoError(err) 150 suite.Contains(string(fileutils.ReadFileUnsafe(rcfile)), ts.Dirs.DefaultBin, "PATH does not have your project in it") 151 } 152 153 cp = ts.SpawnWithOpts(e2e.OptArgs("use", "reset")) 154 cp.Expect("Continue?") 155 cp.SendLine("n") 156 cp.Expect("Reset aborted by user") 157 cp.ExpectExitCode(1) 158 ts.IgnoreLogErrors() 159 160 cp = ts.SpawnWithOpts(e2e.OptArgs("use", "reset", "--non-interactive")) 161 cp.Expect("Stopped using your project runtime") 162 cp.Expect("Note you may need to") 163 cp.ExpectExitCode(0) 164 165 suite.False(fileutils.TargetExists(python3Exe), python3Exe+" still exists") 166 167 cp = ts.SpawnWithOpts(e2e.OptArgs("use", "reset")) 168 cp.Expect("No project to stop using") 169 cp.ExpectExitCode(1) 170 171 if runtime.GOOS != "windows" && fileutils.FileExists(rcfile) { 172 suite.NotContains(string(fileutils.ReadFileUnsafe(rcfile)), ts.Dirs.DefaultBin, "PATH still has your project in it") 173 } 174 } 175 176 func (suite *UseIntegrationTestSuite) TestShow() { 177 suite.OnlyRunForTags(tagsuite.Use) 178 179 ts := e2e.New(suite.T(), false) 180 defer ts.Close() 181 182 cp := ts.SpawnWithOpts(e2e.OptArgs("use", "show")) 183 cp.Expect("No project is being used") 184 cp.ExpectExitCode(1) 185 ts.IgnoreLogErrors() 186 187 cp = ts.SpawnWithOpts(e2e.OptArgs("checkout", "ActiveState-CLI/Python3")) 188 cp.Expect("Skipping runtime setup") 189 cp.Expect("Checked out project") 190 cp.ExpectExitCode(0) 191 192 cp = ts.SpawnWithOpts( 193 e2e.OptArgs("use", "ActiveState-CLI/Python3"), 194 e2e.OptAppendEnv(constants.DisableRuntime+"=false"), 195 ) 196 cp.Expect("Switched to project", e2e.RuntimeSourcingTimeoutOpt) 197 cp.ExpectExitCode(0) 198 199 cp = ts.SpawnWithOpts( 200 e2e.OptArgs("use", "show"), 201 ) 202 cp.Expect("The active project is ActiveState-CLI/Python3") 203 projectDir := filepath.Join(ts.Dirs.Work, "Python3") 204 if runtime.GOOS != "windows" { 205 cp.Expect(projectDir) 206 } else { 207 // Windows uses the long path here. 208 longPath, err := fileutils.GetLongPathName(projectDir) 209 suite.Require().NoError(err) 210 cp.Expect(longPath) 211 } 212 cp.Expect(ts.Dirs.Cache) 213 cp.Expect("exec") 214 cp.ExpectExitCode(0) 215 216 err := os.RemoveAll(projectDir) 217 suite.Require().NoError(err) 218 219 cp = ts.SpawnWithOpts(e2e.OptArgs("use", "show")) 220 cp.Expect("Cannot find your project") 221 // Both Windows and MacOS can run into path comparison issues with symlinks and long paths. 222 if runtime.GOOS == "linux" { 223 cp.Expect(fmt.Sprintf("Could not find project at %s", projectDir)) 224 } 225 cp.ExpectExitCode(1) 226 227 cp = ts.SpawnWithOpts(e2e.OptArgs("use", "reset", "--non-interactive")) 228 cp.Expect("Stopped using your project runtime") 229 cp.ExpectExitCode(0) 230 231 cp = ts.SpawnWithOpts(e2e.OptArgs("use", "show")) 232 cp.Expect("No project is being used") 233 cp.ExpectExitCode(1) 234 } 235 236 func (suite *UseIntegrationTestSuite) TestSetupNotice() { 237 suite.OnlyRunForTags(tagsuite.Use) 238 239 ts := e2e.New(suite.T(), false) 240 defer ts.Close() 241 242 cp := ts.SpawnWithOpts( 243 e2e.OptArgs("checkout", "ActiveState-CLI/Python3"), 244 e2e.OptAppendEnv(constants.DisableRuntime+"=false"), 245 ) 246 cp.Expect("Setting Up Runtime") 247 cp.Expect("Checked out project", e2e.RuntimeSourcingTimeoutOpt) 248 cp.ExpectExitCode(0) 249 250 suite.Require().NoError(os.RemoveAll(filepath.Join(ts.Dirs.Work, "Python3"))) // runtime marker still exists 251 252 cp = ts.SpawnWithOpts( 253 e2e.OptArgs("checkout", "ActiveState-CLI/Python3#623dadf8-ebf9-4876-bfde-f45afafe5ea8"), 254 ) 255 cp.Expect("Skipping runtime setup") 256 cp.Expect("Checked out project") 257 cp.ExpectExitCode(0) 258 259 cp = ts.SpawnWithOpts( 260 e2e.OptArgs("use", "Python3"), 261 e2e.OptAppendEnv(constants.DisableRuntime+"=false"), 262 ) 263 cp.Expect("Setting Up Runtime") 264 cp.Expect("Switched to project", e2e.RuntimeSourcingTimeoutOpt) 265 cp.ExpectExitCode(0) 266 } 267 268 func (suite *UseIntegrationTestSuite) TestJSON() { 269 suite.OnlyRunForTags(tagsuite.Use, tagsuite.JSON) 270 ts := e2e.New(suite.T(), false) 271 defer ts.Close() 272 273 cp := ts.Spawn("checkout", "ActiveState-CLI/Perl-5.32", ".") 274 cp.Expect("Skipping runtime setup") 275 cp.Expect("Checked out") 276 cp.ExpectExitCode(0) 277 278 cp = ts.SpawnWithOpts( 279 e2e.OptArgs("use", "-o", "json"), 280 e2e.OptAppendEnv(constants.DisableRuntime+"=false"), 281 ) 282 cp.Expect(`"namespace":`, e2e.RuntimeSourcingTimeoutOpt) 283 cp.Expect(`"path":`) 284 cp.Expect(`"executables":`) 285 cp.ExpectExitCode(0) 286 AssertValidJSON(suite.T(), cp) 287 288 cp = ts.Spawn("use", "show", "--output", "json") 289 cp.Expect(`"namespace":`) 290 cp.Expect(`"path":`) 291 cp.Expect(`"executables":`) 292 cp.ExpectExitCode(0) 293 AssertValidJSON(suite.T(), cp) 294 } 295 296 func TestUseIntegrationTestSuite(t *testing.T) { 297 suite.Run(t, new(UseIntegrationTestSuite)) 298 }