installer/windows: unit tests for C# custom actions (part 1) (#3521)

This commit is contained in:
Kaloyan Raev 2019-11-09 01:38:06 +02:00 committed by Fadila
parent 69b0ae02bf
commit 9dce3dc942
15 changed files with 648 additions and 102 deletions

View File

@ -1,6 +1,9 @@
/.vs/
/bin/
*/bin/
/obj/
*/obj/
/packages/
*.exe
*.msi
*.wixobj

View File

@ -8,48 +8,20 @@ namespace Storj
{
public class CustomActions
{
private const long GB = 1000 * 1000 * 1000;
private const long TB = (long) 1000 * 1000 * 1000 * 1000;
private const long MinFreeSpace = 550 * GB; // (500 GB + 10% overhead)
[CustomAction]
public static ActionResult ValidateIdentityDir(Session session)
{
string identityDir = session["IDENTITYDIR"];
if (string.IsNullOrEmpty(identityDir))
try
{
session["STORJ_IDENTITYDIR_VALID"] = "You must select an identity folder.";
return ActionResult.Success;
CustomActionRunner.ValidateIdentityDir(identityDir);
}
if (!Directory.Exists(identityDir))
catch (ArgumentException e)
{
session["STORJ_IDENTITYDIR_VALID"] = string.Format("Folder '{0}' does not exist.", identityDir);
return ActionResult.Success;
}
if (!File.Exists(Path.Combine(identityDir, "ca.cert")))
{
session["STORJ_IDENTITYDIR_VALID"] = "File 'ca.cert' not found in the selected folder.";
return ActionResult.Success;
}
if (!File.Exists(Path.Combine(identityDir, "ca.key")))
{
session["STORJ_IDENTITYDIR_VALID"] = "File 'ca.key' not found in the selected folder.";
return ActionResult.Success;
}
if (!File.Exists(Path.Combine(identityDir, "identity.cert")))
{
session["STORJ_IDENTITYDIR_VALID"] = "File 'identity.cert' not found in the selected folder.";
return ActionResult.Success;
}
if (!File.Exists(Path.Combine(identityDir, "identity.key")))
{
session["STORJ_IDENTITYDIR_VALID"] = "File 'identity.key' not found in the selected folder.";
// Identity dir is invalid
session["STORJ_IDENTITYDIR_VALID"] = e.Message;
return ActionResult.Success;
}
@ -63,52 +35,34 @@ namespace Storj
{
string wallet = session["STORJ_WALLET"];
if (string.IsNullOrEmpty(wallet))
try
{
session["STORJ_WALLET_VALID"] = "The payout address cannot be empty.";
CustomActionRunner.ValidateWallet(wallet);
} catch (ArgumentException e)
{
// Wallet is invalid
session["STORJ_WALLET_VALID"] = e.Message;
return ActionResult.Success;
}
if (!wallet.StartsWith("0x"))
{
session["STORJ_WALLET_VALID"] = "The payout address must start with a '0x' prefix.";
return ActionResult.Success;
}
// Remove 0x prefix
wallet = wallet.Substring(2);
if (wallet.Length != 40)
{
session["STORJ_WALLET_VALID"] = "The payout address must have 40 characters after the '0x' prefix.";
return ActionResult.Success;
}
// TODO validate address checksum
// Wallet is valid
session["STORJ_WALLET_VALID"] = "1";
return ActionResult.Success;
}
[CustomAction]
public static ActionResult ValidateStorageDir(Session session)
{
string identityDir = session["STORAGEDIR"];
string storageDir = session["STORAGEDIR"];
if (string.IsNullOrEmpty(identityDir))
try
{
session["STORJ_STORAGEDIR_VALID"] = "You must select a storage folder.";
return ActionResult.Success;
CustomActionRunner.ValidateStorageDir(storageDir);
}
DirectoryInfo dir = new DirectoryInfo(identityDir);
DriveInfo drive = new DriveInfo(dir.Root.FullName);
// TODO: Find a way to calculate the available free space + total size of existing pieces
if (drive.TotalSize < MinFreeSpace)
catch (ArgumentException e)
{
session["STORJ_STORAGEDIR_VALID"] = string.Format("The selected drive '{0}' has only {1:0.##} GB disk size. The minimum required is 550 GB.",
drive.Name, decimal.Divide(drive.TotalSize, GB));
// Storage dir is invalid
session["STORJ_STORAGEDIR_VALID"] = e.Message;
return ActionResult.Success;
}
@ -121,33 +75,16 @@ namespace Storj
public static ActionResult ValidateStorage(Session session)
{
string storageStr = session["STORJ_STORAGE"];
string storageDir = session["STORAGEDIR"];
if (string.IsNullOrEmpty(storageStr))
try
{
session["STORJ_STORAGE_VALID"] = "The value cannot be empty.";
return ActionResult.Success;
CustomActionRunner.ValidateStorage(storageStr, storageDir);
}
if (!double.TryParse(storageStr, NumberStyles.Number, CultureInfo.CreateSpecificCulture("en-US"), out double storage))
catch (ArgumentException e)
{
session["STORJ_STORAGE_VALID"] = string.Format("'{0}' is not a valid number.", storageStr);
return ActionResult.Success;
}
if (storage < 0.5) {
session["STORJ_STORAGE_VALID"] = "The allocated disk space cannot be less than 0.5 TB.";
return ActionResult.Success;
}
DirectoryInfo dir = new DirectoryInfo(session["STORAGEDIR"]);
DriveInfo drive = new DriveInfo(dir.Root.FullName);
long storagePlusOverhead = Convert.ToInt64(storage * 1.1 * TB);
// TODO: Find a way to calculate the available free space + total size of existing pieces
if (drive.TotalSize < storagePlusOverhead)
{
session["STORJ_STORAGE_VALID"] = string.Format("The disk size ({0:0.##} TB) on the selected drive {1} is less than the allocated disk space plus the 10% overhead ({2:0.##} TB total).",
decimal.Divide(drive.TotalSize, TB), drive.Name, decimal.Divide(storagePlusOverhead, TB));
// Allocated Storage is invalid
session["STORJ_STORAGE_VALID"] = e.Message;
return ActionResult.Success;
}
@ -161,21 +98,14 @@ namespace Storj
{
string bandwidthStr = session["STORJ_BANDWIDTH"];
if (string.IsNullOrEmpty(bandwidthStr))
try
{
session["STORJ_BANDWIDTH_VALID"] = "The value cannot be empty.";
return ActionResult.Success;
CustomActionRunner.ValidateBandwidth(bandwidthStr);
}
if (!double.TryParse(bandwidthStr, NumberStyles.Number, CultureInfo.CreateSpecificCulture("en-US"), out double bandwidth))
catch (ArgumentException e)
{
session["STORJ_BANDWIDTH_VALID"] = string.Format("'{0}' is not a valid number.", bandwidthStr);
return ActionResult.Success;
}
if (bandwidth < 2.0)
{
session["STORJ_BANDWIDTH_VALID"] = "The allocated bandwidth cannot be less than 2 TB.";
// Allocated Bandwidth is invalid
session["STORJ_BANDWIDTH_VALID"] = e.Message;
return ActionResult.Success;
}
@ -190,13 +120,174 @@ namespace Storj
string line = session["STORJ_SERVICE_COMMAND"];
session.Log($"ExtractInstallDir registry value: {line}");
Regex pattern = new Regex(@"--config-dir ""(?<installDir>.*)""");
Match match = pattern.Match(line);
string path = match.Groups["installDir"].Value;
string path = CustomActionRunner.ExtractInstallDir(line);
session.Log($"ExtractInstallDir extracted path: {path}");
session["STORJ_INSTALLDIR"] = path;
return ActionResult.Success;
}
}
public class CustomActionRunner
{
private const long GB = 1000 * 1000 * 1000;
private const long TB = (long)1000 * 1000 * 1000 * 1000;
private const long MinFreeSpace = 550 * GB; // (500 GB + 10% overhead)
public static void ValidateIdentityDir(string identityDir)
{
if (string.IsNullOrEmpty(identityDir))
{
throw new ArgumentException("You must select an identity folder.");
}
if (!Directory.Exists(identityDir))
{
throw new ArgumentException(string.Format("Folder '{0}' does not exist.", identityDir));
}
if (!File.Exists(Path.Combine(identityDir, "ca.cert")))
{
throw new ArgumentException("File 'ca.cert' not found in the selected folder.");
}
if (!File.Exists(Path.Combine(identityDir, "ca.key")))
{
throw new ArgumentException("File 'ca.key' not found in the selected folder.");
}
if (!File.Exists(Path.Combine(identityDir, "identity.cert")))
{
throw new ArgumentException("File 'identity.cert' not found in the selected folder.");
}
if (!File.Exists(Path.Combine(identityDir, "identity.key")))
{
throw new ArgumentException("File 'identity.key' not found in the selected folder.");
}
}
public static void ValidateWallet(string wallet)
{
if (string.IsNullOrEmpty(wallet))
{
throw new ArgumentException("The payout address cannot be empty.");
}
if (!wallet.StartsWith("0x"))
{
throw new ArgumentException("The payout address must start with a '0x' prefix.");
}
// Remove 0x prefix
wallet = wallet.Substring(2);
if (wallet.Length != 40)
{
throw new ArgumentException("The payout address must have 40 characters after the '0x' prefix.");
}
// TODO validate address checksum
}
public static void ValidateStorageDir(string storageDir)
{
if (string.IsNullOrEmpty(storageDir))
{
throw new ArgumentException("You must select a storage folder.");
}
DirectoryInfo dir = new DirectoryInfo(storageDir);
DriveInfo drive = new DriveInfo(dir.Root.FullName);
// TODO: Find a way to calculate the available free space + total size of existing pieces
if (drive.TotalSize < MinFreeSpace)
{
throw new ArgumentException(string.Format("The selected drive '{0}' has only {1:0.##} GB disk size. The minimum required is 550 GB.",
drive.Name, decimal.Divide(drive.TotalSize, GB)));
}
}
public static void ValidateStorage(string storageStr, string storageDir)
{
if (string.IsNullOrEmpty(storageStr))
{
throw new ArgumentException("The value cannot be empty.");
}
if (!double.TryParse(storageStr, NumberStyles.Number, CultureInfo.CreateSpecificCulture("en-US"), out double storage))
{
throw new ArgumentException(string.Format("'{0}' is not a valid number.", storageStr));
}
if (storage < 0.5)
{
throw new ArgumentException("The allocated disk space cannot be less than 0.5 TB.");
}
if (string.IsNullOrEmpty(storageDir))
{
throw new ArgumentException("The storage directory cannot be empty");
}
long storagePlusOverhead;
try
{
storagePlusOverhead = Convert.ToInt64(storage * 1.1 * TB);
}
catch (OverflowException)
{
throw new ArgumentException(string.Format("{0} TB is too large value for allocated storage.", storage));
}
DirectoryInfo dir = new DirectoryInfo(storageDir);
DriveInfo drive = new DriveInfo(dir.Root.FullName);
// TODO: Find a way to calculate the available free space + total size of existing pieces
if (drive.TotalSize < storagePlusOverhead)
{
throw new ArgumentException(string.Format("The disk size ({0:0.##} TB) on the selected drive {1} is less than the allocated disk space plus the 10% overhead ({2:0.##} TB total).",
decimal.Divide(drive.TotalSize, TB), drive.Name, decimal.Divide(storagePlusOverhead, TB)));
}
}
public static void ValidateBandwidth(string bandwidthStr)
{
if (string.IsNullOrEmpty(bandwidthStr))
{
throw new ArgumentException("The value cannot be empty.");
}
if (!double.TryParse(bandwidthStr, NumberStyles.Number, CultureInfo.CreateSpecificCulture("en-US"), out double bandwidth))
{
throw new ArgumentException(string.Format("'{0}' is not a valid number.", bandwidthStr));
}
if (bandwidth < 2.0)
{
throw new ArgumentException("The allocated bandwidth cannot be less than 2 TB.");
}
}
public static string ExtractInstallDir(string serviceCmd)
{
if (string.IsNullOrEmpty(serviceCmd))
{
return null;
}
Regex pattern = new Regex(@"--config-dir ""(?<installDir>.*)""");
Match match = pattern.Match(serviceCmd);
string installDir = match.Groups["installDir"].Value;
if (string.IsNullOrEmpty(installDir))
{
return null;
}
return installDir;
}
}
}

View File

@ -0,0 +1,47 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Helper class that allows checking both the type and the message of the thrown exception.
/// </summary>
public class ExpectedExceptionWithMessageAttribute : ExpectedExceptionBaseAttribute
{
public Type ExceptionType { get; set; }
public string ExpectedMessage { get; set; }
public ExpectedExceptionWithMessageAttribute(Type exceptionType)
{
this.ExceptionType = exceptionType;
}
public ExpectedExceptionWithMessageAttribute(Type exceptionType, string expectedMessage)
{
this.ExceptionType = exceptionType;
this.ExpectedMessage = expectedMessage;
}
protected override void Verify(Exception e)
{
if (e.GetType() != this.ExceptionType)
{
throw new AssertFailedException(string.Format(
"Test method threw exception {0}, but exception {1} was expected. Exception message: {1}: {2}",
this.ExceptionType.FullName,
e.GetType().FullName,
e.Message
));
}
var actualMessage = e.Message.Trim();
if (this.ExpectedMessage != null && !this.ExpectedMessage.Equals(actualMessage))
{
throw new AssertFailedException(string.Format(
"Test method threw exception with message '{0}', but message '{1}' was expected.",
actualMessage,
this.ExpectedMessage
));
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Storj;
namespace StorjTests
{
[TestClass]
public class ExtractInstallDirTests
{
[TestMethod]
public void NullServiceCmd()
{
Assert.IsNull(CustomActionRunner.ExtractInstallDir(null));
}
[TestMethod]
public void EmptyServiceCmd()
{
Assert.IsNull(CustomActionRunner.ExtractInstallDir(""));
}
[TestMethod]
public void MissingConfigDirFlag()
{
Assert.IsNull(CustomActionRunner.ExtractInstallDir("\"C:\\Program Files\\Storj\\Storage Node\\storagenode.exe\" run"));
}
[TestMethod]
public void ValidServiceCmd()
{
Assert.AreEqual("C:\\Program Files\\Storj\\Storage Node\\\\",
CustomActionRunner.ExtractInstallDir("\"C:\\Program Files\\Storj\\Storage Node\\storagenode.exe\" run --config-dir \"C:\\Program Files\\Storj\\Storage Node\\\\\""));
}
}
}

View File

@ -0,0 +1,20 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("StorjTests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("StorjTests")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("a3bae3d4-cc1f-4b10-a75f-fcb97f63ef3a")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StorjTests</RootNamespace>
<AssemblyName>StorjTests</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>15.0</OldToolsVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Deployment.WindowsInstaller, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ce35f76fcda82bad, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="ExpectedExceptionWithMessage.cs" />
<Compile Include="ExtractInstallDirTests.cs" />
<Compile Include="ValidateIdentityDirTests.cs" />
<Compile Include="ValidateStorageDirTests.cs" />
<Compile Include="ValidateStorageTests.cs" />
<Compile Include="ValidateBandwidthTests.cs" />
<Compile Include="ValidateWalletTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Storj\Storj.csproj">
<Project>{DDD766C6-0AED-44C9-B61A-2D752D811B56}</Project>
<Name>Storj</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" />
</Project>

View File

@ -0,0 +1,44 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Storj;
namespace StorjTests
{
[TestClass]
public class ValidateBandwidthTests
{
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The value cannot be empty.")]
public void NullBandwidth()
{
CustomActionRunner.ValidateBandwidth(null);
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The value cannot be empty.")]
public void EmptyBandwidth()
{
CustomActionRunner.ValidateBandwidth("");
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "'some random text' is not a valid number.")]
public void InvalidNumber()
{
CustomActionRunner.ValidateBandwidth("some random text");
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The allocated bandwidth cannot be less than 2 TB.")]
public void TooSmall()
{
CustomActionRunner.ValidateBandwidth("1.41");
}
[TestMethod]
public void ValidBandwidth()
{
CustomActionRunner.ValidateBandwidth("3.14");
}
}
}

View File

@ -0,0 +1,33 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Storj;
namespace StorjTests
{
[TestClass]
public class ValidateIdentityDirTests
{
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "You must select an identity folder.")]
public void NullIdentityDir()
{
CustomActionRunner.ValidateIdentityDir(null);
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "You must select an identity folder.")]
public void EmptyIdentityDir()
{
CustomActionRunner.ValidateIdentityDir("");
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "Folder 'X:\\Some\\Nonexistent\\Folder' does not exist.")]
public void NonexistentIdentityDir()
{
CustomActionRunner.ValidateIdentityDir("X:\\Some\\Nonexistent\\Folder");
}
// TODO: add tests that mock the file system
}
}

View File

@ -0,0 +1,26 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Storj;
namespace StorjTests
{
[TestClass]
public class ValidateStorageDirTests
{
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "You must select a storage folder.")]
public void NullStorageDir()
{
CustomActionRunner.ValidateStorageDir(null);
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "You must select a storage folder.")]
public void EmptyStorageDir()
{
CustomActionRunner.ValidateStorageDir("");
}
// TODO: add tests that mock the file system
}
}

View File

@ -0,0 +1,68 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Storj;
namespace StorjTests
{
[TestClass]
public class ValidateStorageTests
{
private const string StorageDir = "X:\\storage";
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The value cannot be empty.")]
public void NullStorage()
{
CustomActionRunner.ValidateStorage(null, StorageDir);
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The value cannot be empty.")]
public void EmptyStorage()
{
CustomActionRunner.ValidateStorage("", StorageDir);
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "'some random text' is not a valid number.")]
public void InvalidNumber()
{
CustomActionRunner.ValidateStorage("some random text", StorageDir);
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The allocated disk space cannot be less than 0.5 TB.")]
public void TooSmall()
{
CustomActionRunner.ValidateStorage("0.41", StorageDir);
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "10000000 TB is too large value for allocated storage.")]
public void TooLarge()
{
CustomActionRunner.ValidateStorage("10000000", StorageDir);
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The storage directory cannot be empty")]
public void NullStorageDir()
{
CustomActionRunner.ValidateStorage("3.14", null);
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The storage directory cannot be empty")]
public void EmptyStorageDir()
{
CustomActionRunner.ValidateStorage("3.14", "");
}
// TODO: add tests that mock the file system
// [TestMethod]
// public void ValidStorage()
// {
// CustomActionRunner.ValidateStorage("3.14", StorageDir);
// }
}
}

View File

@ -0,0 +1,51 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Storj;
namespace StorjTests
{
[TestClass]
public class ValidateWalletTests
{
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The payout address cannot be empty.")]
public void NullWallet()
{
CustomActionRunner.ValidateWallet(null);
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The payout address cannot be empty.")]
public void EmptyWallet()
{
CustomActionRunner.ValidateWallet("");
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The payout address must start with a '0x' prefix.")]
public void PrefixMissing()
{
CustomActionRunner.ValidateWallet("e857955cfCd98bAe1073d4e314c3F9526799357A");
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The payout address must have 40 characters after the '0x' prefix.")]
public void TooShortWallet()
{
CustomActionRunner.ValidateWallet("0xe857955cfCd98bAe1073d4e314c3F9526799357");
}
[TestMethod]
[ExpectedExceptionWithMessage(typeof(ArgumentException), "The payout address must have 40 characters after the '0x' prefix.")]
public void TooLongWallet()
{
CustomActionRunner.ValidateWallet("0xe857955cfCd98bAe1073d4e314c3F9526799357A0");
}
[TestMethod]
public void ValidWallet()
{
CustomActionRunner.ValidateWallet("0xe857955cfCd98bAe1073d4e314c3F9526799357A");
}
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MSTest.TestAdapter" version="1.3.2" targetFramework="net45" />
<package id="MSTest.TestFramework" version="1.3.2" targetFramework="net45" />
</packages>

View File

@ -5,6 +5,9 @@ rem copy the storagenode binaries to the installer project
copy release\%TAG%\storagenode_windows_amd64.exe installer\windows\storagenode.exe
copy release\%TAG%\storagenode-updater_windows_amd64.exe installer\windows\storagenode-updater.exe
rem install NuGet packages
nuget install installer\windows\StorjTests\packages.config -o installer\windows\packages
rem build the installer
msbuild installer\windows\windows.sln /t:Build /p:Configuration=Release

View File

@ -0,0 +1,8 @@
rem install NuGet packages
nuget install installer\windows\StorjTests\packages.config -o installer\windows\packages
rem build the test project
msbuild installer\windows\StorjTests
rem run the unit tests
vstest.console installer\windows\StorjTests\bin\Debug\StorjTests.dll

View File

@ -4,23 +4,46 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 16.0.29215.179
MinimumVisualStudioVersion = 10.0.40219.1
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "windows", "windows.wixproj", "{1FDEF912-9783-4E0B-B656-FB80AA4B5F68}"
ProjectSection(ProjectDependencies) = postProject
{A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A} = {A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Storj", "Storj\Storj.csproj", "{DDD766C6-0AED-44C9-B61A-2D752D811B56}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StorjTests", "StorjTests\StorjTests.csproj", "{A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1FDEF912-9783-4E0B-B656-FB80AA4B5F68}.Debug|Any CPU.ActiveCfg = Debug|x86
{1FDEF912-9783-4E0B-B656-FB80AA4B5F68}.Debug|Any CPU.Build.0 = Debug|x86
{1FDEF912-9783-4E0B-B656-FB80AA4B5F68}.Debug|x86.ActiveCfg = Debug|x86
{1FDEF912-9783-4E0B-B656-FB80AA4B5F68}.Debug|x86.Build.0 = Debug|x86
{1FDEF912-9783-4E0B-B656-FB80AA4B5F68}.Release|Any CPU.ActiveCfg = Release|x86
{1FDEF912-9783-4E0B-B656-FB80AA4B5F68}.Release|Any CPU.Build.0 = Release|x86
{1FDEF912-9783-4E0B-B656-FB80AA4B5F68}.Release|x86.ActiveCfg = Release|x86
{1FDEF912-9783-4E0B-B656-FB80AA4B5F68}.Release|x86.Build.0 = Release|x86
{DDD766C6-0AED-44C9-B61A-2D752D811B56}.Debug|Any CPU.ActiveCfg = Debug|x86
{DDD766C6-0AED-44C9-B61A-2D752D811B56}.Debug|Any CPU.Build.0 = Debug|x86
{DDD766C6-0AED-44C9-B61A-2D752D811B56}.Debug|x86.ActiveCfg = Debug|x86
{DDD766C6-0AED-44C9-B61A-2D752D811B56}.Debug|x86.Build.0 = Debug|x86
{DDD766C6-0AED-44C9-B61A-2D752D811B56}.Release|Any CPU.ActiveCfg = Release|x86
{DDD766C6-0AED-44C9-B61A-2D752D811B56}.Release|Any CPU.Build.0 = Release|x86
{DDD766C6-0AED-44C9-B61A-2D752D811B56}.Release|x86.ActiveCfg = Release|x86
{DDD766C6-0AED-44C9-B61A-2D752D811B56}.Release|x86.Build.0 = Release|x86
{A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A}.Debug|x86.ActiveCfg = Debug|Any CPU
{A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A}.Debug|x86.Build.0 = Debug|Any CPU
{A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A}.Release|Any CPU.Build.0 = Release|Any CPU
{A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A}.Release|x86.ActiveCfg = Release|Any CPU
{A3BAE3D4-CC1F-4B10-A75F-FCB97F63EF3A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE