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

Support multiple remote versions #3036

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
30 changes: 25 additions & 5 deletions Netkan/Transformers/AvcTransformer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,34 @@ public IEnumerable<Metadata> Transform(Metadata metadata, TransformOptions opts)
{
var remoteJson = _github?.DownloadText(remoteUri)
?? _http.DownloadText(remoteUri);
var remoteAvc = JsonConvert.DeserializeObject<AvcVersion>(remoteJson);

if (avc.version.CompareTo(remoteAvc.version) == 0)
var rootToken = JToken.Parse(remoteJson, new JsonLoadSettings { CommentHandling = CommentHandling.Ignore });

if (rootToken.Type == JTokenType.Object)
{
var remoteAvc = rootToken.ToObject<AvcVersion>();
if (avc.version.CompareTo(remoteAvc.version) == 0)
{
// Local AVC and Remote AVC describe the same version, prefer
Log.Info("Remote AVC version file describes same version as local AVC version file, using it preferrentially.");
avc = remoteAvc;
}
}
else if (rootToken.Type == JTokenType.Array)
{
// Local AVC and Remote AVC describe the same version, prefer
Log.Info("Remote AVC version file describes same version as local AVC version file, using it preferrentially.");
avc = remoteAvc;
var remoteAvcs = rootToken.ToObject<AvcVersion[]>();
AvcVersion matchedVersion = null;
foreach (var remoteAvc in remoteAvcs)
{
if (avc.version.CompareTo(remoteAvc.version) != 0) continue;
if (matchedVersion != null) throw new InvalidOperationException("More than one matching version found in remote AVC file");
matchedVersion = remoteAvc;
}
if (matchedVersion == null) throw new InvalidOperationException("No matching version found in remote AVC file");
avc = matchedVersion;
}
else
throw new InvalidOperationException("Invalid root token in remote AVC: " + rootToken.Type.ToString());
}
catch (Exception e)
{
Expand Down
334 changes: 334 additions & 0 deletions Tests/NetKAN/Transformers/AvcTransformerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,5 +291,339 @@ public void Transform_TrustVersionFileTrue_OverridesExistingInfo()
);
}

[Test]
public void Transform_RemoteAvcOverrides_SameVersion()
{
// Arrange
var mHttp = new Mock<IHttpService>();
mHttp.Setup(i => i.DownloadText(It.Is<System.Uri>(u => u.OriginalString == "https://awesomemod.example/avc.version")))
.Returns("//leading comment\n\n{\"version\":\"1.0.0\",\"ksp_version_min\":\"1.2.1\",\"ksp_version_max\":\"1.2.99\"}");

var mModuleService = new Mock<IModuleService>();
mModuleService.Setup(i => i.GetInternalAvc(It.IsAny<CkanModule>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(new AvcVersion()
{
version = new ModuleVersion("1.0.0"),
ksp_version = new KspVersion(1, 2, 3),
Url = "https://awesomemod.example/avc.version",
}); ;

ITransformer sut = new AvcTransformer(mHttp.Object, mModuleService.Object, null);

JObject json = new JObject();
json["spec_version"] = 1;
json["identifier"] = "AwesomeMod";
json["$vref"] = "#/ckan/ksp-avc";
json["download"] = "https://awesomemod.example/AwesomeMod.zip";
json["version"] = "1.0.0";
json["ksp_version"] = "1.2.3";

// Act
Metadata result = sut.Transform(new Metadata(json), opts).First();
JObject transformedJson = result.Json();

// Assert
Assert.That((string)transformedJson["ksp_version"], Is.Null,
"AvcTransformer should replace local AVC info with remote AVC info if the module versions match."
);

Assert.That((string)transformedJson["ksp_version_min"], Is.EqualTo("1.2.1"),
"AvcTransformer should replace local AVC info with remote AVC info if the module versions match."
);

Assert.That((string)transformedJson["ksp_version_max"], Is.EqualTo("1.2.99"),
"AvcTransformer should replace local AVC info with remote AVC info if the module versions match."
);
}

[Test]
public void Transform_RemoteAvcOverrides_DifferentVersion()
{
// Arrange
var mHttp = new Mock<IHttpService>();
mHttp.Setup(i => i.DownloadText(It.Is<System.Uri>(u => u.OriginalString == "https://awesomemod.example/avc.version")))
.Returns("//leading comment\n\n{\"version\":\"1.0.1\",\"ksp_version_min\":\"1.2.1\",\"ksp_version_max\":\"1.2.99\"}");

var mModuleService = new Mock<IModuleService>();
mModuleService.Setup(i => i.GetInternalAvc(It.IsAny<CkanModule>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(new AvcVersion()
{
version = new ModuleVersion("1.0.0"),
ksp_version = new KspVersion(1, 2, 3),
Url = "https://awesomemod.example/avc.version",
}); ;

ITransformer sut = new AvcTransformer(mHttp.Object, mModuleService.Object, null);

JObject json = new JObject();
json["spec_version"] = 1;
json["identifier"] = "AwesomeMod";
json["$vref"] = "#/ckan/ksp-avc";
json["download"] = "https://awesomemod.example/AwesomeMod.zip";
json["version"] = "1.0.0";
json["ksp_version"] = "1.2.3";

// Act
Metadata result = sut.Transform(new Metadata(json), opts).First();
JObject transformedJson = result.Json();

// Assert
Assert.That((string)transformedJson["ksp_version"], Is.EqualTo("1.2.3"),
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);

Assert.That((string)transformedJson["ksp_version_min"], Is.Null,
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);

Assert.That((string)transformedJson["ksp_version_max"], Is.Null,
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);
}

[Test]
public void Transform_RemoteAvcOverrides_FetchError()
{
// Arrange
var mHttp = new Mock<IHttpService>();
mHttp.Setup(i => i.DownloadText(It.Is<System.Uri>(u => u.OriginalString == "https://awesomemod.example/avc.version")))
.Throws<System.Exception>();

var mModuleService = new Mock<IModuleService>();
mModuleService.Setup(i => i.GetInternalAvc(It.IsAny<CkanModule>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(new AvcVersion()
{
version = new ModuleVersion("1.0.0"),
ksp_version = new KspVersion(1, 2, 3),
Url = "https://awesomemod.example/avc.version",
}); ;

ITransformer sut = new AvcTransformer(mHttp.Object, mModuleService.Object, null);

JObject json = new JObject();
json["spec_version"] = 1;
json["identifier"] = "AwesomeMod";
json["$vref"] = "#/ckan/ksp-avc";
json["download"] = "https://awesomemod.example/AwesomeMod.zip";
json["version"] = "1.0.0";
json["ksp_version"] = "1.2.3";

// Act
Metadata result = sut.Transform(new Metadata(json), opts).First();
JObject transformedJson = result.Json();

// Assert
Assert.That((string)transformedJson["ksp_version"], Is.EqualTo("1.2.3"),
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);

Assert.That((string)transformedJson["ksp_version_min"], Is.Null,
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);

Assert.That((string)transformedJson["ksp_version_max"], Is.Null,
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);
}

[Test]
public void Transform_RemoteAvcOverrides_MultipleVersions_VersionFound()
{
// Arrange
var mHttp = new Mock<IHttpService>();
mHttp.Setup(i => i.DownloadText(It.Is<System.Uri>(u => u.OriginalString == "https://awesomemod.example/avc.version")))
.Returns(@"//leading comment
[
{ ""version"" : ""1.0.1"", ""ksp_version"" : ""2.3.4"" },
{ ""version"" : ""1.0.0"", ""ksp_version_min"" : ""1.2.1"", ""ksp_version_max"" : ""1.2.99"" },
{ ""version"" : ""0.9.0"", ""ksp_version"" : ""1.0.0"" },
]
");

var mModuleService = new Mock<IModuleService>();
mModuleService.Setup(i => i.GetInternalAvc(It.IsAny<CkanModule>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(new AvcVersion()
{
version = new ModuleVersion("1.0.0"),
ksp_version = new KspVersion(1, 2, 3),
Url = "https://awesomemod.example/avc.version",
}); ;

ITransformer sut = new AvcTransformer(mHttp.Object, mModuleService.Object, null);

JObject json = new JObject();
json["spec_version"] = 1;
json["identifier"] = "AwesomeMod";
json["$vref"] = "#/ckan/ksp-avc";
json["download"] = "https://awesomemod.example/AwesomeMod.zip";
json["version"] = "1.0.0";
json["ksp_version"] = "1.2.3";

// Act
Metadata result = sut.Transform(new Metadata(json), opts).First();
JObject transformedJson = result.Json();

// Assert
Assert.That((string)transformedJson["ksp_version"], Is.Null,
"AvcTransformer should replace local AVC info with remote AVC info if the module versions match."
);

Assert.That((string)transformedJson["ksp_version_min"], Is.EqualTo("1.2.1"),
"AvcTransformer should replace local AVC info with remote AVC info if the module versions match."
);

Assert.That((string)transformedJson["ksp_version_max"], Is.EqualTo("1.2.99"),
"AvcTransformer should replace local AVC info with remote AVC info if the module versions match."
);
}

[Test]
public void Transform_RemoteAvcOverrides_MultipleVersions_VersionNotFound()
{
// Arrange
var mHttp = new Mock<IHttpService>();
mHttp.Setup(i => i.DownloadText(It.Is<System.Uri>(u => u.OriginalString == "https://awesomemod.example/avc.version")))
.Returns(@"//leading comment
[
{ ""version"" : ""1.0.2"", ""ksp_version"" : ""2.3.4"" },
{ ""version"" : ""1.0.1"", ""ksp_version_min"" : ""1.2.1"", ""ksp_version_max"" : ""1.2.99"" },
{ ""version"" : ""0.9.0"", ""ksp_version"" : ""1.0.0"" },
]
");

var mModuleService = new Mock<IModuleService>();
mModuleService.Setup(i => i.GetInternalAvc(It.IsAny<CkanModule>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(new AvcVersion()
{
version = new ModuleVersion("1.0.0"),
ksp_version = new KspVersion(1, 2, 3),
Url = "https://awesomemod.example/avc.version",
}); ;

ITransformer sut = new AvcTransformer(mHttp.Object, mModuleService.Object, null);

JObject json = new JObject();
json["spec_version"] = 1;
json["identifier"] = "AwesomeMod";
json["$vref"] = "#/ckan/ksp-avc";
json["download"] = "https://awesomemod.example/AwesomeMod.zip";
json["version"] = "1.0.0";
json["ksp_version"] = "1.2.3";

// Act
Metadata result = sut.Transform(new Metadata(json), opts).First();
JObject transformedJson = result.Json();

// Assert
Assert.That((string)transformedJson["ksp_version"], Is.EqualTo("1.2.3"),
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);

Assert.That((string)transformedJson["ksp_version_min"], Is.Null,
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);

Assert.That((string)transformedJson["ksp_version_max"], Is.Null,
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);
}

[Test]
public void Transform_RemoteAvcOverrides_MultipleVersions_MoreThanOneMatchingVersion()
{
// Arrange
var mHttp = new Mock<IHttpService>();
mHttp.Setup(i => i.DownloadText(It.Is<System.Uri>(u => u.OriginalString == "https://awesomemod.example/avc.version")))
.Returns(@"//leading comment
[
{ ""version"" : ""1.0.1"", ""ksp_version"" : ""2.3.4"" },
{ ""version"" : ""1.0.0"", ""ksp_version_min"" : ""1.2.0"", ""ksp_version_max"" : ""1.2.9"" },
{ ""version"" : ""1.0.0"", ""ksp_version_min"" : ""1.2.1"", ""ksp_version_max"" : ""1.2.99"" },
{ ""version"" : ""0.9.0"", ""ksp_version"" : ""1.0.0"" },
]
");

var mModuleService = new Mock<IModuleService>();
mModuleService.Setup(i => i.GetInternalAvc(It.IsAny<CkanModule>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(new AvcVersion()
{
version = new ModuleVersion("1.0.0"),
ksp_version = new KspVersion(1, 2, 3),
Url = "https://awesomemod.example/avc.version",
}); ;

ITransformer sut = new AvcTransformer(mHttp.Object, mModuleService.Object, null);

JObject json = new JObject();
json["spec_version"] = 1;
json["identifier"] = "AwesomeMod";
json["$vref"] = "#/ckan/ksp-avc";
json["download"] = "https://awesomemod.example/AwesomeMod.zip";
json["version"] = "1.0.0";
json["ksp_version"] = "1.2.3";

// Act
Metadata result = sut.Transform(new Metadata(json), opts).First();
JObject transformedJson = result.Json();

// Assert
Assert.That((string)transformedJson["ksp_version"], Is.EqualTo("1.2.3"),
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);

Assert.That((string)transformedJson["ksp_version_min"], Is.Null,
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);

Assert.That((string)transformedJson["ksp_version_max"], Is.Null,
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);
}

[Test]
public void Transform_RemoteAvcOverrides_MultipleVersions_UnknownJsonRootToken()
{
// Arrange
var mHttp = new Mock<IHttpService>();
mHttp.Setup(i => i.DownloadText(It.Is<System.Uri>(u => u.OriginalString == "https://awesomemod.example/avc.version")))
.Returns("//leading comment\n\n1.23456");

var mModuleService = new Mock<IModuleService>();
mModuleService.Setup(i => i.GetInternalAvc(It.IsAny<CkanModule>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(new AvcVersion()
{
version = new ModuleVersion("1.0.0"),
ksp_version = new KspVersion(1, 2, 3),
Url = "https://awesomemod.example/avc.version",
}); ;

ITransformer sut = new AvcTransformer(mHttp.Object, mModuleService.Object, null);

JObject json = new JObject();
json["spec_version"] = 1;
json["identifier"] = "AwesomeMod";
json["$vref"] = "#/ckan/ksp-avc";
json["download"] = "https://awesomemod.example/AwesomeMod.zip";
json["version"] = "1.0.0";
json["ksp_version"] = "1.2.3";

// Act
Metadata result = sut.Transform(new Metadata(json), opts).First();
JObject transformedJson = result.Json();

// Assert
Assert.That((string)transformedJson["ksp_version"], Is.EqualTo("1.2.3"),
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);

Assert.That((string)transformedJson["ksp_version_min"], Is.Null,
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);

Assert.That((string)transformedJson["ksp_version_max"], Is.Null,
"AvcTransformer should not replace local AVC info with remote AVC info if the module versions don't match."
);
}

}
}