Skip to content

Commit 66fb4b9

Browse files
Test snippets using pexpect
`jupyter console` isn't designed for batch execution, some CLI emulation is needed
1 parent 923d637 commit 66fb4b9

4 files changed

Lines changed: 42 additions & 33 deletions

File tree

jjava-distro/src/test/java/org/dflib/jjava/distro/ContainerizedKernelCase.java

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import java.io.IOException;
1515
import java.time.Duration;
1616
import java.util.ArrayList;
17-
import java.util.Base64;
1817
import java.util.Collections;
1918
import java.util.List;
2019
import java.util.Map;
@@ -35,7 +34,6 @@ public abstract class ContainerizedKernelCase {
3534
private static final String FS_KERNELSPEC = "../kernelspec/java";
3635
private static final String FS_RESOURCES = "src/test/resources";
3736

38-
private static final Duration KERNEL_EXECUTION_TIMEOUT = Duration.ofMinutes(1);
3937
private static final String TESTS_ENABLED_PROPERTY = "docker.tests.enabled";
4038

4139
@BeforeAll
@@ -63,16 +61,28 @@ protected static Container.ExecResult executeInKernel(String snippet) throws IOE
6361
}
6462

6563
protected static Container.ExecResult executeInKernel(String snippet, Map<String, String> env) throws IOException, InterruptedException {
66-
String snippetEOL = snippet + "\n";
67-
String snippet64 = Base64.getEncoder().encodeToString(snippetEOL.getBytes());
68-
String jupyterCommand = venvCommand("jupyter console --kernel=java --simple-prompt --no-confirm-exit -y");
69-
String[] containerCommand = new String[]{
70-
"timeout",
71-
String.valueOf(KERNEL_EXECUTION_TIMEOUT.getSeconds()),
72-
"bash",
73-
"-c",
74-
"echo \"" + snippet64 + "\" | base64 -d | " + jupyterCommand
75-
};
64+
StringBuilder snippetLines = new StringBuilder();
65+
for (String line : snippet.split("\n")) {
66+
String lineEscaped = line.replace("\\", "\\\\").replace("\"", "\\\"");
67+
snippetLines.append("p.sendline(\"").append(lineEscaped).append("\")\n");
68+
snippetLines.append("p.expect(r'In \\[\\d+\\]:')\n");
69+
}
70+
71+
String pexpectScript = String.join("\n",
72+
"import pexpect,sys,os,time",
73+
"p=pexpect.spawn('" + venvCommand("jupyter") + "',"
74+
+ "['console','--kernel=java','--no-confirm-exit','--simple-prompt'],"
75+
+ "env=os.environ,timeout=60,encoding='utf-8')",
76+
"p.logfile=sys.stdout",
77+
"p.expect(r'In \\[\\d+\\]:',timeout=10)",
78+
snippetLines.toString(),
79+
"p.logfile.flush()",
80+
"time.sleep(0.1)",
81+
"p.sendeof()",
82+
"p.expect(pexpect.EOF,timeout=5)",
83+
"p.close()"
84+
);
85+
String[] containerCommand = new String[]{venvCommand("python"), "-c", pexpectScript};
7686
Container.ExecResult execResult = container.execInContainer(ExecConfig.builder()
7787
.envVars(env)
7888
.command(containerCommand)
@@ -82,7 +92,6 @@ protected static Container.ExecResult executeInKernel(String snippet, Map<String
8292
LOGGER.info("env = {}", env);
8393
LOGGER.info("snippet = {}", snippet);
8494
LOGGER.info("exitCode = {}", execResult.getExitCode());
85-
LOGGER.debug("stderr = {}", execResult.getStderr());
8695
LOGGER.debug("stdout = {}", execResult.getStdout());
8796
return execResult;
8897
}
@@ -108,7 +117,7 @@ private static String getStartupCommand() {
108117
"apt-get update",
109118
"apt-get install --no-install-recommends -y python3 python3-pip python3-venv curl",
110119
"python3 -m venv ./venv",
111-
venvCommand("pip install jupyter-console --progress-bar off"),
120+
venvCommand("pip install jupyter-console pexpect --progress-bar off"),
112121
"tail -f /dev/null"
113122
);
114123
}

jjava-distro/src/test/java/org/dflib/jjava/distro/KernelEnvIT.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ void compilerOpts() throws Exception {
1818
String snippet = "var value = 1;";
1919
Container.ExecResult snippetResult = executeInKernel(snippet, env);
2020

21-
assertThat(snippetResult.getStderr(), CoreMatchers.allOf(
21+
assertThat(snippetResult.getStdout(), CoreMatchers.allOf(
2222
containsString("| var value = 1;"),
2323
containsString(Runtime.version().feature() == 11
2424
? "'var' is a restricted local variable type"
@@ -32,7 +32,7 @@ void timeout() throws Exception {
3232
String snippet = "Thread.sleep(5000);";
3333
Container.ExecResult snippetResult = executeInKernel(snippet, env);
3434

35-
assertThat(snippetResult.getStderr(), CoreMatchers.allOf(
35+
assertThat(snippetResult.getStdout(), CoreMatchers.allOf(
3636
containsString("| " + snippet),
3737
containsString("Evaluation timed out after 3000 milliseconds.")
3838
));
@@ -41,13 +41,13 @@ void timeout() throws Exception {
4141
@Test
4242
void classpath() throws Exception {
4343
Map<String, String> env = Map.of(Env.JJAVA_CLASSPATH, TEST_CLASSPATH);
44-
String snippet = String.join("; ",
45-
"import org.dflib.jjava.Dummy",
46-
"Dummy.class.getName()"
44+
String snippet = String.join("\n",
45+
"import org.dflib.jjava.Dummy;",
46+
"Dummy.class.getName();"
4747
);
4848
Container.ExecResult snippetResult = executeInKernel(snippet, env);
4949

50-
assertThat(snippetResult.getStderr(), not(containsString("|")));
50+
assertThat(snippetResult.getStdout(), not(containsString("|")));
5151
assertThat(snippetResult.getStdout(), containsString("org.dflib.jjava.Dummy"));
5252
}
5353

@@ -57,7 +57,7 @@ void startUpScriptsPath() throws Exception {
5757
String snippet = "ping()";
5858
Container.ExecResult snippetResult = executeInKernel(snippet, env);
5959

60-
assertThat(snippetResult.getStderr(), not(containsString("|")));
60+
assertThat(snippetResult.getStdout(), not(containsString("|")));
6161
assertThat(snippetResult.getStdout(), containsString("pong!"));
6262
}
6363

@@ -67,7 +67,7 @@ void startUpScript() throws Exception {
6767
String snippet = "ping()";
6868
Container.ExecResult snippetResult = executeInKernel(snippet, env);
6969

70-
assertThat(snippetResult.getStderr(), not(containsString("|")));
70+
assertThat(snippetResult.getStdout(), not(containsString("|")));
7171
assertThat(snippetResult.getStdout(), containsString("pong!"));
7272
}
7373

@@ -76,7 +76,7 @@ void loadExtensions_Default() throws Exception {
7676
String snippet = "printf(\"Hello, %s!\", \"world\");";
7777
Container.ExecResult snippetResult = executeInKernel(snippet);
7878

79-
assertThat(snippetResult.getStderr(), not(containsString("|")));
79+
assertThat(snippetResult.getStdout(), not(containsString("|")));
8080
assertThat(snippetResult.getStdout(), containsString("Hello, world!"));
8181
}
8282

@@ -86,7 +86,7 @@ void loadExtensions_Disable() throws Exception {
8686
String snippet = "printf(\"Hello, %s!\", \"world\");";
8787
Container.ExecResult snippetResult = executeInKernel(snippet, env);
8888

89-
assertThat(snippetResult.getStderr(), CoreMatchers.allOf(
89+
assertThat(snippetResult.getStdout(), CoreMatchers.allOf(
9090
containsString("| " + snippet),
9191
containsString("cannot find symbol")
9292
));
@@ -98,7 +98,7 @@ void jvmOpts() throws Exception {
9898
String snippet = "Runtime.getRuntime().maxMemory()";
9999
Container.ExecResult snippetResult = executeInKernel(snippet, env);
100100

101-
assertThat(snippetResult.getStderr(), not(containsString("|")));
101+
assertThat(snippetResult.getStdout(), not(containsString("|")));
102102
assertThat(snippetResult.getStdout(), containsString(String.valueOf(300 * (int) Math.pow(1024, 2))));
103103
}
104104
}

jjava-distro/src/test/java/org/dflib/jjava/distro/KernelMagicIT.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ void jars() throws Exception {
1919
"https://repo1.maven.org/maven2/jakarta/annotation/jakarta.annotation-api/3.0.0/jakarta.annotation-api-3.0.0.jar",
2020
"-o", jar
2121
);
22-
assertEquals(0, fetchResult.getExitCode(), fetchResult.getStdout() + "\n" + fetchResult.getStderr());
22+
assertEquals(0, fetchResult.getExitCode(), fetchResult.getStdout());
2323

2424
String snippet = String.join("\n",
2525
"%jars " + jar,
@@ -28,7 +28,7 @@ void jars() throws Exception {
2828
);
2929
Container.ExecResult snippetResult = executeInKernel(snippet);
3030

31-
assertThat(snippetResult.getStderr(), not(containsString("|")));
31+
assertThat(snippetResult.getStdout(), not(containsString("|")));
3232
assertThat(snippetResult.getStdout(), containsString("jakarta.annotation.Nullable"));
3333
}
3434

@@ -41,7 +41,7 @@ void classpath() throws Exception {
4141
);
4242
Container.ExecResult snippetResult = executeInKernel(snippet);
4343

44-
assertThat(snippetResult.getStderr(), not(containsString("|")));
44+
assertThat(snippetResult.getStdout(), not(containsString("|")));
4545
assertThat(snippetResult.getStdout(), containsString("org.dflib.jjava.Dummy"));
4646
}
4747

@@ -53,7 +53,7 @@ void maven() throws Exception {
5353
);
5454
Container.ExecResult snippetResult = executeInKernel(snippet);
5555

56-
assertThat(snippetResult.getStderr(), not(containsString("|")));
56+
assertThat(snippetResult.getStdout(), not(containsString("|")));
5757
assertThat(snippetResult.getStdout(), containsString("dflib-jupyter-1.0.0-RC1.jar"));
5858
}
5959

@@ -67,7 +67,7 @@ void mavenIvySyntax() throws Exception {
6767

6868
Container.ExecResult snippetResult = executeInKernel(snippet);
6969

70-
assertThat(snippetResult.getStderr(), not(containsString("|")));
70+
assertThat(snippetResult.getStdout(), not(containsString("|")));
7171
assertThat(snippetResult.getStdout(), containsString("jakarta.annotation-api-3.0.0.jar"));
7272
}
7373

@@ -80,7 +80,7 @@ void load() throws Exception {
8080
);
8181
Container.ExecResult snippetResult = executeInKernel(snippet);
8282

83-
assertThat(snippetResult.getStderr(), not(containsString("|")));
83+
assertThat(snippetResult.getStdout(), not(containsString("|")));
8484
assertThat(snippetResult.getStdout(), containsString("pong!"));
8585
}
8686

@@ -94,7 +94,7 @@ void loadFromPOM() throws Exception {
9494
);
9595
Container.ExecResult snippetResult = executeInKernel(snippet);
9696

97-
assertThat(snippetResult.getStderr(), not(containsString("|")));
97+
assertThat(snippetResult.getStdout(), not(containsString("|")));
9898
assertThat(snippetResult.getStdout(), containsString("jakarta.annotation.Nullable"));
9999
}
100100
}

jjava-distro/src/test/java/org/dflib/jjava/distro/KernelStartupIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ void startUp() throws Exception {
1414
String snippet = "1000d + 1";
1515
Container.ExecResult snippetResult = executeInKernel(snippet);
1616

17-
assertThat(snippetResult.getStderr(), not(containsString("|")));
17+
assertThat(snippetResult.getStdout(), not(containsString("|")));
1818
assertThat(snippetResult.getStdout(), containsString("1001.0"));
1919
}
2020
}

0 commit comments

Comments
 (0)