Skip to content

Commit

Permalink
libsubprocess/test: cover line buffer overflow
Browse files Browse the repository at this point in the history
Problem: There are no unit tests for when a single line exceeds
the size of an output buffer.

Add unit tests.
  • Loading branch information
chu11 committed Sep 23, 2024
1 parent 6ec4756 commit 93b87e0
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 6 deletions.
13 changes: 7 additions & 6 deletions src/common/libsubprocess/test/iostress.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,13 @@ int main (int argc, char *argv[])
ok (iostress_run_check (h, "balanced", false, 0, 0, 8, 8, 80),
"balanced worked");

// (remote?) stdout buffer is overrun
// Needs further investigation as no errors are thrown and completion is
// not called called after subprocess exit. The doomsday timer stops
// the test.
ok (!iostress_run_check (h, "tinystdout", false, 0, 128, 1, 1, 256),
"tinystdout failed as expected");
// stdout buffer is overrun

// libsubprocess will attempt to get the user to read from the buffer that
// is overrun. So generally speaking, stdout buffer overrun should still
// work.
ok (iostress_run_check (h, "tinystdout", false, 0, 128, 1, 1, 256),
"tinystdout works");

// local stdin buffer is overrun (immediately)
// remote stdin buffer is also overwritten
Expand Down
80 changes: 80 additions & 0 deletions src/common/libsubprocess/test/stdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,84 @@ void test_stream_start_stop_mid_stop (flux_reactor_t *r)
flux_watcher_destroy (tw);
}

void overflow_output_cb (flux_subprocess_t *p, const char *stream)
{
const char *buf = NULL;
int len;

if (strcasecmp (stream, "stdout") != 0) {
ok (false, "unexpected stream %s", stream);
return;
}

/* first callback should return "0123" for 4 byte buffer.
* second callback should return "456\n" in 4 byte buffer
*/
if (stdout_output_cb_count == 0) {
len = flux_subprocess_read_line (p, stream, &buf);
ok (len > 0
&& buf != NULL,
"flux_subprocess_read_line on %s success", stream);

ok (streq (buf, "0123"),
"flux_subprocess_read_line returned correct data");
ok (len == 4,
"flux_subprocess_read_line returned correct data len");
}
else if (stdout_output_cb_count == 1) {
len = flux_subprocess_read_line (p, stream, &buf);
ok (len > 0
&& buf != NULL,
"flux_subprocess_read_line on %s success", stream);

ok (streq (buf, "456\n"),
"flux_subprocess_read_line returned correct data");
ok (len == 4,
"flux_subprocess_read_line returned correct data len");
}
else {
ok (flux_subprocess_read_stream_closed (p, stream),
"flux_subprocess_read_stream_closed saw EOF on %s", stream);

len = flux_subprocess_read (p, stream, &buf);
ok (len == 0,
"flux_subprocess_read on %s read EOF", stream);
}
stdout_output_cb_count++;
}

/* Set buffer size to 4 and have 7 bytes of output (8 including newline) */
void test_overflow_output_buffer (flux_reactor_t *r)
{
char *av[] = { TEST_SUBPROCESS_DIR "test_echo", "-O", "0123456", NULL };
flux_cmd_t *cmd;
flux_subprocess_t *p = NULL;

ok ((cmd = flux_cmd_create (3, av, environ)) != NULL, "flux_cmd_create");

ok (flux_cmd_setopt (cmd, "stdout_BUFSIZE", "4") == 0,
"flux_cmd_setopt set stdout_BUFSIZE success");

flux_subprocess_ops_t ops = {
.on_completion = completion_cb,
.on_stdout = overflow_output_cb
};
completion_cb_count = 0;
stdout_output_cb_count = 0;
p = flux_local_exec (r, 0, cmd, &ops);
ok (p != NULL, "flux_local_exec");

ok (flux_subprocess_state (p) == FLUX_SUBPROCESS_RUNNING,
"subprocess state == RUNNING after flux_local_exec");

int rc = flux_reactor_run (r, 0);
ok (rc == 0, "flux_reactor_run returned zero status");
ok (completion_cb_count == 1, "completion callback called 1 time");
ok (stdout_output_cb_count == 3, "stdout output callback called 3 times");
flux_subprocess_destroy (p);
flux_cmd_destroy (cmd);
}

int main (int argc, char *argv[])
{
flux_reactor_t *r;
Expand Down Expand Up @@ -1395,6 +1473,8 @@ int main (int argc, char *argv[])
test_stream_start_stop_initial_stop (r);
diag ("stream_start_stop_mid_stop");
test_stream_start_stop_mid_stop (r);
diag ("overflow_output_buffer");
test_overflow_output_buffer (r);

end_fdcount = fdcount ();

Expand Down

0 comments on commit 93b87e0

Please sign in to comment.