Skip to content

Commit

Permalink
Set exit code
Browse files Browse the repository at this point in the history
Now setting the exit code. 0 for success and 1 for failure.

Wrote tests for the entry point (Program).
  • Loading branch information
gabrielweyer committed Apr 19, 2022
1 parent 1d002a7 commit 1f46204
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 16 deletions.
8 changes: 8 additions & 0 deletions src/dotnet-decode-base64/IConsole.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace DotNet.DecodeBase64;

internal interface IConsole
{
void WriteFancyLine(string line);
void WriteBoringLine(string line);
void WriteErrorLine(string line);
}
26 changes: 26 additions & 0 deletions src/dotnet-decode-base64/NonThreadSafeConsole.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace DotNet.DecodeBase64;

internal class NonThreadSafeConsole : IConsole
{
public void WriteFancyLine(string line)
{
WriteColoredLine(ConsoleColor.Green, line);
}

public void WriteBoringLine(string line)
{
Console.WriteLine(line);
}

public void WriteErrorLine(string line)
{
WriteColoredLine(ConsoleColor.Red, line);
}

private static void WriteColoredLine(ConsoleColor color, string line)
{
Console.ForegroundColor = color;
Console.WriteLine(line);
Console.ResetColor();
}
}
32 changes: 17 additions & 15 deletions src/dotnet-decode-base64/Program.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
namespace DotNet.DecodeBase64;

internal class Program
internal static class Program
{
private static void Main(string[] args)
internal const int SuccessExitCode = 0;
internal const int FailureExitCode = 1;

internal static IConsole AbstractedConsole;

internal static int Main(string[] args)
{
AbstractedConsole ??= new NonThreadSafeConsole();

if (args.Length != 1)
{
Console.WriteLine("A single argument should be provided:");
Console.WriteLine("dotnet decode-base64 SGVsbG8gV29ybGQh");
return;
AbstractedConsole.WriteBoringLine("A single argument should be provided:");
AbstractedConsole.WriteBoringLine("dotnet decode-base64 SGVsbG8gV29ybGQh");
return FailureExitCode;
}

try
{
var decodedString = Base64Decoder.Decode(args[0]);

Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Decoded string:");
Console.ResetColor();
Console.WriteLine(decodedString);
AbstractedConsole.WriteFancyLine("Decoded string:");
AbstractedConsole.WriteBoringLine(decodedString);
return SuccessExitCode;
}
catch (FormatException e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e.Message);
}
finally
{
Console.ResetColor();
AbstractedConsole.WriteErrorLine(e.Message);
return FailureExitCode;
}
}
}
5 changes: 4 additions & 1 deletion src/dotnet-decode-base64/dotnet-decode-base64.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<NoWarn>CS7035</NoWarn>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="DotNet.DecodeBase64.Tests" />
</ItemGroup>
<ItemGroup>
<Using Include="System.Text" />
</ItemGroup>
Expand All @@ -31,6 +34,6 @@
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\"/>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>
143 changes: 143 additions & 0 deletions tests/dotnet-decode-base64-tests/ProgramTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
using DotNet.DecodeBase64.Tests.TestInfrastructure;
using FluentAssertions;

namespace DotNet.DecodeBase64.Tests;

public class ProgramTests
{
private readonly MockConsole _console;
private const string ValidBase64Input = "SGVsbG8gV29ybGQh";
private const string DecodedValidBase64Input = "Hello World!";
private const string InvalidBase64Input = "#";

public ProgramTests()
{
_console = new MockConsole();
Program.AbstractedConsole = _console;
}

[Fact]
public void GivenNoArgumentProvided_ThenDisplayInstructions()
{
// Arrange
var input = Array.Empty<string>();

// Act
Program.Main(input);

// Assert
var expectedLines = new List<ColoredLine>
{
new("A single argument should be provided:", MockConsole.BoringColor),
new("dotnet decode-base64 SGVsbG8gV29ybGQh", MockConsole.BoringColor)
};
_console.Lines.Should().BeEquivalentTo(expectedLines);
}

[Fact]
public void GivenNoArgumentProvided_ThenFailureExitCode()
{
// Arrange
var input = Array.Empty<string>();

// Act
var actualExitCode = Program.Main(input);

// Assert
actualExitCode.Should().Be(Program.FailureExitCode);
}

[Fact]
public void GivenMoreThanOneArgumentProvided_ThenDisplayInstructions()
{
// Arrange
var input = new[] { ValidBase64Input, ValidBase64Input };

// Act
Program.Main(input);

// Assert
var expectedLines = new List<ColoredLine>
{
new("A single argument should be provided:", MockConsole.BoringColor),
new("dotnet decode-base64 SGVsbG8gV29ybGQh", MockConsole.BoringColor)
};
_console.Lines.Should().BeEquivalentTo(expectedLines);
}

[Fact]
public void GivenMoreThanOneArgumentProvided_ThenFailureExitCode()
{
// Arrange
var input = new[] { ValidBase64Input, ValidBase64Input };

// Act
var actualExitCode = Program.Main(input);

// Assert
actualExitCode.Should().Be(Program.FailureExitCode);
}

[Fact]
public void GivenInvalidBase64Input_ThenDisplayErrorMessage()
{
// Arrange
var input = new[] { InvalidBase64Input };

// Act
Program.Main(input);

// Assert
const string errorMessage =
"The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.";
var expectedLines = new List<ColoredLine>
{
new(errorMessage, MockConsole.ErrorColor)
};
_console.Lines.Should().BeEquivalentTo(expectedLines);
}

[Fact]
public void GivenInvalidBase64Input_ThenFailureExitCode()
{
// Arrange
var input = new[] { InvalidBase64Input };

// Act
var actualExitCode = Program.Main(input);

// Assert
actualExitCode.Should().Be(Program.FailureExitCode);
}

[Fact]
public void GivenValidBase64Input_ThenDisplayDecodedInput()
{
// Arrange
var input = new[] { ValidBase64Input };

// Act
Program.Main(input);

// Assert
var expectedLines = new List<ColoredLine>
{
new("Decoded string:", MockConsole.FancyColor),
new(DecodedValidBase64Input, MockConsole.BoringColor)
};
_console.Lines.Should().BeEquivalentTo(expectedLines);
}

[Fact]
public void GivenValidBase64Input_ThenSuccessExitCode()
{
// Arrange
var input = new[] { ValidBase64Input };

// Act
var actualExitCode = Program.Main(input);

// Assert
actualExitCode.Should().Be(Program.SuccessExitCode);
}
}
43 changes: 43 additions & 0 deletions tests/dotnet-decode-base64-tests/TestInfrastructure/MockConsole.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace DotNet.DecodeBase64.Tests.TestInfrastructure;

internal class MockConsole : IConsole
{
public const ConsoleColor FancyColor = ConsoleColor.Cyan;
public const ConsoleColor BoringColor = ConsoleColor.Yellow;
public const ConsoleColor ErrorColor = ConsoleColor.Magenta;
public IReadOnlyList<ColoredLine> Lines => _lines;

private readonly List<ColoredLine> _lines;

public MockConsole()
{
_lines = new List<ColoredLine>();
}

public void WriteFancyLine(string line)
{
_lines.Add(new ColoredLine(line, FancyColor));
}

public void WriteBoringLine(string line)
{
_lines.Add(new ColoredLine(line, BoringColor));
}

public void WriteErrorLine(string line)
{
_lines.Add(new ColoredLine(line, ErrorColor));
}
}

internal class ColoredLine
{
public ColoredLine(string line, ConsoleColor color)
{
Line = line;
Color = color;
}

public ConsoleColor Color { get; }
public string Line { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>DotNet.DecodeBase64.Tests</RootNamespace>
<AssemblyName>DotNet.DecodeBase64.Tests</AssemblyName>
<IsPackable>false</IsPackable>
<NoWarn>CS7035</NoWarn>
</PropertyGroup>
Expand All @@ -18,6 +19,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="6.6.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
Expand Down

0 comments on commit 1f46204

Please sign in to comment.