X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Ftest%2Ftest-util.c;h=80425ca61a3aa176ae7e7564147e756e0f02e732;hb=c2fa048c4a70c8386c6d8fe939e5ea9edecf1e98;hp=9a28ef9eec4a2d73075ab50acf4fec523f31ca73;hpb=0f625d0b87139fc18cd565c9b6da05c53a0eb7ab;p=elogind.git diff --git a/src/test/test-util.c b/src/test/test-util.c index 9a28ef9ee..80425ca61 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "util.h" #include "mkdir.h" @@ -69,6 +71,66 @@ static void test_align_power2(void) { } } +static void test_max(void) { + static const struct { + int a; + int b[CONST_MAX(10, 100)]; + } val1 = { + .a = CONST_MAX(10, 100), + }; + int d = 0; + + assert_cc(sizeof(val1.b) == sizeof(int) * 100); + + /* CONST_MAX returns (void) instead of a value if the passed arguments + * are not of the same type or not constant expressions. */ + assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 10)), int)); + assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 1U)), void)); + + assert_se(val1.a == 100); + assert_se(MAX(++d, 0) == 1); + assert_se(d == 1); + + assert_cc(MAXSIZE(char[3], uint16_t) == 3); + assert_cc(MAXSIZE(char[3], uint32_t) == 4); + assert_cc(MAXSIZE(char, long) == sizeof(long)); + + assert_se(MAX(-5, 5) == 5); + assert_se(MAX(5, 5) == 5); + assert_se(MAX(MAX(1, MAX(2, MAX(3, 4))), 5) == 5); + assert_se(MAX(MAX(1, MAX(2, MAX(3, 2))), 1) == 3); + assert_se(MAX(MIN(1, MIN(2, MIN(3, 4))), 5) == 5); + assert_se(MAX(MAX(1, MIN(2, MIN(3, 2))), 1) == 2); + assert_se(LESS_BY(8, 4) == 4); + assert_se(LESS_BY(8, 8) == 0); + assert_se(LESS_BY(4, 8) == 0); + assert_se(LESS_BY(16, LESS_BY(8, 4)) == 12); + assert_se(LESS_BY(4, LESS_BY(8, 4)) == 0); + assert_se(CLAMP(-5, 0, 1) == 0); + assert_se(CLAMP(5, 0, 1) == 1); + assert_se(CLAMP(5, -10, 1) == 1); + assert_se(CLAMP(5, -10, 10) == 5); + assert_se(CLAMP(CLAMP(0, -10, 10), CLAMP(-5, 10, 20), CLAMP(100, -5, 20)) == 10); +} + +static void test_container_of(void) { + struct mytype { + uint8_t pad1[3]; + uint64_t v1; + uint8_t pad2[2]; + uint32_t v2; + } _packed_ myval = { }; + + assert_cc(sizeof(myval) == 17); + assert_se(container_of(&myval.v1, struct mytype, v1) == &myval); + assert_se(container_of(&myval.v2, struct mytype, v2) == &myval); + assert_se(container_of(&container_of(&myval.v2, + struct mytype, + v2)->v1, + struct mytype, + v1) == &myval); +} + static void test_first_word(void) { assert_se(first_word("Hello", "")); assert_se(first_word("Hello", "Hello")); @@ -191,7 +253,7 @@ static void test_safe_atod(void) { r = safe_atod("0.2244", &d); assert_se(r == 0); - assert_se(abs(d - 0.2244) < 0.000001); + assert_se(fabs(d - 0.2244) < 0.000001); r = safe_atod("0,5", &d); assert_se(r == -EINVAL); @@ -201,24 +263,25 @@ static void test_safe_atod(void) { assert_se(*e == ','); /* Check if this really is locale independent */ - setlocale(LC_NUMERIC, "de_DE.utf8"); + if (setlocale(LC_NUMERIC, "de_DE.utf8")) { - r = safe_atod("0.2244", &d); - assert_se(r == 0); - assert_se(abs(d - 0.2244) < 0.000001); + r = safe_atod("0.2244", &d); + assert_se(r == 0); + assert_se(fabs(d - 0.2244) < 0.000001); - r = safe_atod("0,5", &d); - assert_se(r == -EINVAL); + r = safe_atod("0,5", &d); + assert_se(r == -EINVAL); - errno = 0; - assert_se(abs(strtod("0,5", &e) - 0.5) < 0.00001); + errno = 0; + assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001); + } /* And check again, reset */ - setlocale(LC_NUMERIC, "C"); + assert_se(setlocale(LC_NUMERIC, "C")); r = safe_atod("0.2244", &d); assert_se(r == 0); - assert_se(abs(d - 0.2244) < 0.000001); + assert_se(fabs(d - 0.2244) < 0.000001); r = safe_atod("0,5", &d); assert_se(r == -EINVAL); @@ -311,7 +374,7 @@ static void test_cunescape(void) { } static void test_foreach_word(void) { - char *w, *state; + const char *word, *state; size_t l; int i = 0; const char test[] = "test abc d\te f "; @@ -325,13 +388,12 @@ static void test_foreach_word(void) { NULL }; - FOREACH_WORD(w, l, test, state) { - assert_se(strneq(expected[i++], w, l)); - } + FOREACH_WORD(word, l, test, state) + assert_se(strneq(expected[i++], word, l)); } static void test_foreach_word_quoted(void) { - char *w, *state; + const char *word, *state; size_t l; int i = 0; const char test[] = "test a b c 'd' e '' '' hhh '' '' \"a b c\""; @@ -352,13 +414,14 @@ static void test_foreach_word_quoted(void) { }; printf("<%s>\n", test); - FOREACH_WORD_QUOTED(w, l, test, state) { + FOREACH_WORD_QUOTED(word, l, test, state) { _cleanup_free_ char *t = NULL; - assert_se(t = strndup(w, l)); - assert_se(strneq(expected[i++], w, l)); + assert_se(t = strndup(word, l)); + assert_se(strneq(expected[i++], word, l)); printf("<%s>\n", t); } + assert(isempty(state)); } static void test_default_term_for_tty(void) { @@ -835,7 +898,7 @@ static void test_readlink_and_make_absolute(void) { char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias"; char *r = NULL; - assert(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0); + assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0); assert_se(touch(name) >= 0); assert_se(symlink(name, name_alias) >= 0); @@ -855,11 +918,11 @@ static void test_readlink_and_make_absolute(void) { } static void test_read_one_char(void) { + _cleanup_fclose_ FILE *file = NULL; char r; bool need_nl; char name[] = "/tmp/test-read_one_char.XXXXXX"; - _cleanup_close_ int fd = -1; - FILE *file; + int fd; fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); @@ -906,12 +969,291 @@ static void test_strshorten(void) { assert_se(strlen(strshorten(s, 0)) == 0); } +static void test_strappenda(void) { + char *actual; + + actual = strappenda("", "foo", "bar"); + assert_se(streq(actual, "foobar")); + + actual = strappenda("foo", "bar", "baz"); + assert_se(streq(actual, "foobarbaz")); + + actual = strappenda("foo", "", "bar", "baz"); + assert_se(streq(actual, "foobarbaz")); +} + +static void test_is_symlink(void) { + char name[] = "/tmp/test-is_symlink.XXXXXX"; + char name_link[] = "/tmp/test-is_symlink.link"; + _cleanup_close_ int fd = -1; + + fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + assert_se(fd >= 0); + assert_se(symlink(name, name_link) >= 0); + + assert_se(is_symlink(name) == 0); + assert_se(is_symlink(name_link) == 1); + assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0); + + + unlink(name); + unlink(name_link); +} + +static void test_pid_is_unwaited(void) { + pid_t pid; + + pid = fork(); + assert_se(pid >= 0); + if (pid == 0) { + _exit(EXIT_SUCCESS); + } else { + int status; + + waitpid(pid, &status, 0); + assert_se(!pid_is_unwaited(pid)); + } + assert_se(pid_is_unwaited(getpid())); + assert_se(!pid_is_unwaited(-1)); +} + +static void test_pid_is_alive(void) { + pid_t pid; + + pid = fork(); + assert_se(pid >= 0); + if (pid == 0) { + _exit(EXIT_SUCCESS); + } else { + int status; + + waitpid(pid, &status, 0); + assert_se(!pid_is_alive(pid)); + } + assert_se(pid_is_alive(getpid())); + assert_se(!pid_is_alive(-1)); +} + +static void test_search_and_fopen(void) { + const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL}; + char name[] = "/tmp/test-search_and_fopen.XXXXXX"; + int fd = -1; + int r; + FILE *f; + + fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + assert_se(fd >= 0); + close(fd); + + r = search_and_fopen(basename(name), "r", NULL, dirs, &f); + assert_se(r >= 0); + fclose(f); + + r = search_and_fopen(name, "r", NULL, dirs, &f); + assert_se(r >= 0); + fclose(f); + + r = search_and_fopen(basename(name), "r", "/", dirs, &f); + assert_se(r >= 0); + fclose(f); + + r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f); + assert_se(r < 0); + r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f); + assert_se(r < 0); + + r = unlink(name); + assert_se(r == 0); + + r = search_and_fopen(basename(name), "r", NULL, dirs, &f); + assert_se(r < 0); +} + + +static void test_search_and_fopen_nulstr(void) { + const char dirs[] = "/tmp/foo/bar\0/tmp\0"; + char name[] = "/tmp/test-search_and_fopen.XXXXXX"; + int fd = -1; + int r; + FILE *f; + + fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + assert_se(fd >= 0); + close(fd); + + r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f); + assert_se(r >= 0); + fclose(f); + + r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f); + assert_se(r >= 0); + fclose(f); + + r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f); + assert_se(r < 0); + r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f); + assert_se(r < 0); + + r = unlink(name); + assert_se(r == 0); + + r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f); + assert_se(r < 0); +} + +static void test_glob_exists(void) { + char name[] = "/tmp/test-glob_exists.XXXXXX"; + int fd = -1; + int r; + + fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + assert_se(fd >= 0); + close(fd); + + r = glob_exists("/tmp/test-glob_exists*"); + assert_se(r == 1); + + r = unlink(name); + assert_se(r == 0); + r = glob_exists("/tmp/test-glob_exists*"); + assert_se(r == 0); +} + +static void test_execute_directory(void) { + char name[] = "/tmp/test-execute_directory/script1"; + char name2[] = "/tmp/test-execute_directory/script2"; + char name3[] = "/tmp/test-execute_directory/useless"; + char tempdir[] = "/tmp/test-execute_directory/"; + + assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0); + assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch /tmp/test-execute_directory/it_works") == 0); + assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch /tmp/test-execute_directory/it_works2") == 0); + assert_se(chmod(name, 0755) == 0); + assert_se(chmod(name2, 0755) == 0); + assert_se(touch(name3) >= 0); + + execute_directory(tempdir, NULL, DEFAULT_TIMEOUT_USEC, NULL); + assert_se(access("/tmp/test-execute_directory/it_works", F_OK) >= 0); + assert_se(access("/tmp/test-execute_directory/it_works2", F_OK) >= 0); + + rm_rf_dangerous(tempdir, false, true, false); +} + +static void test_unquote_first_word(void) { + const char *p, *original; + char *t; + + p = original = "foobar waldo"; + assert_se(unquote_first_word(&p, &t) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 7); + + assert_se(unquote_first_word(&p, &t) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(p == original + 12); + + assert_se(unquote_first_word(&p, &t) == 0); + assert_se(!t); + assert_se(p == original + 12); + + p = original = "\"foobar\" \'waldo\'"; + assert_se(unquote_first_word(&p, &t) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 9); + + assert_se(unquote_first_word(&p, &t) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(p == original + 16); + + assert_se(unquote_first_word(&p, &t) == 0); + assert_se(!t); + assert_se(p == original + 16); + + p = original = "\""; + assert_se(unquote_first_word(&p, &t) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\'"; + assert_se(unquote_first_word(&p, &t) == -EINVAL); + assert_se(p == original + 1); + + p = original = "yay\'foo\'bar"; + assert_se(unquote_first_word(&p, &t) > 0); + assert_se(streq(t, "yayfoobar")); + free(t); + assert_se(p == original + 11); + + p = original = " foobar "; + assert_se(unquote_first_word(&p, &t) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 12); +} + +static void test_unquote_many_words(void) { + const char *p, *original; + char *a, *b, *c; + + p = original = "foobar waldi piep"; + assert_se(unquote_many_words(&p, &a, &b, &c, NULL) == 3); + assert_se(p == original + 17); + assert_se(streq_ptr(a, "foobar")); + assert_se(streq_ptr(b, "waldi")); + assert_se(streq_ptr(c, "piep")); + free(a); + free(b); + free(c); + + p = original = "'foobar' wa\"ld\"i "; + assert_se(unquote_many_words(&p, &a, &b, &c, NULL) == 2); + assert_se(p == original + 19); + assert_se(streq_ptr(a, "foobar")); + assert_se(streq_ptr(b, "waldi")); + assert_se(streq_ptr(c, NULL)); + free(a); + free(b); + + p = original = ""; + assert_se(unquote_many_words(&p, &a, &b, &c, NULL) == 0); + assert_se(p == original); + assert_se(streq_ptr(a, NULL)); + assert_se(streq_ptr(b, NULL)); + assert_se(streq_ptr(c, NULL)); + + p = original = " "; + assert_se(unquote_many_words(&p, &a, &b, &c, NULL) == 0); + assert_se(p == original+2); + assert_se(streq_ptr(a, NULL)); + assert_se(streq_ptr(b, NULL)); + assert_se(streq_ptr(c, NULL)); + + p = original = "foobar"; + assert_se(unquote_many_words(&p, NULL) == 0); + assert_se(p == original); + + p = original = "foobar waldi"; + assert_se(unquote_many_words(&p, &a, NULL) == 1); + assert_se(p == original+7); + assert_se(streq_ptr(a, "foobar")); + + p = original = " foobar "; + assert_se(unquote_many_words(&p, &a, NULL) == 1); + assert_se(p == original+15); + assert_se(streq_ptr(a, "foobar")); +} + int main(int argc, char *argv[]) { log_parse_environment(); log_open(); test_streq_ptr(); test_align_power2(); + test_max(); + test_container_of(); test_first_word(); test_close_many(); test_parse_boolean(); @@ -964,6 +1306,16 @@ int main(int argc, char *argv[]) { test_read_one_char(); test_ignore_signals(); test_strshorten(); + test_strappenda(); + test_is_symlink(); + test_pid_is_unwaited(); + test_pid_is_alive(); + test_search_and_fopen(); + test_search_and_fopen_nulstr(); + test_glob_exists(); + test_execute_directory(); + test_unquote_first_word(); + test_unquote_many_words(); return 0; }