Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds godot symlink to OS' PATH, auto-detect default SHELL on UNIX systems #54

Merged
merged 14 commits into from
Jan 13, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ GodotEnv/addons
GodotEnv/.addons
GodotEnv/addons.json
GodotEnv/addons.jsonc
GodotEnv.sln.DotSettings.user

.idea/
edassis marked this conversation as resolved.
Show resolved Hide resolved
9 changes: 5 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"[csharp]": {
"editor.codeActionsOnSave": {
"source.addMissingImports": true,
"source.fixAll": false,
"source.organizeImports": true
"source.addMissingImports": "explicit",
"source.fixAll": "never",
"source.organizeImports": "explicit"
},
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
Expand Down Expand Up @@ -162,5 +162,6 @@
"source": "PowerShell"
}
},
"dotnet.completion.showCompletionItemsFromUnimportedNamespaces": true
"dotnet.completion.showCompletionItemsFromUnimportedNamespaces": true,
"dotnet.defaultSolution": "GodotEnv.sln"
}
22 changes: 11 additions & 11 deletions GodotEnv.Tests/reports/branch_coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 11 additions & 11 deletions GodotEnv.Tests/reports/line_coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions GodotEnv.Tests/reports/method_coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
194 changes: 194 additions & 0 deletions GodotEnv.Tests/src/common/clients/EnvironmentVariableClientTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
namespace Chickensoft.GodotEnv.Tests;

using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Chickensoft.GodotEnv.Common.Utilities;
using Common.Clients;
using Common.Models;
using Moq;
using Shouldly;
using Xunit;

public class EnvironmentVariableClientTest {
[Fact]
public async Task SetUserEnv() {
const string WORKING_DIR = ".";
var env = "GODOT";
var envValue = "godotenv/godot/bin/godot";

// Given
var processRunner = new Mock<IProcessRunner>();

// GetDefaultShell()
processRunner.Setup(
pr => pr.Run(WORKING_DIR, "sh", It.Is<string[]>(
value => value.SequenceEqual(new[] { "-c", EnvironmentVariableClient.USER_SHELL_COMMAND_MAC })
))
).Returns(Task.FromResult(new ProcessResult(0, "bash")));
processRunner.Setup(
pr => pr.Run(WORKING_DIR, "sh", It.Is<string[]>(
value => value.SequenceEqual(new[] { "-c", EnvironmentVariableClient.USER_SHELL_COMMAND_LINUX })
))
).Returns(Task.FromResult(new ProcessResult(0, "bash")));

// GetUserEnv()
processRunner.Setup(
pr => pr.Run(WORKING_DIR, "bash", It.Is<string[]>(
value => value.SequenceEqual(new[] { "-ic", $"echo ${env}" })
))).Returns(Task.FromResult(new ProcessResult(0, envValue)));

var fileClient = new Mock<IFileClient>();
fileClient.Setup(fc => fc.OS).Returns(FileClient.IsOSPlatform(OSPlatform.OSX)
? OSType.MacOS
: FileClient.IsOSPlatform(OSPlatform.Linux)
? OSType.Linux
: FileClient.IsOSPlatform(OSPlatform.Windows)
? OSType.Windows
: OSType.Unknown);
fileClient.Setup(fc => fc.AppDataDirectory).Returns(WORKING_DIR);

var computer = new Mock<IComputer>();
computer.Setup(c => c.CreateShell(WORKING_DIR)).Returns(new Shell(processRunner.Object, WORKING_DIR));

var envClient = new EnvironmentVariableClient(processRunner.Object, fileClient.Object, computer.Object, new Mock<EnvironmentClient>().Object);

// When
envClient.SetUserEnv(env, envValue);

// Then
var userEnv = await envClient.GetUserEnv(env);
userEnv.ShouldBe(envValue);
}

[Fact]
public async Task AppendToUserEnv() {
var WORKING_DIR = ".";
var env = Defaults.PATH_ENV_VAR_NAME;
var envValue = "godotenv/godot/bin/godot";

var fileClient = new Mock<IFileClient>();
fileClient.Setup(fc => fc.OS).Returns(FileClient.IsOSPlatform(OSPlatform.OSX)
? OSType.MacOS
: FileClient.IsOSPlatform(OSPlatform.Linux)
? OSType.Linux
: FileClient.IsOSPlatform(OSPlatform.Windows)
? OSType.Windows
: OSType.Unknown);
fileClient.Setup(fc => fc.AppDataDirectory).Returns(WORKING_DIR);

var processRunner = new Mock<IProcessRunner>();

// GetDefaultShell()
processRunner.Setup(
pr => pr.Run(WORKING_DIR, "sh", It.Is<string[]>(
value => value.SequenceEqual(new[] { "-c", EnvironmentVariableClient.USER_SHELL_COMMAND_MAC })
))
).Returns(Task.FromResult(new ProcessResult(0, "bash")));
processRunner.Setup(
pr => pr.Run(WORKING_DIR, "sh", It.Is<string[]>(
value => value.SequenceEqual(new[] { "-c", EnvironmentVariableClient.USER_SHELL_COMMAND_LINUX })
))
).Returns(Task.FromResult(new ProcessResult(0, "bash")));

// GetUserEnv()
processRunner.Setup(
pr => pr.Run(WORKING_DIR, "bash", It.Is<string[]>(
value => value.SequenceEqual(new[] { "-ic", $"echo ${env}" })
))).Returns(Task.FromResult(new ProcessResult(0, envValue)));

var computer = new Mock<IComputer>();
computer.Setup(c => c.CreateShell(WORKING_DIR)).Returns(new Shell(processRunner.Object, WORKING_DIR));

var envClient = new Mock<IEnvironmentClient>();
envClient.Setup(ec => ec.GetEnvironmentVariable(env, EnvironmentVariableTarget.User)).Returns(envValue);

var envVarClient = new EnvironmentVariableClient(processRunner.Object, fileClient.Object, computer.Object, envClient.Object);

await envVarClient.AppendToUserEnv(env, envValue);

var userEnv = await envVarClient.GetUserEnv(env);
userEnv.ShouldContain(envValue);
}

[PlatformFact(TestPlatform.Windows)]
public async Task GetDefaultShellOnWindows() {
var processRunner = new Mock<IProcessRunner>();
var fileClient = new Mock<IFileClient>();
fileClient.Setup(fc => fc.OS).Returns(OSType.Windows);
fileClient.Setup(fc => fc.AppDataDirectory).Returns(".");
var computer = new Mock<IComputer>();
var envClient = new EnvironmentVariableClient(processRunner.Object, fileClient.Object, computer.Object, new Mock<EnvironmentClient>().Object);

var userDefaultShell = await envClient.GetUserDefaultShell();
userDefaultShell.ShouldBe(string.Empty);
}

[PlatformFact(TestPlatform.Mac)]
public async Task GetDefaultShellOnMac() => await GetDefaultShellUnixRoutine(OSType.MacOS,
["-c", EnvironmentVariableClient.USER_SHELL_COMMAND_MAC]);

[PlatformFact(TestPlatform.Linux)]
public async Task GetDefaultShellOnLinux() =>
await GetDefaultShellUnixRoutine(OSType.Linux, ["-c", EnvironmentVariableClient.USER_SHELL_COMMAND_LINUX]);

private static async Task GetDefaultShellUnixRoutine(OSType os, string[] shellArgs) {
var processRunner = new Mock<IProcessRunner>();
const string WORKING_DIR = ".";
const int exitCode = 0;
const string stdOutput = "bash";
const string exe = "sh";

var processResult = new ProcessResult(exitCode, stdOutput);
processRunner.Setup(
pr => pr.Run(WORKING_DIR, exe, It.Is<string[]>(
value => value.SequenceEqual(shellArgs)
))
).Returns(Task.FromResult(processResult));

var fileClient = new Mock<IFileClient>();
fileClient.Setup(fc => fc.OS).Returns(os);
fileClient.Setup(fc => fc.AppDataDirectory).Returns(WORKING_DIR);

var computer = new Mock<IComputer>();
computer.Setup(c => c.CreateShell(WORKING_DIR)).Returns(new Shell(processRunner.Object, WORKING_DIR));

var envVarClient = new EnvironmentVariableClient(processRunner.Object, fileClient.Object, computer.Object, new Mock<EnvironmentClient>().Object);

var result = await envVarClient.GetUserDefaultShell();
result.ShouldBe(stdOutput);
processRunner.VerifyAll();
}

[PlatformFact(TestPlatform.Windows)]
public void CheckSupportedShellOnWindows() {
var processRunner = new Mock<IProcessRunner>();
var fileClient = new Mock<IFileClient>();
fileClient.Setup(fc => fc.OS).Returns(OSType.Windows);
var computer = new Mock<IComputer>();
var envClient = new EnvironmentVariableClient(processRunner.Object, fileClient.Object, computer.Object, new Mock<EnvironmentClient>().Object);

envClient.IsShellSupported("any").ShouldBeTrue();
envClient.IsShellSupported(string.Empty).ShouldBeTrue();
}

[PlatformFact(TestPlatform.MacLinux)]
public void CheckSupportedShellOnMacLinux() {
var processRunner = new Mock<IProcessRunner>();
var fileClient = new Mock<IFileClient>();
fileClient.Setup(fc => fc.OS).Returns(FileClient.IsOSPlatform(OSPlatform.OSX)
? OSType.MacOS
: FileClient.IsOSPlatform(OSPlatform.Linux)
? OSType.Linux
: FileClient.IsOSPlatform(OSPlatform.Windows)
? OSType.Windows
: OSType.Unknown);
var computer = new Mock<IComputer>();
var envClient = new EnvironmentVariableClient(processRunner.Object, fileClient.Object, computer.Object, new Mock<EnvironmentClient>().Object);

envClient.IsShellSupported("zsh").ShouldBeTrue();
envClient.IsShellSupported("bash").ShouldBeTrue();
envClient.IsShellSupported("fish").ShouldBeFalse();
}
}
Loading