diff --git a/core/src/main/java/org/testcontainers/containers/ContainerState.java b/core/src/main/java/org/testcontainers/containers/ContainerState.java index b3a38febf73..b289f35f7a3 100644 --- a/core/src/main/java/org/testcontainers/containers/ContainerState.java +++ b/core/src/main/java/org/testcontainers/containers/ContainerState.java @@ -22,14 +22,17 @@ import org.testcontainers.utility.MountableFile; import org.testcontainers.utility.ThrowingFunction; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -345,21 +348,32 @@ default void copyFileToContainer(Transferable transferable, String containerPath throw new IllegalStateException("copyFileToContainer can only be used with created / running container"); } + Path tempFile = Files.createTempFile("tc-", "-copy"); + try ( - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - TarArchiveOutputStream tarArchive = new TarArchiveOutputStream(byteArrayOutputStream) + OutputStream os = Files.newOutputStream(tempFile); + BufferedOutputStream bos = new BufferedOutputStream(os); + TarArchiveOutputStream tarArchive = new TarArchiveOutputStream(bos) ) { tarArchive.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX); tarArchive.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX); transferable.transferTo(tarArchive, containerPath); tarArchive.finish(); - - getDockerClient() - .copyArchiveToContainerCmd(getContainerId()) - .withTarInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())) - .withRemotePath("/") - .exec(); + bos.flush(); + + try ( + InputStream is = Files.newInputStream(tempFile); + BufferedInputStream bis = new BufferedInputStream(is) + ) { + getDockerClient() + .copyArchiveToContainerCmd(getContainerId()) + .withTarInputStream(bis) + .withRemotePath("/") + .exec(); + } + } finally { + Files.deleteIfExists(tempFile); } } diff --git a/core/src/test/java/org/testcontainers/junit/FileOperationsTest.java b/core/src/test/java/org/testcontainers/junit/FileOperationsTest.java index d9655443480..4b3aa804b50 100644 --- a/core/src/test/java/org/testcontainers/junit/FileOperationsTest.java +++ b/core/src/test/java/org/testcontainers/junit/FileOperationsTest.java @@ -3,15 +3,19 @@ import com.github.dockerjava.api.exception.NotFoundException; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; +import org.apache.commons.io.output.CountingOutputStream; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.testcontainers.TestImages; +import org.testcontainers.containers.Container; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; import org.testcontainers.utility.MountableFile; +import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import static org.assertj.core.api.Assertions.assertThat; @@ -40,6 +44,43 @@ public void copyFileToContainerFileTest() throws Exception { } } + @Test + public void copyLargeFilesToContainer() throws Exception { + File tempFile = temporaryFolder.newFile(); + try ( + GenericContainer alpineCopyToContainer = new GenericContainer(TestImages.ALPINE_IMAGE) // + .withCommand("sleep", "infinity") + ) { + alpineCopyToContainer.start(); + final long byteCount; + try ( + FileOutputStream fos = new FileOutputStream(tempFile); + CountingOutputStream cos = new CountingOutputStream(fos); + BufferedOutputStream bos = new BufferedOutputStream(cos) + ) { + for (int i = 0; i < 0x4000; i++) { + byte[] bytes = new byte[0xFFFF]; + bos.write(bytes); + } + bos.flush(); + byteCount = cos.getByteCount(); + } + final MountableFile mountableFile = MountableFile.forHostPath(tempFile.getPath()); + final String containerPath = "/test.bin"; + alpineCopyToContainer.copyFileToContainer(mountableFile, containerPath); + + final Container.ExecResult execResult = alpineCopyToContainer.execInContainer( // + "stat", + "-c", + "%s", + containerPath + ); + assertThat(execResult.getStdout()).isEqualToIgnoringNewLines(Long.toString(byteCount)); + } finally { + tempFile.delete(); + } + } + @Test public void copyFileToContainerFolderTest() throws Exception { try (