diff --git a/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java b/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java index 53ee8ba5577..52b8d0b0b5e 100644 --- a/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java +++ b/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java @@ -220,7 +220,7 @@ protected void configure() { if (getShmSize() == null) { if (SystemUtils.IS_OS_WINDOWS) { withSharedMemorySize(512 * FileUtils.ONE_MB); - } else { + } else if (getBinds().stream().noneMatch(bind -> "/dev/shm".equals(bind.getVolume().getPath()))) { this.getBinds().add(new Bind("/dev/shm", new Volume("/dev/shm"), AccessMode.rw)); } } diff --git a/modules/selenium/src/main/java/org/testcontainers/selenium/BrowserWebDriverContainer.java b/modules/selenium/src/main/java/org/testcontainers/selenium/BrowserWebDriverContainer.java index 97ac23f5d55..fce30cc5fc5 100644 --- a/modules/selenium/src/main/java/org/testcontainers/selenium/BrowserWebDriverContainer.java +++ b/modules/selenium/src/main/java/org/testcontainers/selenium/BrowserWebDriverContainer.java @@ -164,7 +164,7 @@ protected void configure() { if (getShmSize() == null) { if (SystemUtils.IS_OS_WINDOWS) { withSharedMemorySize(512 * FileUtils.ONE_MB); - } else { + } else if (getBinds().stream().noneMatch(bind -> "/dev/shm".equals(bind.getVolume().getPath()))) { this.getBinds().add(new Bind("/dev/shm", new Volume("/dev/shm"), AccessMode.rw)); } } diff --git a/modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java b/modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java new file mode 100644 index 00000000000..bce998cf53b --- /dev/null +++ b/modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java @@ -0,0 +1,34 @@ +package org.testcontainers.containers; + +import com.github.dockerjava.api.model.Bind; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; +import org.testcontainers.utility.DockerImageName; + +import static org.assertj.core.api.Assertions.assertThat; + +class BrowserWebDriverContainerReuseTest { + + private static final DockerImageName CHROME_IMAGE = DockerImageName.parse("selenium/standalone-chrome:4.13.0"); + + @Test + @DisabledOnOs(OS.WINDOWS) + void configureDoesNotAddDuplicateShmBindOnReuse() { + BrowserWebDriverContainer container = new BrowserWebDriverContainer<>(CHROME_IMAGE); + + // configure() runs on every start(), so a reused container that is started + // more than once must not accumulate duplicate /dev/shm binds (see #11941). + container.configure(); + container.configure(); + + long shmBinds = container + .getBinds() + .stream() + .map(Bind::getVolume) + .filter(volume -> "/dev/shm".equals(volume.getPath())) + .count(); + + assertThat(shmBinds).isEqualTo(1); + } +} diff --git a/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java b/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java new file mode 100644 index 00000000000..dcbcd7409e1 --- /dev/null +++ b/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java @@ -0,0 +1,34 @@ +package org.testcontainers.selenium; + +import com.github.dockerjava.api.model.Bind; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; +import org.testcontainers.utility.DockerImageName; + +import static org.assertj.core.api.Assertions.assertThat; + +class BrowserWebDriverContainerReuseTest { + + private static final DockerImageName CHROME_IMAGE = DockerImageName.parse("selenium/standalone-chrome:4.13.0"); + + @Test + @DisabledOnOs(OS.WINDOWS) + void configureDoesNotAddDuplicateShmBindOnReuse() { + BrowserWebDriverContainer container = new BrowserWebDriverContainer(CHROME_IMAGE); + + // configure() runs on every start(), so a reused container that is started + // more than once must not accumulate duplicate /dev/shm binds (see #11941). + container.configure(); + container.configure(); + + long shmBinds = container + .getBinds() + .stream() + .map(Bind::getVolume) + .filter(volume -> "/dev/shm".equals(volume.getPath())) + .count(); + + assertThat(shmBinds).isEqualTo(1); + } +}