diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index f685d19..bf6c50a 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -8,11 +8,15 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: matrix: - java: [ 11, 17, 21 ] + os: [ ubuntu-latest ] + java: [ 11, 17, 21, 25 ] + include: + - os: windows-latest + java: 25 steps: - name: Checkout @@ -26,4 +30,4 @@ jobs: cache: 'maven' - name: Build and test - run: mvn clean verify -U + run: mvn clean verify -U ${{ matrix.os != 'windows-latest' && '-Pdocker' || '' }} diff --git a/jjava-distro/src/test/java/org/dflib/jjava/distro/ContainerizedKernelCase.java b/jjava-distro/src/test/java/org/dflib/jjava/distro/ContainerizedKernelCase.java index 4b66c8c..e560a40 100644 --- a/jjava-distro/src/test/java/org/dflib/jjava/distro/ContainerizedKernelCase.java +++ b/jjava-distro/src/test/java/org/dflib/jjava/distro/ContainerizedKernelCase.java @@ -1,5 +1,6 @@ package org.dflib.jjava.distro; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,10 +14,12 @@ import java.io.IOException; import java.time.Duration; import java.util.ArrayList; -import java.util.Base64; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -24,7 +27,7 @@ public abstract class ContainerizedKernelCase { private static final Logger LOGGER = LoggerFactory.getLogger(ContainerizedKernelCase.class); - protected static final GenericContainer container; + protected static GenericContainer container; protected static final String WORKING_DIRECTORY = "/test"; protected static final String CONTAINER_KERNELSPEC = "/usr/share/jupyter/kernels/java"; protected static final String CONTAINER_RESOURCES = WORKING_DIRECTORY + "/resources"; @@ -34,20 +37,13 @@ public abstract class ContainerizedKernelCase { private static final String FS_KERNELSPEC = "../kernelspec/java"; private static final String FS_RESOURCES = "src/test/resources"; - static { - container = new GenericContainer<>(BASE_IMAGE) - .withWorkingDirectory(WORKING_DIRECTORY) - .withCopyToContainer(MountableFile.forHostPath(FS_KERNELSPEC), CONTAINER_KERNELSPEC) - .withCopyToContainer(MountableFile.forHostPath(FS_RESOURCES), CONTAINER_RESOURCES) - .withCommand("bash", "-c", getStartupCommand()) - .withLogConsumer(new Slf4jLogConsumer(LOGGER)) - .waitingFor(Wait.forSuccessfulCommand(getSuccessfulCommand())) - .withStartupTimeout(Duration.ofMinutes(1)); - container.start(); - } + private static final String TESTS_ENABLED_PROPERTY = "docker.tests.enabled"; @BeforeAll - static void compileSources() throws IOException, InterruptedException { + static void setUp() throws IOException, InterruptedException { + initializeContainer(); + Assumptions.assumeTrue(container != null, "Docker tests are disabled. Enable with -Pdocker"); + String source = "$(find " + CONTAINER_RESOURCES + "/src -name '*.java')"; Container.ExecResult compileResult = executeInContainer("javac -d " + TEST_CLASSPATH + " " + source); @@ -68,9 +64,29 @@ protected static Container.ExecResult executeInKernel(String snippet) throws IOE } protected static Container.ExecResult executeInKernel(String snippet, Map env) throws IOException, InterruptedException { - String snippet64 = Base64.getEncoder().encodeToString(snippet.getBytes()); - String jupyterCommand = venvCommand("jupyter console --kernel=java --simple-prompt"); - String[] containerCommand = new String[]{"bash", "-c", "echo \"" + snippet64 + "\" | base64 -d | " + jupyterCommand}; + long snippetLines = snippet.lines().count(); + String snippetEscaped = snippet.replace("\\", "\\\\").replace("\"", "\\\""); + String snippetFeeding = Arrays.stream(snippetEscaped.split("\n")) + .flatMap(line -> Stream.of( + "p.expect(r'In \\[\\d+\\]:')", + "p.sendline(\"" + line + "\")" + )) + .collect(Collectors.joining("\n")); + + String pexpectScript = String.join("\n", + "import pexpect, sys, os, time", + "env = os.environ.copy()", + "env['PROMPT_TOOLKIT_NO_CPR'] = '1'", + "env['TERM'] = 'dumb'", + "p=pexpect.spawn('" + venvCommand("jupyter") + "', " + + "['console', '--kernel=java', '--no-confirm-exit'], " + + "env=env, timeout=60, encoding='utf-8')", + "p.logfile_read = sys.stdout", + snippetFeeding, + "p.expect(r'In \\[" + (snippetLines + 1) + "\\]:')", + "p.close(force=True)" + ); + String[] containerCommand = new String[]{venvCommand("python"), "-c", pexpectScript}; Container.ExecResult execResult = container.execInContainer(ExecConfig.builder() .envVars(env) .command(containerCommand) @@ -80,17 +96,33 @@ protected static Container.ExecResult executeInKernel(String snippet, Map(BASE_IMAGE) + .withWorkingDirectory(WORKING_DIRECTORY) + .withCopyToContainer(MountableFile.forHostPath(FS_KERNELSPEC), CONTAINER_KERNELSPEC) + .withCopyToContainer(MountableFile.forHostPath(FS_RESOURCES), CONTAINER_RESOURCES) + .withCommand("bash", "-c", getStartupCommand()) + .withLogConsumer(new Slf4jLogConsumer(LOGGER)) + .waitingFor(Wait.forSuccessfulCommand(getSuccessfulCommand())) + .withStartupTimeout(Duration.ofMinutes(1)); + container.start(); + } + private static String getStartupCommand() { return String.join(" && ", "apt-get update", - "apt-get install --no-install-recommends -y python3 python3-pip python3-venv", + "apt-get install --no-install-recommends -y python3 python3-pip python3-venv curl", "python3 -m venv ./venv", - venvCommand("pip install jupyter-console --progress-bar off"), + venvCommand("pip install jupyter-console pexpect --progress-bar off"), "tail -f /dev/null" ); } diff --git a/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelEnvIT.java b/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelEnvIT.java index d7b588a..cd9e855 100644 --- a/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelEnvIT.java +++ b/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelEnvIT.java @@ -1,24 +1,26 @@ package org.dflib.jjava.distro; -import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.Test; import org.testcontainers.containers.Container; import java.util.Map; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.junit.jupiter.api.Assertions.assertEquals; -public class KernelEnvIT extends ContainerizedKernelCase { +class KernelEnvIT extends ContainerizedKernelCase { @Test - public void compilerOpts() throws Exception { + void compilerOpts() throws Exception { Map env = Map.of(Env.JJAVA_COMPILER_OPTS, "-source 9"); String snippet = "var value = 1;"; Container.ExecResult snippetResult = executeInKernel(snippet, env); - assertThat(snippetResult.getStderr(), CoreMatchers.allOf( + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), allOf( containsString("| var value = 1;"), containsString(Runtime.version().feature() == 11 ? "'var' is a restricted local variable type" @@ -27,78 +29,85 @@ public void compilerOpts() throws Exception { } @Test - public void timeout() throws Exception { + void timeout() throws Exception { Map env = Map.of(Env.JJAVA_TIMEOUT, "3000"); String snippet = "Thread.sleep(5000);"; Container.ExecResult snippetResult = executeInKernel(snippet, env); - assertThat(snippetResult.getStderr(), CoreMatchers.allOf( + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), allOf( containsString("| " + snippet), containsString("Evaluation timed out after 3000 milliseconds.") )); } @Test - public void classpath() throws Exception { + void classpath() throws Exception { Map env = Map.of(Env.JJAVA_CLASSPATH, TEST_CLASSPATH); String snippet = String.join("\n", "import org.dflib.jjava.Dummy;", - "Dummy.class.getName()" + "\"className = \" + Dummy.class.getName();" ); Container.ExecResult snippetResult = executeInKernel(snippet, env); - assertThat(snippetResult.getStderr(), not(containsString("|"))); - assertThat(snippetResult.getStdout(), containsString("org.dflib.jjava.Dummy")); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); + assertThat(snippetResult.getStdout(), containsString("className = org.dflib.jjava.Dummy")); } @Test - public void startUpScriptsPath() throws Exception { - Map env = Map.of(Env.JJAVA_STARTUP_SCRIPTS_PATH, CONTAINER_RESOURCES + "/test-ping.jshell"); + void startUpScriptsPath() throws Exception { + Map env = Map.of(Env.JJAVA_STARTUP_SCRIPTS_PATH, CONTAINER_RESOURCES + "/test-ping.jshell"); String snippet = "ping()"; Container.ExecResult snippetResult = executeInKernel(snippet, env); - assertThat(snippetResult.getStderr(), not(containsString("|"))); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); assertThat(snippetResult.getStdout(), containsString("pong!")); } @Test - public void startUpScript() throws Exception { + void startUpScript() throws Exception { Map env = Map.of(Env.JJAVA_STARTUP_SCRIPT, "public String ping() { return \"pong!\"; }"); String snippet = "ping()"; Container.ExecResult snippetResult = executeInKernel(snippet, env); - assertThat(snippetResult.getStderr(), not(containsString("|"))); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); assertThat(snippetResult.getStdout(), containsString("pong!")); } @Test - public void loadExtensions_Default() throws Exception { + void loadExtensions_Default() throws Exception { String snippet = "printf(\"Hello, %s!\", \"world\");"; Container.ExecResult snippetResult = executeInKernel(snippet); - assertThat(snippetResult.getStderr(), not(containsString("|"))); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); assertThat(snippetResult.getStdout(), containsString("Hello, world!")); } @Test - public void loadExtensions_Disable() throws Exception { + void loadExtensions_Disable() throws Exception { Map env = Map.of(Env.JJAVA_LOAD_EXTENSIONS, "0"); String snippet = "printf(\"Hello, %s!\", \"world\");"; Container.ExecResult snippetResult = executeInKernel(snippet, env); - assertThat(snippetResult.getStderr(), CoreMatchers.allOf( + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), allOf( containsString("| " + snippet), containsString("cannot find symbol") )); } @Test - public void jvmOpts() throws Exception { + void jvmOpts() throws Exception { Map env = Map.of(Env.JJAVA_JVM_OPTS, "-Xmx300m"); String snippet = "Runtime.getRuntime().maxMemory()"; Container.ExecResult snippetResult = executeInKernel(snippet, env); - assertThat(snippetResult.getStderr(), not(containsString("|"))); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); assertThat(snippetResult.getStdout(), containsString(String.valueOf(300 * (int) Math.pow(1024, 2)))); } } diff --git a/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelMagicIT.java b/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelMagicIT.java index 37e156c..d08e2f1 100644 --- a/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelMagicIT.java +++ b/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelMagicIT.java @@ -3,23 +3,23 @@ import org.junit.jupiter.api.Test; import org.testcontainers.containers.Container; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertEquals; -public class KernelMagicIT extends ContainerizedKernelCase { +class KernelMagicIT extends ContainerizedKernelCase { @Deprecated @Test - public void jars() throws Exception { + void jars() throws Exception { String jar = CONTAINER_RESOURCES + "/jakarta.annotation-api-3.0.0.jar"; Container.ExecResult fetchResult = container.execInContainer( "curl", "-L", "-s", "-S", "-f", "https://repo1.maven.org/maven2/jakarta/annotation/jakarta.annotation-api/3.0.0/jakarta.annotation-api-3.0.0.jar", "-o", jar ); - assertEquals("", fetchResult.getStderr()); + assertEquals(0, fetchResult.getExitCode(), fetchResult.getStdout()); String snippet = String.join("\n", "%jars " + jar, @@ -28,38 +28,41 @@ public void jars() throws Exception { ); Container.ExecResult snippetResult = executeInKernel(snippet); - assertThat(snippetResult.getStderr(), not(containsString("|"))); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); assertThat(snippetResult.getStdout(), containsString("jakarta.annotation.Nullable")); } @Test - public void classpath() throws Exception { + void classpath() throws Exception { String snippet = String.join("\n", "%classpath " + TEST_CLASSPATH, "import org.dflib.jjava.Dummy;", - "Dummy.class.getName()" + "\"className = \" + Dummy.class.getName();" ); Container.ExecResult snippetResult = executeInKernel(snippet); - assertThat(snippetResult.getStderr(), not(containsString("|"))); - assertThat(snippetResult.getStdout(), containsString("org.dflib.jjava.Dummy")); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); + assertThat(snippetResult.getStdout(), containsString("className = org.dflib.jjava.Dummy")); } @Test - public void maven() throws Exception { + void maven() throws Exception { String snippet = String.join("\n", "%maven org.dflib:dflib-jupyter:1.0.0-RC1", "System.getProperty(\"java.class.path\")" ); Container.ExecResult snippetResult = executeInKernel(snippet); - assertThat(snippetResult.getStderr(), not(containsString("|"))); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); assertThat(snippetResult.getStdout(), containsString("dflib-jupyter-1.0.0-RC1.jar")); } @Deprecated @Test - public void mavenIvySyntax() throws Exception { + void mavenIvySyntax() throws Exception { String snippet = String.join("\n", "%maven jakarta.annotation#jakarta.annotation-api;3.0.0", "System.getProperty(\"java.class.path\")" @@ -67,12 +70,13 @@ public void mavenIvySyntax() throws Exception { Container.ExecResult snippetResult = executeInKernel(snippet); - assertThat(snippetResult.getStderr(), not(containsString("|"))); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); assertThat(snippetResult.getStdout(), containsString("jakarta.annotation-api-3.0.0.jar")); } @Test - public void load() throws Exception { + void load() throws Exception { String script = CONTAINER_RESOURCES + "/test-ping.jshell"; String snippet = String.join("\n", "%load " + script, @@ -80,12 +84,13 @@ public void load() throws Exception { ); Container.ExecResult snippetResult = executeInKernel(snippet); - assertThat(snippetResult.getStderr(), not(containsString("|"))); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); assertThat(snippetResult.getStdout(), containsString("pong!")); } @Test - public void loadFromPOM() throws Exception { + void loadFromPOM() throws Exception { String pom = CONTAINER_RESOURCES + "/test-pom.xml"; String snippet = String.join("\n", "%loadFromPOM " + pom, @@ -94,7 +99,8 @@ public void loadFromPOM() throws Exception { ); Container.ExecResult snippetResult = executeInKernel(snippet); - assertThat(snippetResult.getStderr(), not(containsString("|"))); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); assertThat(snippetResult.getStdout(), containsString("jakarta.annotation.Nullable")); } } diff --git a/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelStartupIT.java b/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelStartupIT.java index a4678a0..f1f9979 100644 --- a/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelStartupIT.java +++ b/jjava-distro/src/test/java/org/dflib/jjava/distro/KernelStartupIT.java @@ -5,19 +5,21 @@ import java.util.Map; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.matchesPattern; +import static org.hamcrest.Matchers.not; +import static org.junit.jupiter.api.Assertions.assertEquals; -public class KernelStartupIT extends ContainerizedKernelCase { +class KernelStartupIT extends ContainerizedKernelCase { @Test - public void startUp() throws Exception { + void startUp() throws Exception { String snippet = "1000d + 1"; Container.ExecResult snippetResult = executeInKernel(snippet); - assertThat(snippetResult.getStderr(), not(containsString("|"))); + assertEquals(0, snippetResult.getExitCode(), snippetResult.getStdout()); + assertThat(snippetResult.getStdout(), not(containsString("|"))); assertThat(snippetResult.getStdout(), containsString("1001.0")); } diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernel.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernel.java index 52e9ee3..99c2053 100644 --- a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernel.java +++ b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernel.java @@ -11,8 +11,8 @@ import org.dflib.jjava.jupyter.kernel.display.common.Url; import org.dflib.jjava.jupyter.kernel.history.HistoryEntry; import org.dflib.jjava.jupyter.kernel.history.HistoryManager; -import org.dflib.jjava.jupyter.kernel.magic.MagicsResolver; import org.dflib.jjava.jupyter.kernel.magic.MagicsRegistry; +import org.dflib.jjava.jupyter.kernel.magic.MagicsResolver; import org.dflib.jjava.jupyter.kernel.util.PathsHandler; import org.dflib.jjava.jupyter.kernel.util.StringStyler; import org.dflib.jjava.jupyter.messages.Header; diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernelBuilder.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernelBuilder.java index f797732..cb57a69 100644 --- a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernelBuilder.java +++ b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/kernel/BaseKernelBuilder.java @@ -5,9 +5,9 @@ import org.dflib.jjava.jupyter.kernel.history.HistoryManager; import org.dflib.jjava.jupyter.kernel.magic.CellMagic; import org.dflib.jjava.jupyter.kernel.magic.LineMagic; -import org.dflib.jjava.jupyter.kernel.magic.MagicsResolver; import org.dflib.jjava.jupyter.kernel.magic.MagicTranspiler; import org.dflib.jjava.jupyter.kernel.magic.MagicsRegistry; +import org.dflib.jjava.jupyter.kernel.magic.MagicsResolver; import org.dflib.jjava.jupyter.kernel.util.StringStyler; import org.dflib.jjava.jupyter.kernel.util.TextColor; diff --git a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/messages/HMACGenerator.java b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/messages/HMACGenerator.java index d57f38e..f0004db 100644 --- a/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/messages/HMACGenerator.java +++ b/jjava-jupyter/src/main/java/org/dflib/jjava/jupyter/messages/HMACGenerator.java @@ -1,7 +1,5 @@ package org.dflib.jjava.jupyter.messages; -import org.dflib.jjava.jupyter.channels.JupyterSocket; - import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; diff --git a/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/util/GlobResolverTest.java b/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/util/GlobResolverTest.java index ff7a55d..cc79c69 100644 --- a/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/util/GlobResolverTest.java +++ b/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/util/GlobResolverTest.java @@ -2,7 +2,6 @@ import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; - import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; diff --git a/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/util/PathsHandlerTest.java b/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/util/PathsHandlerTest.java index 8737d2d..9bbc2e8 100644 --- a/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/util/PathsHandlerTest.java +++ b/jjava-jupyter/src/test/java/org/dflib/jjava/jupyter/kernel/util/PathsHandlerTest.java @@ -9,20 +9,21 @@ import java.nio.file.Path; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; -public class PathsHandlerTest { +class PathsHandlerTest { @Test - public void testSpit() { + void testSpit() { assertEquals(List.of(), PathsHandler.split("")); assertEquals(List.of("a"), PathsHandler.split("a")); assertEquals(List.of("a", "b/c/d"), PathsHandler.split("a" + File.pathSeparator + "b/c/d")); } @Test - public void testSpitAndResolveGlobs(@TempDir Path dir) throws IOException { + void testSpitAndResolveGlobs(@TempDir Path dir) throws IOException { Files.createFile(dir.resolve("a1.txt")); Files.createFile(dir.resolve("a2.txt")); @@ -30,16 +31,29 @@ public void testSpitAndResolveGlobs(@TempDir Path dir) throws IOException { Files.createFile(dir.resolve("b2.txt")); Files.createFile(dir.resolve("c1.txt")); - String basePath = dir + File.separator; + String baseGlob = dir + "/"; // glob resolver only accepts "/" as splitter assertEquals(List.of(), PathsHandler.splitAndResolveGlobs("")); - assertEquals(List.of(), PathsHandler.splitAndResolveGlobs(basePath + "a")); - assertEquals(List.of(), PathsHandler.splitAndResolveGlobs(basePath + "a" + File.pathSeparator + "b/c/d")); + assertEquals(List.of(), PathsHandler.splitAndResolveGlobs(baseGlob + "a")); + assertEquals(List.of(), PathsHandler.splitAndResolveGlobs(baseGlob + "a" + File.pathSeparator + "b/c/d")); - assertEquals(List.of(basePath + "a1.txt", basePath + "a2.txt"), - PathsHandler.splitAndResolveGlobs(basePath + "a*").stream().map(p -> p.toAbsolutePath().toString()).sorted().collect(Collectors.toList())); assertEquals( - List.of(basePath + "a1.txt", basePath + "a2.txt", basePath + "b1.txt", basePath + "b2.txt"), - PathsHandler.splitAndResolveGlobs(basePath + "a*" + File.pathSeparator + basePath + "b*").stream().map(p -> p.toAbsolutePath().toString()).sorted().collect(Collectors.toList())); + List.of(joinPath(dir, "a1.txt"), joinPath(dir, "a2.txt")), + PathsHandler.splitAndResolveGlobs(baseGlob + "a*").stream() + .map(p -> p.toAbsolutePath().toString()) + .sorted() + .collect(Collectors.toList()) + ); + assertEquals( + List.of(joinPath(dir, "a1.txt"), joinPath(dir, "a2.txt"), joinPath(dir, "b1.txt"), joinPath(dir, "b2.txt")), + PathsHandler.splitAndResolveGlobs(baseGlob + "a*" + File.pathSeparator + baseGlob + "b*").stream() + .map(p -> p.toAbsolutePath().toString()) + .sorted() + .collect(Collectors.toList()) + ); + } + + private static String joinPath(Object... elements) { + return Stream.of(elements).map(String::valueOf).collect(Collectors.joining(File.separator)); } } diff --git a/jjava-kernel/src/main/java/org/dflib/jjava/kernel/JavaKernel.java b/jjava-kernel/src/main/java/org/dflib/jjava/kernel/JavaKernel.java index e740993..5ba0a3d 100644 --- a/jjava-kernel/src/main/java/org/dflib/jjava/kernel/JavaKernel.java +++ b/jjava-kernel/src/main/java/org/dflib/jjava/kernel/JavaKernel.java @@ -16,9 +16,9 @@ import org.dflib.jjava.jupyter.kernel.display.DisplayData; import org.dflib.jjava.jupyter.kernel.display.Renderer; import org.dflib.jjava.jupyter.kernel.history.HistoryManager; -import org.dflib.jjava.jupyter.kernel.magic.MagicsResolver; import org.dflib.jjava.jupyter.kernel.magic.MagicTranspiler; import org.dflib.jjava.jupyter.kernel.magic.MagicsRegistry; +import org.dflib.jjava.jupyter.kernel.magic.MagicsResolver; import org.dflib.jjava.jupyter.kernel.util.CharPredicate; import org.dflib.jjava.jupyter.kernel.util.PathsHandler; import org.dflib.jjava.jupyter.kernel.util.StringStyler; diff --git a/jjava-kernel/src/main/java/org/dflib/jjava/kernel/JavaKernelBuilder.java b/jjava-kernel/src/main/java/org/dflib/jjava/kernel/JavaKernelBuilder.java index 556bf03..c954ef5 100644 --- a/jjava-kernel/src/main/java/org/dflib/jjava/kernel/JavaKernelBuilder.java +++ b/jjava-kernel/src/main/java/org/dflib/jjava/kernel/JavaKernelBuilder.java @@ -3,8 +3,8 @@ import jdk.jshell.JShell; import org.dflib.jjava.jupyter.kernel.BaseKernelBuilder; import org.dflib.jjava.jupyter.kernel.LanguageInfo; -import org.dflib.jjava.jupyter.kernel.magic.MagicsResolver; import org.dflib.jjava.jupyter.kernel.magic.MagicTranspiler; +import org.dflib.jjava.jupyter.kernel.magic.MagicsResolver; import org.dflib.jjava.kernel.execution.CodeEvaluator; import org.dflib.jjava.kernel.execution.JJavaExecutionControlProvider; @@ -96,4 +96,4 @@ protected JJavaExecutionControlProvider buildJShellExecControlProvider(String na ? jShellExecControlProvider : new JJavaExecutionControlProvider(name); } -} \ No newline at end of file +} diff --git a/jjava-kernel/src/main/java/org/dflib/jjava/kernel/magics/LoadCodeMagic.java b/jjava-kernel/src/main/java/org/dflib/jjava/kernel/magics/LoadCodeMagic.java index ed93d06..56680bc 100644 --- a/jjava-kernel/src/main/java/org/dflib/jjava/kernel/magics/LoadCodeMagic.java +++ b/jjava-kernel/src/main/java/org/dflib/jjava/kernel/magics/LoadCodeMagic.java @@ -3,9 +3,9 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.stream.JsonReader; -import org.dflib.jjava.kernel.JavaKernel; import org.dflib.jjava.jupyter.kernel.magic.LineMagic; import org.dflib.jjava.jupyter.kernel.magic.MagicsArgs; +import org.dflib.jjava.kernel.JavaKernel; import java.io.FileNotFoundException; import java.io.Reader; diff --git a/jjava-kernel/src/test/java/org/dflib/jjava/kernel/JavaKernelExtensionsLifecycleTest.java b/jjava-kernel/src/test/java/org/dflib/jjava/kernel/JavaKernelExtensionsLifecycleTest.java index b184cd4..2f2db61 100644 --- a/jjava-kernel/src/test/java/org/dflib/jjava/kernel/JavaKernelExtensionsLifecycleTest.java +++ b/jjava-kernel/src/test/java/org/dflib/jjava/kernel/JavaKernelExtensionsLifecycleTest.java @@ -6,7 +6,8 @@ import java.nio.file.Path; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; public class JavaKernelExtensionsLifecycleTest { diff --git a/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/LoadFromPomLineMagic.java b/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/LoadFromPomLineMagic.java index 5cef635..f2c0915 100644 --- a/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/LoadFromPomLineMagic.java +++ b/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/LoadFromPomLineMagic.java @@ -1,9 +1,9 @@ package org.dflib.jjava.maven.magics; -import org.dflib.jjava.jupyter.kernel.util.PathsHandler; -import org.dflib.jjava.kernel.JavaKernel; import org.dflib.jjava.jupyter.kernel.magic.LineMagic; import org.dflib.jjava.jupyter.kernel.magic.MagicsArgs; +import org.dflib.jjava.jupyter.kernel.util.PathsHandler; +import org.dflib.jjava.kernel.JavaKernel; import org.dflib.jjava.maven.MavenDependencyResolver; import java.io.File; diff --git a/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/MavenMagic.java b/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/MavenMagic.java index 3d98a2d..d7070d3 100644 --- a/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/MavenMagic.java +++ b/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/MavenMagic.java @@ -1,9 +1,9 @@ package org.dflib.jjava.maven.magics; -import org.dflib.jjava.jupyter.kernel.util.PathsHandler; -import org.dflib.jjava.kernel.JavaKernel; import org.dflib.jjava.jupyter.kernel.magic.LineMagic; import org.dflib.jjava.jupyter.kernel.magic.MagicsArgs; +import org.dflib.jjava.jupyter.kernel.util.PathsHandler; +import org.dflib.jjava.kernel.JavaKernel; import org.dflib.jjava.maven.MavenDependencyResolver; import java.util.List; diff --git a/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/MavenRepoMagic.java b/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/MavenRepoMagic.java index 1044385..e7565e3 100644 --- a/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/MavenRepoMagic.java +++ b/jjava-maven/src/main/java/org/dflib/jjava/maven/magics/MavenRepoMagic.java @@ -1,8 +1,8 @@ package org.dflib.jjava.maven.magics; -import org.dflib.jjava.kernel.JavaKernel; import org.dflib.jjava.jupyter.kernel.magic.LineMagic; import org.dflib.jjava.jupyter.kernel.magic.MagicsArgs; +import org.dflib.jjava.kernel.JavaKernel; import org.dflib.jjava.maven.MavenDependencyResolver; import java.util.List; diff --git a/pom.xml b/pom.xml index d556ed2..d143791 100644 --- a/pom.xml +++ b/pom.xml @@ -255,6 +255,11 @@ + + + ${docker.tests.enabled} + + org.apache.maven.plugins @@ -337,5 +342,11 @@ + + docker + + true + +