Merge pull request #148 from wabbajack-tools/validation-tests

Add modlist validation tests.
This commit is contained in:
Timothy Baldridge 2019-11-05 16:25:18 -07:00 committed by GitHub
commit 21b603e78a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 461 additions and 44 deletions

View File

@ -81,6 +81,8 @@ namespace Wabbajack.Common
}
}
public static string WabbajackCacheLocation = "http://build.wabbajack.org/nexus_api_cache/";
public static TimeSpan NexusCacheExpiry = new TimeSpan(1, 0, 0, 0);
}
}

View File

@ -147,13 +147,28 @@ namespace Wabbajack.Common
return Convert.ToBase64String(data);
}
public static string ToHEX(this byte[] bytes)
public static string ToHex(this byte[] bytes)
{
var builder = new StringBuilder();
for (var i = 0; i < bytes.Length; i++) builder.Append(bytes[i].ToString("x2"));
return builder.ToString();
}
public static byte[] FromHex(this string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
public static DateTime AsUnixTime(this long timestamp)
{
System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
dtDateTime = dtDateTime.AddSeconds(timestamp).ToLocalTime();
return dtDateTime;
}
/// <summary>
/// Returns data from a base64 stream
/// </summary>
@ -535,8 +550,8 @@ namespace Wabbajack.Common
public static void CreatePatch(byte[] a, byte[] b, Stream output)
{
var data_a = a.SHA256().FromBase64().ToHEX();
var data_b = b.SHA256().FromBase64().ToHEX();
var data_a = a.SHA256().FromBase64().ToHex();
var data_b = b.SHA256().FromBase64().ToHex();
var cache_file = Path.Combine("patch_cache", $"{data_a}_{data_b}.patch");
if (!Directory.Exists("patch_cache"))
Directory.CreateDirectory("patch_cache");
@ -570,7 +585,7 @@ namespace Wabbajack.Common
public static void TryGetPatch(string foundHash, string fileHash, out byte[] ePatch)
{
var patch_name = Path.Combine("patch_cache",
$"{foundHash.FromBase64().ToHEX()}_{fileHash.FromBase64().ToHEX()}.patch");
$"{foundHash.FromBase64().ToHex()}_{fileHash.FromBase64().ToHex()}.patch");
ePatch = File.Exists(patch_name) ? File.ReadAllBytes(patch_name) : null;
}

View File

@ -128,18 +128,12 @@
<PackageReference Include="ini-parser">
<Version>2.5.2</Version>
</PackageReference>
<PackageReference Include="murmurhash">
<Version>1.0.3</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>12.0.2</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json.Bson">
<Version>1.0.2</Version>
</PackageReference>
<PackageReference Include="protobuf-net">
<Version>2.4.0</Version>
</PackageReference>
<PackageReference Include="System.Data.HashFunction.xxHash">
<Version>2.0.0</Version>
</PackageReference>

View File

@ -15,6 +15,7 @@ using VFS;
using Wabbajack.Common;
using Wabbajack.Lib.CompilationSteps;
using Wabbajack.Lib.Downloaders;
using Wabbajack.Lib.ModListRegistry;
using Wabbajack.Lib.NexusApi;
using Wabbajack.Lib.Validation;
using Directory = Alphaleonis.Win32.Filesystem.Directory;
@ -346,6 +347,16 @@ namespace Wabbajack.Lib
});
}
}
Utils.Log("Exporting Modlist metadata");
var metadata = new ModlistMetadata.DownloadMetadata
{
Size = File.GetSize(ModListOutputFile),
Hash = ModListOutputFile.FileHash()
};
metadata.ToJSON(ModListOutputFile + ".meta.json");
Utils.Log("Removing modlist staging folder");
Directory.Delete(ModListOutputFolder, true);

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using Wabbajack.Common;
namespace Wabbajack.Lib.Downloaders
{
@ -49,5 +50,11 @@ namespace Wabbajack.Lib.Downloaders
return Downloaders.OfType<IUrlDownloader>().Select(d => d.GetDownloaderState(url)).FirstOrDefault(result => result != null);
}
public static void PrepareAll(IEnumerable<AbstractDownloadState> states)
{
states.Select(s => s.GetDownloader().GetType())
.Distinct()
.Do(t => Downloaders.First(d => d.GetType() == t).Prepare());
}
}
}

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Wabbajack.Common;
using Wabbajack.Lib.NexusApi;
using Wabbajack.Lib.Validation;
using Game = Wabbajack.Common.Game;
namespace Wabbajack.Lib.Downloaders
{
@ -54,6 +55,9 @@ namespace Wabbajack.Lib.Downloaders
Utils.Error($"Automated installs with Wabbajack requires a premium nexus account. {client.Username} is not a premium account.");
return;
}
client.ClearUpdatedModsInCache();
//var updated = client.GetModsUpdatedSince(Game.Skyrim,DateTime.Now - TimeSpan.FromDays(30));
}
public class State : AbstractDownloadState

View File

@ -51,11 +51,21 @@ namespace Wabbajack.Lib.ModListRegistry
[JsonProperty("download")]
public string Download { get; set; }
[JsonProperty("download_metadata")]
public DownloadMetadata DownloadMetadata { get; set; }
[JsonProperty("machineURL")]
public string MachineURL { get; set; }
}
public class DownloadMetadata
{
public string Hash { get; set; }
public long Size { get; set; }
}
public static List<ModlistMetadata> LoadFromGithub()
{
var client = new HttpClient();
@ -63,5 +73,16 @@ namespace Wabbajack.Lib.ModListRegistry
var result = client.GetStringSync(Consts.ModlistMetadataURL);
return result.FromJSONString<List<ModlistMetadata>>();
}
public bool NeedsDownload(string modlistPath)
{
if (!File.Exists(modlistPath)) return true;
if (Links.DownloadMetadata?.Hash == null)
{
return false;
}
return Links.DownloadMetadata.Hash != modlistPath.FileHash();
}
}
}

View File

@ -153,7 +153,6 @@ namespace Wabbajack.Lib.NexusApi
}
catch (Exception)
{
Utils.Log("Couldn't find x-rl-*-remaining headers in Nexus response. Ignoring");
}
}
@ -173,6 +172,9 @@ namespace Wabbajack.Lib.NexusApi
headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
headers.Add("Application-Name", Consts.AppName);
headers.Add("Application-Version", $"{Assembly.GetEntryAssembly()?.GetName()?.Version ?? new Version(0, 1)}");
if (!Directory.Exists(Consts.NexusCacheDirectory))
Directory.CreateDirectory(Consts.NexusCacheDirectory);
}
private T Get<T>(string url)
@ -194,16 +196,33 @@ namespace Wabbajack.Lib.NexusApi
private T GetCached<T>(string url)
{
var code = Encoding.UTF8.GetBytes(url).ToHEX();
var cache_file = Path.Combine(Consts.NexusCacheDirectory, code + ".json");
if (File.Exists(cache_file) && DateTime.Now - File.GetLastWriteTime(cache_file) < Consts.NexusCacheExpiry)
var code = Encoding.UTF8.GetBytes(url).ToHex() + ".json";
if (UseLocalCache)
{
return cache_file.FromJSON<T>();
if (!Directory.Exists(LocalCacheDir))
Directory.CreateDirectory(LocalCacheDir);
var cache_file = Path.Combine(LocalCacheDir, code);
if (File.Exists(cache_file))
{
return cache_file.FromJSON<T>();
}
var result = Get<T>(url);
result.ToJSON(cache_file);
return result;
}
try
{
return Get<T>(Consts.WabbajackCacheLocation + code);
}
catch (Exception)
{
return Get<T>(url);
}
var result = Get<T>(url);
result.ToJSON(cache_file);
return result;
}
@ -307,6 +326,77 @@ namespace Wabbajack.Lib.NexusApi
{
public string URI { get; set; }
}
private class UpdatedMod
{
public long mod_id;
public long latest_file_update;
public long latest_mod_activity;
}
private static bool? _useLocalCache;
public static bool UseLocalCache
{
get
{
if (_useLocalCache == null) return LocalCacheDir != null;
return _useLocalCache ?? false;
}
set => _useLocalCache = value;
}
private static string _localCacheDir;
public static string LocalCacheDir
{
get
{
if (_localCacheDir == null)
_localCacheDir = Environment.GetEnvironmentVariable("NEXUSCACHEDIR");
return _localCacheDir;
}
set => _localCacheDir = value;
}
public void ClearUpdatedModsInCache()
{
if (!UseLocalCache) return;
var purge = GameRegistry.Games.Values
.Where(game => game.NexusName != null)
.Select(game => new
{
game = game,
mods = Get<List<UpdatedMod>>(
$"https://api.nexusmods.com/v1/games/{game.NexusName}/mods/updated.json?period=1m")
})
.SelectMany(r => r.mods.Select(mod => new {game = r.game,
mod = mod}))
.ToList();
Utils.Log($"Found {purge.Count} updated mods in the last month");
var to_purge = Directory.EnumerateFiles(LocalCacheDir, "*.json")
.Select(f =>
{
Utils.Status("Cleaning Nexus cache for");
var uri = new Uri(Encoding.UTF8.GetString(Path.GetFileNameWithoutExtension(f).FromHex()));
var parts = uri.PathAndQuery.Split('/', '.').ToHashSet();
var found = purge.FirstOrDefault(p => parts.Contains(p.game.NexusName) && parts.Contains(p.mod.mod_id.ToString()));
if (found != null)
{
var should_remove = File.GetLastWriteTimeUtc(f) <= found.mod.latest_file_update.AsUnixTime();
return (should_remove, f);
}
return (false, f);
})
.Where(p => p.Item1)
.ToList();
Utils.Log($"Purging {to_purge.Count} cache entries");
to_purge.PMap(f => File.Delete(f.f));
}
}
}

View File

@ -61,7 +61,7 @@ namespace Wabbajack.Lib
$"#### Download Summary ({lst.Archives.Count} archives - {lst.Archives.Sum(a => a.Size).ToFileSizeString()})");
foreach (var archive in SortArchives(lst.Archives))
{
var hash = archive.Hash.FromBase64().ToHEX();
var hash = archive.Hash.FromBase64().ToHex();
NoWrapText(archive.State.GetReportEntry(archive));
NoWrapText($" * Size : {archive.Size.ToFileSizeString()}");
NoWrapText($" * SHA256 : [{hash}](https://www.virustotal.com/gui/file/{hash})");

View File

@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -30,6 +31,26 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Wabbajack.Common;
using Wabbajack.Lib;
using Wabbajack.Lib.Downloaders;
using Wabbajack.Lib.ModListRegistry;
using Wabbajack.Lib.NexusApi;
namespace Wabbajack.Test.ListValidation
{
[TestClass]
public class ListValidation
{
[TestInitialize]
public void Setup()
{
Directory.CreateDirectory(Consts.ModListDownloadFolder);
Utils.LogMessages.Subscribe(s => TestContext.WriteLine(s));
var api = new NexusApiClient();
api.ClearUpdatedModsInCache();
}
private TestContext testContextInstance;
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}
[TestCategory("ListValidation")]
[DataTestMethod]
[DynamicData(nameof(GetModLists), DynamicDataSourceType.Method)]
public void ValidateModLists(string name, ModlistMetadata list)
{
Log($"Testing {list.Links.MachineURL} - {list.Title}");
var modlist_path = Path.Combine(Consts.ModListDownloadFolder, list.Links.MachineURL + ".wabbajack");
if (list.NeedsDownload(modlist_path))
{
var state = DownloadDispatcher.ResolveArchive(list.Links.Download);
Log($"Downloading {list.Links.MachineURL} - {list.Title}");
state.Download(modlist_path);
}
else
{
Log($"No changes detected from downloaded modlist");
}
Log($"Loading {modlist_path}");
var installer = Installer.LoadFromFile(modlist_path);
Log($"{installer.Archives.Count} archives to validate");
var invalids = installer.Archives
.PMap(archive =>
{
Log($"Validating: {archive.Name}");
return new {archive, is_valid = archive.State.Verify()};
})
.Where(a => !a.is_valid)
.ToList();
DownloadDispatcher.PrepareAll(installer.Archives.Select(a => a.State));
Log("Invalid Archives");
foreach (var invalid in invalids)
{
Log(invalid.archive.State.GetReportEntry(invalid.archive));
}
Assert.AreEqual(invalids.Count, 0, "There were invalid archives");
}
void Log(string msg)
{
TestContext.WriteLine(msg);
}
public static IEnumerable<object[]> GetModLists()
{
return ModlistMetadata.LoadFromGithub().Select(l => new object[] {l.Title, l});
}
}
}

View File

@ -0,0 +1,20 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Wabbajack.Test.ListValidation")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Wabbajack.Test.ListValidation")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("ba013d05-1d70-452f-bb8f-272b31e6c74e")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<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>{BA013D05-1D70-452F-BB8F-272B31E6C74E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Wabbajack.Test.ListValidation</RootNamespace>
<AssemblyName>Wabbajack.Test.ListValidation</AssemblyName>
<TargetFrameworkVersion>v4.7.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>
</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>
<PlatformTarget>x64</PlatformTarget>
</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>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="ListValidation.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Wabbajack.Common\Wabbajack.Common.csproj">
<Project>{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}</Project>
<Name>Wabbajack.Common</Name>
</ProjectReference>
<ProjectReference Include="..\Wabbajack.Lib\Wabbajack.Lib.csproj">
<Project>{0a820830-a298-497d-85e0-e9a89efef5fe}</Project>
<Name>Wabbajack.Lib</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="MSTest.TestAdapter">
<Version>1.3.2</Version>
</PackageReference>
<PackageReference Include="MSTest.TestFramework">
<Version>1.3.2</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>12.0.2</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -7,6 +7,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
using Wabbajack.Common;
using Wabbajack.Lib;
using Wabbajack.Lib.Downloaders;
using Wabbajack.Lib.NexusApi;
using Wabbajack.Lib.Validation;
using File = Alphaleonis.Win32.Filesystem.File;
@ -15,6 +16,11 @@ namespace Wabbajack.Test
[TestClass]
public class DownloaderTests
{
[TestInitialize]
public void Setup()
{
}
[TestMethod]
public void TestAllPrepares()
{
@ -145,9 +151,9 @@ namespace Wabbajack.Test
public void MediaFireDownload()
{
var ini = @"[General]
directURL=http://www.mediafire.com/file/agiqzm1xwebczpx/WABBAJACK_TEST_FILE.txt";
directURL=http://www.mediafire.com/file/agiqzm1xwebczpx/WABBAJACK_TEST_FILE.txt";
var state = (AbstractDownloadState)DownloadDispatcher.ResolveArchive(ini.LoadIniString());
var state = (AbstractDownloadState) DownloadDispatcher.ResolveArchive(ini.LoadIniString());
Assert.IsNotNull(state);
@ -155,44 +161,56 @@ namespace Wabbajack.Test
"http://www.mediafire.com/file/agiqzm1xwebczpx/WABBAJACK_TEST_FILE.txt");
Assert.AreEqual("http://www.mediafire.com/file/agiqzm1xwebczpx/WABBAJACK_TEST_FILE.txt",
((MediaFireDownloader.State)url_state).Url);
((MediaFireDownloader.State) url_state).Url);
var converted = state.ViaJSON();
Assert.IsTrue(converted.Verify());
var filename = Guid.NewGuid().ToString();
Assert.IsTrue(converted.IsWhitelisted(new ServerWhitelist { AllowedPrefixes = new List<string> { "http://www.mediafire.com/file/agiqzm1xwebczpx/" } }));
Assert.IsFalse(converted.IsWhitelisted(new ServerWhitelist { AllowedPrefixes = new List<string>() }));
Assert.IsTrue(converted.IsWhitelisted(new ServerWhitelist
{AllowedPrefixes = new List<string> {"http://www.mediafire.com/file/agiqzm1xwebczpx/"}}));
Assert.IsFalse(converted.IsWhitelisted(new ServerWhitelist {AllowedPrefixes = new List<string>()}));
converted.Download(new Archive { Name = "Media Fire Test.txt" }, filename);
converted.Download(new Archive {Name = "Media Fire Test.txt"}, filename);
Assert.AreEqual(File.ReadAllText(filename), "Cheese for Everyone!");
}
[TestMethod]
public void NexusDownload()
{
var ini = @"[General]
var old_val = NexusApiClient.UseLocalCache;
try
{
NexusApiClient.UseLocalCache = false;
var ini = @"[General]
gameName=SkyrimSE
modID = 12604
fileID=35407";
var state = (AbstractDownloadState)DownloadDispatcher.ResolveArchive(ini.LoadIniString());
var state = (AbstractDownloadState)DownloadDispatcher.ResolveArchive(ini.LoadIniString());
Assert.IsNotNull(state);
Assert.IsNotNull(state);
var converted = state.ViaJSON();
Assert.IsTrue(converted.Verify());
// Exercise the cache code
Assert.IsTrue(converted.Verify());
var filename = Guid.NewGuid().ToString();
var converted = state.ViaJSON();
Assert.IsTrue(converted.Verify());
// Exercise the cache code
Assert.IsTrue(converted.Verify());
var filename = Guid.NewGuid().ToString();
Assert.IsTrue(converted.IsWhitelisted(new ServerWhitelist { AllowedPrefixes = new List<string> () }));
Assert.IsTrue(converted.IsWhitelisted(new ServerWhitelist { AllowedPrefixes = new List<string> () }));
converted.Download(new Archive { Name = "SkyUI.7z" }, filename);
converted.Download(new Archive { Name = "SkyUI.7z" }, filename);
Assert.AreEqual(filename.FileHash(), "dF2yafV2Oks=");
Assert.AreEqual(filename.FileHash(), "dF2yafV2Oks=");
}
finally
{
NexusApiClient.UseLocalCache = old_val;
}
}
[TestMethod]

View File

@ -28,6 +28,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Test", "Wabbajack
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Lib", "Wabbajack.Lib\Wabbajack.Lib.csproj", "{0A820830-A298-497D-85E0-E9A89EFEF5FE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Test.ListValidation", "Wabbajack.Test.ListValidation\Wabbajack.Test.ListValidation.csproj", "{BA013D05-1D70-452F-BB8F-272B31E6C74E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug (no commandargs)|Any CPU = Debug (no commandargs)|Any CPU
@ -169,8 +171,8 @@ Global
{A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Release|x86.Build.0 = Release|x86
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Debug (no commandargs)|x64.ActiveCfg = Debug|Any CPU
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Debug (no commandargs)|x64.Build.0 = Debug|Any CPU
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Debug (no commandargs)|x64.ActiveCfg = Debug|x64
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Debug (no commandargs)|x64.Build.0 = Debug|x64
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Debug (no commandargs)|x86.ActiveCfg = Debug|Any CPU
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Debug (no commandargs)|x86.Build.0 = Debug|Any CPU
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@ -185,6 +187,24 @@ Global
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Release|x64.Build.0 = Release|Any CPU
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Release|x86.ActiveCfg = Release|Any CPU
{0A820830-A298-497D-85E0-E9A89EFEF5FE}.Release|x86.Build.0 = Release|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug (no commandargs)|x64.ActiveCfg = Debug|x64
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug (no commandargs)|x64.Build.0 = Debug|x64
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug (no commandargs)|x86.ActiveCfg = Debug|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug (no commandargs)|x86.Build.0 = Debug|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug|x64.ActiveCfg = Debug|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug|x64.Build.0 = Debug|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug|x86.ActiveCfg = Debug|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Debug|x86.Build.0 = Debug|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Release|Any CPU.Build.0 = Release|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Release|x64.ActiveCfg = Release|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Release|x64.Build.0 = Release|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Release|x86.ActiveCfg = Release|Any CPU
{BA013D05-1D70-452F-BB8F-272B31E6C74E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -331,18 +331,18 @@
<Version>0.15.1</Version>
</PackageReference>
<PackageReference Include="Costura.Fody">
<Version>4.0.0</Version>
<Version>4.1.0</Version>
</PackageReference>
<PackageReference Include="DynamicData">
<Version>6.13.17</Version>
<Version>6.13.20</Version>
</PackageReference>
<PackageReference Include="Fody">
<Version>5.1.1</Version>
<Version>6.0.4</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="GitInfo">
<Version>2.0.20</Version>
<Version>2.0.21</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
@ -377,7 +377,7 @@
<Version>10.5.7</Version>
</PackageReference>
<PackageReference Include="ReactiveUI.WPF">
<Version>10.4.1</Version>
<Version>10.5.7</Version>
</PackageReference>
<PackageReference Include="SharpCompress">
<Version>0.23.0</Version>
@ -398,7 +398,7 @@
<Version>1.0.8</Version>
</PackageReference>
<PackageReference Include="YamlDotNet">
<Version>7.0.0</Version>
<Version>8.0.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>

View File

@ -41,6 +41,7 @@ steps:
inputs:
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
testFiltercriteria: 'TestCategory!=ListValidation'
- task: DownloadSecureFile@1
inputs:
secureFile: 'CertFile.p12'