diff options
Diffstat (limited to 'tests/subprocess_tests.c')
-rw-r--r-- | tests/subprocess_tests.c | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/tests/subprocess_tests.c b/tests/subprocess_tests.c new file mode 100644 index 00000000..138c1019 --- /dev/null +++ b/tests/subprocess_tests.c @@ -0,0 +1,185 @@ +/* Copyright 2019 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <stdlib.h> +#include <string.h> + +#include "subprocess.h" +#include "test_common.h" + +#define TEST_STRING "hello world" +#define TEST_STRING_LN TEST_STRING "\n" + +static void test_subprocess_output_to_buffer(void) +{ + char output_buffer[__builtin_strlen(TEST_STRING_LN)]; + + struct subprocess_target output = { + .type = TARGET_BUFFER, + .buffer = { + .buf = output_buffer, + .size = sizeof(output_buffer), + }, + }; + const char *const argv[] = { + "echo", TEST_STRING, NULL + }; + + TEST_EQ(subprocess_run(argv, &subprocess_null, &output, NULL), 0, + "Return value of \"echo 'hello world'\" is 0"); + TEST_EQ(memcmp(output_buffer, TEST_STRING_LN, sizeof(output_buffer)), 0, + "Output is \"hello world\\n\""); + TEST_EQ(output.buffer.bytes_consumed, sizeof(output_buffer), + "The entire output buffer should have been used."); +} + +static void test_subprocess_output_to_buffer_null_terminated(void) +{ + char output_buffer[__builtin_strlen(TEST_STRING_LN) + 1]; + + struct subprocess_target output = { + .type = TARGET_BUFFER_NULL_TERMINATED, + .buffer = { + .buf = output_buffer, + .size = sizeof(output_buffer), + }, + }; + const char *const argv[] = { + "echo", TEST_STRING, NULL + }; + + TEST_EQ(subprocess_run(argv, &subprocess_null, &output, NULL), 0, + "Return value of \"echo 'hello world'\" is 0"); + TEST_STR_EQ(output_buffer, TEST_STRING_LN, + "Output is \"hello world\\n\""); + TEST_EQ(output.buffer.bytes_consumed, sizeof(output_buffer) - 1, + "The entire output buffer should have been used."); +} + +#define TEST_STRING_2 "hello\0world!" + +static void test_subprocess_input_buffer(void) +{ + char input_buffer[sizeof(TEST_STRING_2)]; + char output_buffer[20]; + char error_buffer[20]; + + memcpy(input_buffer, TEST_STRING_2, sizeof(input_buffer)); + + struct subprocess_target input = { + .type = TARGET_BUFFER, + .buffer = { + .buf = input_buffer, + .size = sizeof(input_buffer), + }, + }; + struct subprocess_target output = { + .type = TARGET_BUFFER_NULL_TERMINATED, + .buffer = { + .buf = output_buffer, + .size = sizeof(output_buffer), + }, + }; + struct subprocess_target error = { + .type = TARGET_BUFFER_NULL_TERMINATED, + .buffer = { + .buf = error_buffer, + .size = sizeof(error_buffer), + }, + }; + const char *const argv[] = {"cat", NULL}; + + TEST_EQ(subprocess_run(argv, &input, &output, &error), 0, + "Return value of \"cat\" is 0"); + TEST_EQ(memcmp(output_buffer, TEST_STRING_2, sizeof(TEST_STRING_2)), + 0, "Output is \"hello\\0world!\""); + TEST_STR_EQ(error_buffer, "", "No output captured on stderr"); + TEST_EQ(output.buffer.bytes_consumed, sizeof(TEST_STRING_2), + "Bytes consumed is correct"); + TEST_EQ(error.buffer.bytes_consumed, 0, "No bytes used for error"); +} + +static void test_subprocess_input_null_terminated(void) +{ + char input_buffer[20]; + char output_buffer[20]; + char error_buffer[20]; + + memcpy(input_buffer, TEST_STRING_2, sizeof(TEST_STRING_2)); + + struct subprocess_target input = { + .type = TARGET_BUFFER_NULL_TERMINATED, + .buffer = { + .buf = input_buffer, + }, + }; + struct subprocess_target output = { + .type = TARGET_BUFFER_NULL_TERMINATED, + .buffer = { + .buf = output_buffer, + .size = sizeof(output_buffer), + }, + }; + struct subprocess_target error = { + .type = TARGET_BUFFER_NULL_TERMINATED, + .buffer = { + .buf = error_buffer, + .size = sizeof(error_buffer), + }, + }; + const char *const argv[] = {"cat", NULL}; + + TEST_EQ(subprocess_run(argv, &input, &output, &error), 0, + "Return value of \"cat\" is 0"); + TEST_STR_EQ(output_buffer, "hello", "Output is \"hello\""); + TEST_STR_EQ(error_buffer, "", "No output captured on stderr"); + TEST_EQ(output.buffer.bytes_consumed, 5, "5 bytes used"); + TEST_EQ(error.buffer.bytes_consumed, 0, "No bytes used for error"); +} + +static void test_subprocess_small_output_buffer(void) +{ + char output_buffer[3]; + + struct subprocess_target output = { + .type = TARGET_BUFFER_NULL_TERMINATED, + .buffer = { + .buf = output_buffer, + .size = sizeof(output_buffer), + }, + }; + const char *const argv[] = { + "echo", TEST_STRING, NULL + }; + + TEST_EQ(subprocess_run(argv, &subprocess_null, &output, NULL), 0, + "Return value of \"echo 'hello world'\" is 0"); + TEST_STR_EQ(output_buffer, "he", + "Output is \"he\" (truncated to small buffer)"); + TEST_EQ(output.buffer.bytes_consumed, sizeof(output_buffer) - 1, + "The entire output buffer should have been used."); +} + +static void test_subprocess_return_code_failure(void) +{ + const char *const argv[] = {"false"}; + + TEST_NEQ(subprocess_run(argv, NULL, NULL, NULL), 0, + "Return value of \"false\" is nonzero"); +} + +int main(int argc, char *argv[]) +{ + test_subprocess_output_to_buffer(); + test_subprocess_output_to_buffer_null_terminated(); + test_subprocess_input_buffer(); + test_subprocess_input_null_terminated(); + test_subprocess_small_output_buffer(); + test_subprocess_return_code_failure(); + + if (!gTestSuccess) + return 255; + return 0; +} |