Skip to content

Commit

Permalink
Add stream API methods (oras-project#60)
Browse files Browse the repository at this point in the history
Co-authored-by: Valentin Delaye <[email protected]>
Signed-off-by: AayushSaini101 <[email protected]>
  • Loading branch information
2 people authored and AayushSaini101 committed Feb 12, 2025
1 parent 1b06a07 commit 06bb6dc
Showing 1 changed file with 153 additions and 2 deletions.
155 changes: 153 additions & 2 deletions src/test/java/land/oras/RegistryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
import java.nio.file.Path;
import java.util.List;
import java.util.Map;

import land.oras.exception.OrasException;
import java.util.Random;
import land.oras.utils.Const;
import land.oras.utils.DigestUtils;
import land.oras.utils.RegistryContainer;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
Expand Down Expand Up @@ -216,4 +217,154 @@ void testShouldPushCompressedDirectory() throws IOException {
assertEquals(blobDir.getFileName().toString(), annotations.get(Const.ANNOTATION_TITLE));
assertEquals("true", annotations.get(Const.ANNOTATION_ORAS_UNPACK));
}

// Push blob - successfull
// Push blob - failed - when blob already exists
// Push blob - Handles io exception
// Handle large stream content
@Test
void shouldPushAndGetBlobStream() throws IOException {
Registry registry = Registry.Builder.builder()
.withInsecure(true)
.withSkipTlsVerify(true)
.build();
ContainerRef containerRef =
ContainerRef.parse("%s/library/artifact-stream".formatted(this.registry.getRegistry()));

// Create a file with test data to get accurate stream size
Path testFile = Files.createTempFile("test-data-", ".tmp");
String testData = "Hello World Stream Test";
Files.writeString(testFile, testData);
long fileSize = Files.size(testFile);

// Test pushBlobStream using file input stream
Layer layer;
try (InputStream inputStream = Files.newInputStream(testFile)) {
layer = registry.pushBlobStream(containerRef, inputStream, fileSize);

// Verify the digest matches SHA-256 of content
assertEquals(DigestUtils.sha256(testFile), layer.getDigest());
assertEquals(fileSize, layer.getSize());
}

// Test getBlobStream
try (InputStream resultStream = registry.getBlobStream(containerRef.withDigest(layer.getDigest()))) {
String result = new String(resultStream.readAllBytes());
assertEquals(testData, result);
}

// Clean up
Files.delete(testFile);
registry.deleteBlob(containerRef.withDigest(layer.getDigest()));
}

@Test
void shouldHandleExistingBlobInStreamPush() throws IOException {
Registry registry = Registry.Builder.builder()
.withInsecure(true)
.withSkipTlsVerify(true)
.build();
ContainerRef containerRef =
ContainerRef.parse("%s/library/artifact-stream".formatted(this.registry.getRegistry()));

// Create test file
Path testFile = Files.createTempFile("test-data-", ".tmp");
Files.writeString(testFile, "Test Content");
long fileSize = Files.size(testFile);
String expectedDigest = DigestUtils.sha256(testFile);

// First push
Layer firstLayer;
try (InputStream inputStream = Files.newInputStream(testFile)) {
firstLayer = registry.pushBlobStream(containerRef, inputStream, fileSize);
}

// Second push of same content should detect existing blob
Layer secondLayer;
try (InputStream inputStream = Files.newInputStream(testFile)) {
secondLayer = registry.pushBlobStream(containerRef, inputStream, fileSize);
}

// Verify both operations return same digest
assertEquals(expectedDigest, firstLayer.getDigest());
assertEquals(expectedDigest, secondLayer.getDigest());
assertEquals(firstLayer.getSize(), secondLayer.getSize());

// Clean up
Files.delete(testFile);
registry.deleteBlob(containerRef.withDigest(firstLayer.getDigest()));
}

@Test
void shouldHandleIOExceptionInStreamPush() throws IOException {
Registry registry = Registry.Builder.builder()
.withInsecure(true)
.withSkipTlsVerify(true)
.build();
ContainerRef containerRef =
ContainerRef.parse("%s/library/artifact-stream".formatted(this.registry.getRegistry()));

// Create a failing input stream
InputStream failingStream = new InputStream() {
@Override
public int read() throws IOException {
throw new IOException("Simulated IO failure");
}
};

// Verify exception is wrapped in OrasException
OrasException exception =
assertThrows(OrasException.class, () -> registry.pushBlobStream(containerRef, failingStream, 100));
assertEquals("Failed to push blob stream", exception.getMessage());
assertTrue(exception.getCause() instanceof IOException);
}

@Test
void shouldHandleNonExistentBlobInGetStream() {
Registry registry = Registry.Builder.builder()
.withInsecure(true)
.withSkipTlsVerify(true)
.build();
ContainerRef containerRef =
ContainerRef.parse("%s/library/artifact-stream".formatted(this.registry.getRegistry()));

// Try to get non-existent blob
String nonExistentDigest = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";

// Verify it throws OrasException
assertThrows(OrasException.class, () -> registry.getBlobStream(containerRef.withDigest(nonExistentDigest)));
}

@Test
void shouldHandleLargeStreamContent() throws IOException {
Registry registry = Registry.Builder.builder()
.withInsecure(true)
.withSkipTlsVerify(true)
.build();
ContainerRef containerRef =
ContainerRef.parse("%s/library/artifact-stream".formatted(this.registry.getRegistry()));

// Create temp file with 5MB of random data
Path largeFile = Files.createTempFile("large-test-", ".tmp");
byte[] largeData = new byte[5 * 1024 * 1024];
new Random().nextBytes(largeData);
Files.write(largeFile, largeData);
long fileSize = Files.size(largeFile);

// Push large content
Layer layer;
try (InputStream inputStream = Files.newInputStream(largeFile)) {
layer = registry.pushBlobStream(containerRef, inputStream, fileSize);
}

// Verify content with stream
try (InputStream resultStream = registry.getBlobStream(containerRef.withDigest(layer.getDigest()))) {
byte[] result = resultStream.readAllBytes();
Assertions.assertArrayEquals(largeData, result);
}

// Clean up
Files.delete(largeFile);
registry.deleteBlob(containerRef.withDigest(layer.getDigest()));
}
}

0 comments on commit 06bb6dc

Please sign in to comment.