Skip to content

Commit

Permalink
add unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Patrick Pan <[email protected]>
  • Loading branch information
Patrick Pan committed Nov 19, 2024
1 parent 846e173 commit 7fca0cb
Show file tree
Hide file tree
Showing 10 changed files with 2,378 additions and 114 deletions.
26 changes: 0 additions & 26 deletions src/OrasProject.Oras/Oci/Artifact.cs

This file was deleted.

13 changes: 0 additions & 13 deletions src/OrasProject.Oras/Registry/Remote/Auth/Client.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ namespace OrasProject.Oras.Registry.Remote;
internal static class HttpResponseMessageExtensions
{
private const string _dockerContentDigestHeader = "Docker-Content-Digest";

/// <summary>
/// Parses the error returned by the remote registry.
/// </summary>
Expand Down
6 changes: 2 additions & 4 deletions src/OrasProject.Oras/Registry/Remote/ManifestStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,8 @@ public async Task<bool> ExistsAsync(Descriptor target, CancellationToken cancell
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task PushAsync(Descriptor expected, Stream content, CancellationToken cancellationToken = default)
{
await PushWithIndexingAsync(expected, content, expected.Digest, cancellationToken).ConfigureAwait(false);
}
=> await PushWithIndexingAsync(expected, content, expected.Digest, cancellationToken).ConfigureAwait(false);


/// <summary>
/// PushReferenceASync pushes the manifest with a reference tag.
Expand Down Expand Up @@ -328,7 +327,6 @@ private async Task InternalPushAsync(Descriptor expected, Stream stream, string
request.Content = new StreamContent(stream);
request.Content.Headers.ContentLength = expected.Size;
request.Content.Headers.Add("Content-Type", expected.MediaType);

var client = Repository.Options.HttpClient;
using var response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
if (response.StatusCode != HttpStatusCode.Created)
Expand Down
15 changes: 14 additions & 1 deletion tests/OrasProject.Oras.Tests/Oci/IndexTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
using System.Text.Json;
// Copyright The ORAS Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Text.Json;
using OrasProject.Oras.Content;
using OrasProject.Oras.Oci;
using static OrasProject.Oras.Tests.Remote.Util.Util;
Expand Down
133 changes: 68 additions & 65 deletions tests/OrasProject.Oras.Tests/Remote/ManifestStoreTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
using System.Net;
// Copyright The ORAS Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Net;
using System.Text;
using System.Text.Json;
using OrasProject.Oras.Oci;
Expand All @@ -8,77 +21,13 @@
using static OrasProject.Oras.Tests.Remote.Util.Util;
using static OrasProject.Oras.Content.Digest;
using Index = OrasProject.Oras.Oci.Index;


using Xunit;
using Xunit.Abstractions;

namespace OrasProject.Oras.Tests.Remote;

public class ManifestStoreTest
{
private const string _dockerContentDigestHeader = "Docker-Content-Digest";

private ITestOutputHelper _output;

public ManifestStoreTest(ITestOutputHelper output)
{
_output = output;
}

/// <summary>
/// ManifestStore_PushAsyncWithSubjectAndReferrerSupported tests PushAsync method for pushing manifest with subject when registry supports referrers API
/// </summary>
[Fact]
public async Task ManifestStore_PushAsyncWithSubjectAndReferrerSupported()
{
var (_, manifestBytes) = RandomManifestWithSubject();
var manifestDesc = new Descriptor
{
MediaType = MediaType.ImageManifest,
Digest = ComputeSHA256(manifestBytes),
Size = manifestBytes.Length
};
byte[]? receivedManifest = null;

var mockHttpRequestHandler = async (HttpRequestMessage req, CancellationToken cancellationToken) =>
{
var res = new HttpResponseMessage();
res.RequestMessage = req;
if (req.Method == HttpMethod.Put && req.RequestUri?.AbsolutePath == $"/v2/test/manifests/{manifestDesc.Digest}")
{
if (req.Headers.TryGetValues("Content-Type", out IEnumerable<string>? values) && !values.Contains(MediaType.ImageManifest))
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
if (req.Content?.Headers?.ContentLength != null)
{
var buf = new byte[req.Content.Headers.ContentLength.Value];
(await req.Content.ReadAsByteArrayAsync(cancellationToken)).CopyTo(buf, 0);
receivedManifest = buf;
}
res.Headers.Add(_dockerContentDigestHeader, new string[] { manifestDesc.Digest });
res.StatusCode = HttpStatusCode.Created;
res.Headers.Add("OCI-Subject", "test");
return res;
}
return new HttpResponseMessage(HttpStatusCode.Forbidden);
};


var repo = new Repository(new RepositoryOptions()
{
Reference = Reference.Parse("localhost:5000/test"),
HttpClient = CustomClient(mockHttpRequestHandler),
PlainHttp = true,
});
var cancellationToken = new CancellationToken();
var store = new ManifestStore(repo);
Assert.Equal(Referrers.ReferrerState.ReferrerUnknown, repo.ReferrerState);
await store.PushAsync(manifestDesc, new MemoryStream(manifestBytes), cancellationToken);
Assert.Equal(manifestBytes, receivedManifest);
Assert.Equal(Referrers.ReferrerState.ReferrerSupported, repo.ReferrerState);
}

[Fact]
public async Task ManifestStore_PullReferrersIndexListSuccessfully()
Expand Down Expand Up @@ -155,6 +104,60 @@ public async Task ManifestStore_PullReferrersIndexListNotFound()
Assert.Empty(receivedManifests);
}

/// <summary>
/// ManifestStore_PushAsyncWithSubjectAndReferrerSupported tests PushAsync method for pushing manifest with subject when registry supports referrers API
/// </summary>
[Fact]
public async Task ManifestStore_PushAsyncWithSubjectAndReferrerSupported()
{
var (_, manifestBytes) = RandomManifestWithSubject();
var manifestDesc = new Descriptor
{
MediaType = MediaType.ImageManifest,
Digest = ComputeSHA256(manifestBytes),
Size = manifestBytes.Length
};
byte[]? receivedManifest = null;

var mockHttpRequestHandler = async (HttpRequestMessage req, CancellationToken cancellationToken) =>
{
var res = new HttpResponseMessage();
res.RequestMessage = req;
if (req.Method == HttpMethod.Put && req.RequestUri?.AbsolutePath == $"/v2/test/manifests/{manifestDesc.Digest}")
{
if (req.Headers.TryGetValues("Content-Type", out IEnumerable<string>? values) && !values.Contains(MediaType.ImageManifest))
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
if (req.Content?.Headers?.ContentLength != null)
{
var buf = new byte[req.Content.Headers.ContentLength.Value];
(await req.Content.ReadAsByteArrayAsync(cancellationToken)).CopyTo(buf, 0);
receivedManifest = buf;
}
res.Headers.Add(_dockerContentDigestHeader, new string[] { manifestDesc.Digest });
res.StatusCode = HttpStatusCode.Created;
res.Headers.Add("OCI-Subject", "test");
return res;
}
return new HttpResponseMessage(HttpStatusCode.Forbidden);
};


var repo = new Repository(new RepositoryOptions()
{
Reference = Reference.Parse("localhost:5000/test"),
HttpClient = CustomClient(mockHttpRequestHandler),
PlainHttp = true,
});
var cancellationToken = new CancellationToken();
var store = new ManifestStore(repo);
Assert.Equal(Referrers.ReferrerState.ReferrerUnknown, repo.ReferrerState);
await store.PushAsync(manifestDesc, new MemoryStream(manifestBytes), cancellationToken);
Assert.Equal(manifestBytes, receivedManifest);
Assert.Equal(Referrers.ReferrerState.ReferrerSupported, repo.ReferrerState);
}


[Fact]
public async Task ManifestStore_PushAsyncWithSubjectAndReferrerNotSupported()
Expand Down
15 changes: 14 additions & 1 deletion tests/OrasProject.Oras.Tests/Remote/ReferrersTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
using OrasProject.Oras.Exceptions;
// Copyright The ORAS Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using OrasProject.Oras.Exceptions;
using OrasProject.Oras.Oci;
using OrasProject.Oras.Registry.Remote;
using static OrasProject.Oras.Tests.Remote.Util.Util;
Expand Down
2,253 changes: 2,252 additions & 1 deletion tests/OrasProject.Oras.Tests/Remote/RepositoryTest.cs

Large diffs are not rendered by default.

15 changes: 14 additions & 1 deletion tests/OrasProject.Oras.Tests/Remote/Util/RandomDataGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
using System.Text;
// Copyright The ORAS Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Text;
using System.Text.Json;
using OrasProject.Oras.Content;
using OrasProject.Oras.Oci;
Expand Down
15 changes: 14 additions & 1 deletion tests/OrasProject.Oras.Tests/Remote/Util/Util.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
using Moq;
// Copyright The ORAS Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Moq;
using Moq.Protected;
using OrasProject.Oras.Oci;

Expand Down

0 comments on commit 7fca0cb

Please sign in to comment.