From 9177fa9f2b59502fbd433af88f1173a705b5fb27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 1 Mar 2018 09:30:55 +0100 Subject: [PATCH] basic/cgroup-util: simplify cg_get_keyed_attribute(), add test I didn't like the nested loop where we'd count what we have acquired already, since we should always know that. --- src/basic/cgroup-util.c | 23 ++++++--------------- src/test/test-cgroup-util.c | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 7944785bbf..9c3905e91e 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -2042,7 +2042,7 @@ int cg_get_keyed_attribute( _cleanup_free_ char *filename = NULL, *contents = NULL; _cleanup_fclose_ FILE *f = NULL; const char *p; - size_t n, i; + size_t n, i, n_done = 0; char **v; int r; @@ -2069,42 +2069,31 @@ int cg_get_keyed_attribute( for (p = contents; *p;) { const char *w = NULL; - size_t n_done = 0; - for (i = 0; i < n; i++) { - if (v[i]) - n_done ++; - else { + for (i = 0; i < n; i++) + if (!v[i]) { w = first_word(p, keys[i]); if (w) break; } - } if (w) { - char *c; size_t l; l = strcspn(w, NEWLINE); - c = strndup(w, l); - if (!c) { + v[i] = strndup(w, l); + if (!v[i]) { r = -ENOMEM; goto fail; } - v[i] = c; n_done++; - if (n_done >= n) goto done; p = w + l; - } else { - if (n_done >= n) - goto done; - + } else p += strcspn(p, NEWLINE); - } p += strspn(p, NEWLINE); } diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 2248a30635..c4163fc3a9 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -30,6 +30,7 @@ #include "special.h" #include "stat-util.h" #include "string-util.h" +#include "strv.h" #include "test-helper.h" #include "user-util.h" #include "util.h" @@ -404,6 +405,45 @@ static void test_cg_tests(void) { assert_se(!systemd); } +static void test_cg_get_keyed_attribute(void) { + _cleanup_free_ char *val = NULL; + char *vals3[3] = {}, *vals3a[3] = {}; + int i; + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "no_such_file", STRV_MAKE("no_such_attr"), &val) == -ENOENT); + assert_se(val == NULL); + + if (access("/sys/fs/cgroup/init.scope/cpu.stat", R_OK) < 0) { + log_info_errno(errno, "Skipping most of %s, /init.scope/cpu.stat not accessible: %m", __func__); + return; + } + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("no_such_attr"), &val) == -ENXIO); + assert_se(val == NULL); + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec"), &val) == 0); + log_info("cpu /init.scope cpu.stat [usage_usec] → \"%s\"", val); + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "no_such_attr"), vals3) == -ENXIO); + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "usage_usec"), vals3) == -ENXIO); + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", + STRV_MAKE("usage_usec", "user_usec", "system_usec"), vals3) == 0); + log_info("cpu /init.scope cpu.stat [usage_usec user_usec system_usec] → \"%s\", \"%s\", \"%s\"", + vals3[0], vals3[1], vals3[2]); + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", + STRV_MAKE("system_usec", "user_usec", "usage_usec"), vals3a) == 0); + log_info("cpu /init.scope cpu.stat [system_usec user_usec usage_usec] → \"%s\", \"%s\", \"%s\"", + vals3a[0], vals3a[1], vals3a[2]); + + for (i = 0; i < 3; i++) { + free(vals3[i]); + free(vals3a[i]); + } +} + int main(void) { log_set_max_level(LOG_DEBUG); log_parse_environment(); @@ -429,6 +469,7 @@ int main(void) { test_is_wanted_print(false); /* run twice to test caching */ test_is_wanted(); test_cg_tests(); + test_cg_get_keyed_attribute(); return 0; }