diff --git a/test/data/nuget-artifacts/dummy.nuget.1.0.0.nupkg b/test/data/nuget-artifacts/dummy.nuget.1.0.0.nupkg deleted file mode 100644 index 070a94b..0000000 Binary files a/test/data/nuget-artifacts/dummy.nuget.1.0.0.nupkg and /dev/null differ diff --git a/test/data/nuget-artifacts/dummy.nuget.1.0.0/dummy.nuget.nuspec b/test/data/nuget-artifacts/dummy.nuget.1.0.0/dummy.nuget.nuspec deleted file mode 100644 index feb3a4a..0000000 --- a/test/data/nuget-artifacts/dummy.nuget.1.0.0/dummy.nuget.nuspec +++ /dev/null @@ -1,9 +0,0 @@ - - - - dummy.nuget - 1.0.0 - isnd.tests - Dummy test package used by integration tests. - - diff --git a/test/isnd.tests/UnitTestWebHost.cs b/test/isnd.tests/UnitTestWebHost.cs index c71b5ea..b89caae 100644 --- a/test/isnd.tests/UnitTestWebHost.cs +++ b/test/isnd.tests/UnitTestWebHost.cs @@ -1,39 +1,34 @@ -using System; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Security.Cryptography; using System.Threading; -using System.Threading.Tasks; -using System.Xml.Linq; -using Isn.Abstract; +using System; +using System.Net.Http; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore; +using Xunit; using isnd.Data; -using isnd.Data.ApiKeys; -using isnd.Helpers; -using isnd.tests; -using Microsoft.AspNetCore.DataProtection; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using NuGet.Common; -using NuGet.Configuration; +using System.Diagnostics; +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.Extensions.Configuration; +using isnd.tests; using NuGet.Protocol; +using NuGet.Configuration; +using System.Threading.Tasks; using NuGet.Protocol.Core.Types; -using Xunit; +using NuGet.Common; +using Isn.Abstract; +using isnd.Helpers; +using Microsoft.AspNetCore.DataProtection; +using System.Security.Cryptography; namespace isnd.host.tests -{ +{ [Collection("Web server collection")] public class UnitTestWebHost : IClassFixture { - private const string DummyPackageId = "dummy.nuget"; - private const string DummyPackageVersion = "1.0.0"; - private const string DummyArtifactRelativePath = "test/data/nuget-artifacts/dummy.nuget.1.0.0.nupkg"; - - private readonly WebServerFixture server; - + WebServerFixture server; public UnitTestWebHost(WebServerFixture server) { this.server = server; @@ -42,16 +37,18 @@ namespace isnd.host.tests [Fact] public void TestHaveTestDbContextAndMigrate() { - using var serviceScope = server.Host.Services.CreateScope(); - var services = serviceScope.ServiceProvider; - var myDependency = services.GetRequiredService(); - if (myDependency.Database.ProviderName?.Contains("InMemory", StringComparison.OrdinalIgnoreCase) == true) + using (var serviceScope = server.Host.Services.CreateScope()) { - myDependency.Database.EnsureCreated(); - } - else - { - myDependency.Database.Migrate(); + var services = serviceScope.ServiceProvider; + var myDependency = services.GetRequiredService(); + if (myDependency.Database.ProviderName?.Contains("InMemory", StringComparison.OrdinalIgnoreCase) == true) + { + myDependency.Database.EnsureCreated(); + } + else + { + myDependency.Database.Migrate(); + } } } @@ -77,121 +74,67 @@ namespace isnd.host.tests } [Fact] - public void TestDropUser() + void TestDropUser() { - using var serviceScope = server.Host.Services.CreateScope(); - var services = serviceScope.ServiceProvider; - var dbContext = services.GetRequiredService(); - var paul = dbContext.Users.FirstOrDefaultAsync(u => u.Email == "paul@pschneider.fr").Result; - if (paul != null) + + using (var serviceScope = server.Host.Services.CreateScope()) { - dbContext.Users.Remove(paul); - dbContext.SaveChanges(); + var services = serviceScope.ServiceProvider; + var dbContext = services.GetRequiredService(); + var paul = dbContext.Users.FirstOrDefaultAsync(u => u.Email == "paul@pschneider.fr").Result; + if (paul!=null) + { + dbContext.Users.Remove(paul); + dbContext.SaveChanges(); + } } } + [Fact] public void NugetInstallsTest() { - var pkgSourceUrl = GetServerBaseUrl() + "/" + Constants.APIPrefix + "index.json"; - using var client = new HttpClient(); - var response = client.GetAsync(pkgSourceUrl).GetAwaiter().GetResult(); - var body = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); - - Assert.True(response.IsSuccessStatusCode, $"Expected {pkgSourceUrl} to be reachable but got {(int)response.StatusCode} {response.ReasonPhrase}"); - Assert.False(string.IsNullOrWhiteSpace(body)); - Assert.Contains("PackagePublish/2.0.0", body, StringComparison.OrdinalIgnoreCase); - Assert.Contains("RegistrationsBaseUrl/Versioned", body, StringComparison.OrdinalIgnoreCase); - } - - [Fact] - public void DummyNugetArtifactShouldBeAReadablePackage() - { - var packagePath = GetDummyArtifactPath(); - Assert.True(File.Exists(packagePath), $"Missing dummy artifact at {packagePath}"); - - var fileInfo = new FileInfo(packagePath); - Assert.True(fileInfo.Length > 0, "Dummy artifact is empty."); - - using var stream = File.OpenRead(packagePath); - using var archive = new ZipArchive(stream, ZipArchiveMode.Read, leaveOpen: false); - var nuspecEntry = archive.GetEntry("dummy.nuget.nuspec"); - Assert.NotNull(nuspecEntry); - - using var nuspecStream = nuspecEntry.Open(); - var nuspec = XDocument.Load(nuspecStream); - XNamespace ns = "http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"; - var id = nuspec.Root?.Element(ns + "metadata")?.Element(ns + "id")?.Value; - var version = nuspec.Root?.Element(ns + "metadata")?.Element(ns + "version")?.Value; - - Assert.Equal(DummyPackageId, id); - Assert.Equal(DummyPackageVersion, version); - } - - [Fact] - public async Task PushDummyPackageAndDiscoverItThroughNuGetEndpoints() - { - var apiKeyValue = $"dummy-key-{Guid.NewGuid():N}"; - var packagePath = GetDummyArtifactPath(); - Assert.True(File.Exists(packagePath), $"Missing dummy artifact at {packagePath}"); - using (var serviceScope = server.Host.Services.CreateScope()) { - var dbContext = serviceScope.ServiceProvider.GetRequiredService(); - var userId = $"dummy-user-{Guid.NewGuid():N}"; + var isnSettings = serviceScope.ServiceProvider.GetService>().Value; + string pkgSourceUrl = isnSettings.ExternalUrl + "/" + Constants.APIPrefix + "index.json"; + using var client = new HttpClient(); + var response = client.GetAsync(pkgSourceUrl).GetAwaiter().GetResult(); + var body = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); - await ResetDummyPackageStateAsync(serviceScope.ServiceProvider, dbContext); - - dbContext.Users.Add(new ApplicationUser - { - Id = userId, - UserName = userId, - NormalizedUserName = userId.ToUpperInvariant(), - Email = $"{userId}@tests.local", - NormalizedEmail = $"{userId}@tests.local".ToUpperInvariant(), - EmailConfirmed = true - }); - - dbContext.ApiKeys.Add(new ApiKey - { - Id = apiKeyValue, - UserId = userId, - Name = "dummy-key", - CreationDate = DateTime.UtcNow, - ValidityPeriodInDays = 30 - }); - - await dbContext.SaveChangesAsync(); + Assert.True(response.IsSuccessStatusCode, $"Expected {pkgSourceUrl} to be reachable but got {(int)response.StatusCode} {response.ReasonPhrase}"); + Assert.False(string.IsNullOrWhiteSpace(body)); } - - await PushPackageAsync(packagePath, apiKeyValue); - await AssertRegistrationContainsPushedVersionAsync(DummyPackageId, DummyPackageVersion); - await AssertAutocompleteContainsPushedVersionAsync(DummyPackageId, DummyPackageVersion); } [Fact] public void TestRegistrationV3Resource() { - using var serviceScope = server.Host.Services.CreateScope(); - var isnSettings = serviceScope.ServiceProvider.GetService>().Value; + using (var serviceScope = server.Host.Services.CreateScope()) + { var isnSettings = serviceScope.ServiceProvider.GetService>().Value; string pkgSourceUrl = isnSettings.ExternalUrl + "/pkgs/index.json"; - var throttle = new NullThrottle(); + NullThrottle throttle = new NullThrottle(); - var packageSource = new PackageSource(pkgSourceUrl); - var client = new HttpSource(packageSource, PkgSourceMessageHandler, throttle); - _ = new RegistrationResourceV3(client, new Uri(isnSettings.ExternalUrl + "/v3.4.0//registration")); + PackageSource packageSource = new PackageSource(pkgSourceUrl); + HttpSource client = new HttpSource(packageSource, PkgSourceMessageHandler, throttle); + NuGet.Protocol.RegistrationResourceV3 res = new NuGet.Protocol.RegistrationResourceV3(client , + new Uri(isnSettings.ExternalUrl + "/v3.4.0//registration")); + } } - + [Fact] public void TrueTestRegistrationV3Resource() { - using var serviceScope = server.Host.Services.CreateScope(); - var isnSettings = serviceScope.ServiceProvider.GetService>().Value; + using (var serviceScope = server.Host.Services.CreateScope()) + { + var isnSettings = serviceScope.ServiceProvider.GetService>().Value; string pkgSourceUrl = isnSettings.ExternalUrl + "/pkgs/index.json"; var prov = new RegistrationResourceV3Provider(); var source = new PackageSource(pkgSourceUrl); - var repo = new SourceRepository(source, new INuGetResourceProvider[] { prov }); + var repo = new SourceRepository(source, new INuGetResourceProvider[]{ prov }); prov.TryCreate(repo, CancellationToken.None); + + } } private Task PkgSourceMessageHandler() @@ -199,103 +142,6 @@ namespace isnd.host.tests throw new NotImplementedException(); } - private string GetServerBaseUrl() - { - var address = server.Addresses.FirstOrDefault(); - Assert.False(string.IsNullOrWhiteSpace(address), "No listening address was captured from WebServerFixture."); - return address.TrimEnd('/'); - } - - private string GetDummyArtifactPath() - { - var root = FindRepoRoot(); - return Path.Combine(root, DummyArtifactRelativePath); - } - - private static string FindRepoRoot() - { - var dir = new DirectoryInfo(AppContext.BaseDirectory); - while (dir != null) - { - if (File.Exists(Path.Combine(dir.FullName, "isn.sln"))) - { - return dir.FullName; - } - - dir = dir.Parent; - } - - throw new DirectoryNotFoundException("Could not locate repository root from AppContext.BaseDirectory."); - } - - private static async Task ResetDummyPackageStateAsync(IServiceProvider serviceProvider, ApplicationDbContext dbContext) - { - var settings = serviceProvider.GetRequiredService>().Value; - var versions = dbContext.PackageVersions.Where(v => v.PackageId == DummyPackageId); - var packages = dbContext.Packages.Where(p => p.Id == DummyPackageId); - - dbContext.PackageVersions.RemoveRange(versions); - dbContext.Packages.RemoveRange(packages); - await dbContext.SaveChangesAsync(); - - var packageRootDir = settings.PackagesRootDir; - if (!Path.IsPathRooted(packageRootDir)) - { - packageRootDir = Path.Combine(FindRepoRoot(), packageRootDir); - } - - var packageOnDiskPath = Path.Combine(packageRootDir, DummyPackageId); - if (Directory.Exists(packageOnDiskPath)) - { - Directory.Delete(packageOnDiskPath, recursive: true); - } - } - - private async Task PushPackageAsync(string packagePath, string apiKey) - { - using var client = new HttpClient { BaseAddress = new Uri(GetServerBaseUrl()) }; - using var request = new HttpRequestMessage(HttpMethod.Put, $"/{Constants.APIPrefix}{isnd.Entities.ApiConfig.Publish}"); - using var multipart = new MultipartFormDataContent(); - await using var packageStream = File.OpenRead(packagePath); - using var packageContent = new StreamContent(packageStream); - - packageContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); - multipart.Add(packageContent, "package", Path.GetFileName(packagePath)); - request.Content = multipart; - request.Headers.Add("X-NuGet-ApiKey", apiKey); - request.Headers.Add("X-NuGet-Client-Version", "6.11.1"); - - var response = await client.SendAsync(request); - var responseBody = await response.Content.ReadAsStringAsync(); - Assert.True(response.IsSuccessStatusCode, - $"Expected push to succeed but got {(int)response.StatusCode} {response.ReasonPhrase}. Body: {responseBody}"); - } - - private async Task AssertRegistrationContainsPushedVersionAsync(string packageId, string packageVersion) - { - using var client = new HttpClient { BaseAddress = new Uri(GetServerBaseUrl()) }; - var lowerId = packageId.ToLowerInvariant(); - var route = $"/{Constants.APIPrefix}v3.4.0/{isnd.Entities.ApiConfig.Registration}/{lowerId}/index.json"; - var response = await client.GetAsync(route); - var body = await response.Content.ReadAsStringAsync(); - - Assert.True(response.IsSuccessStatusCode, - $"Expected registration endpoint to succeed but got {(int)response.StatusCode} {response.ReasonPhrase}. Body: {body}"); - Assert.Contains(packageVersion, body, StringComparison.OrdinalIgnoreCase); - } - - private async Task AssertAutocompleteContainsPushedVersionAsync(string packageId, string packageVersion) - { - using var client = new HttpClient { BaseAddress = new Uri(GetServerBaseUrl()) }; - var route = $"/{Constants.APIPrefix}{isnd.Entities.ApiConfig.AutoComplete}?id={packageId}&semVerLevel=3.0.0&prerelease=true"; - var response = await client.GetAsync(route); - var body = await response.Content.ReadAsStringAsync(); - - Assert.True(response.IsSuccessStatusCode, - $"Expected autocomplete endpoint to succeed but got {(int)response.StatusCode} {response.ReasonPhrase}. Body: {body}"); - Assert.Contains(packageVersion, body, StringComparison.OrdinalIgnoreCase); - } - private sealed class ThrowingProtector : IDataProtector { public byte[] Protect(byte[] plaintext) => throw new CryptographicException("unexpected protect call");