mirror of
https://github.com/systemd/systemd.git
synced 2026-11-06 05:17:24 +00:00
test-bus-unit-util: verify serialization of individual settings
So far we only checked whether bus_append_unit_property_assignment() accepts or rejects a given assignment. Add test_setting() which also checks what ends up in the message: the property name, the variant signature, and the value, in the compact JSON representation produced by sd_bus_message_dump_json(). Use it on a representative set of settings for the various serialization helpers, in particular for the filter lists which now accept commas as separators.
This commit is contained in:
1 parent
5b578462bc
commit
fd697ce91a
1 file changed
+180
-1
@@ -1,13 +1,17 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-json.h"
|
||||
|
||||
#include "bus-internal.h"
|
||||
#include "bus-unit-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "unit-def.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
#include "unit-def.h"
|
||||
|
||||
static sd_bus *arg_bus = NULL;
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_bus, sd_bus_unrefp);
|
||||
@@ -35,6 +39,57 @@ static void test_transient_settings_one(UnitType type, const char* const* lines)
|
||||
}
|
||||
}
|
||||
|
||||
/* Checks that the assignment is accepted and serialized as the given sequence of (property name, variant
|
||||
* signature, value) triplets, terminated by NULL. The value is the compact JSON representation produced by
|
||||
* sd_bus_message_dump_json(), with double quotes replaced by single quotes for readability (which means
|
||||
* that a value containing an apostrophe cannot be expressed). */
|
||||
static void test_setting_full(UnitType type, const char *assignment, ...) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
sd_json_variant *data;
|
||||
size_t n = 0;
|
||||
va_list ap;
|
||||
|
||||
ASSERT_OK(sd_bus_message_new(arg_bus, &m, SD_BUS_MESSAGE_METHOD_CALL));
|
||||
ASSERT_OK_EQ(bus_append_unit_property_assignment(m, type, assignment), 1);
|
||||
ASSERT_OK(sd_bus_message_seal(m, 1, 0));
|
||||
ASSERT_OK(sd_bus_message_dump_json(m, 0, &v));
|
||||
|
||||
/* The message body is a sequence of (sv) structs, represented in JSON as an array of
|
||||
* [name, {"type": signature, "data": value}] pairs. */
|
||||
ASSERT_NOT_NULL(data = sd_json_variant_by_key(v, "data"));
|
||||
|
||||
va_start(ap, assignment);
|
||||
for (const char *name; (name = va_arg(ap, const char*)); n++) {
|
||||
const char *signature = ASSERT_PTR(va_arg(ap, const char*));
|
||||
const char *expected = ASSERT_PTR(va_arg(ap, const char*));
|
||||
_cleanup_free_ char *s = NULL;
|
||||
sd_json_variant *pair, *variant;
|
||||
|
||||
ASSERT_LT(n, sd_json_variant_elements(data));
|
||||
ASSERT_NOT_NULL(pair = sd_json_variant_by_index(data, n));
|
||||
ASSERT_NOT_NULL(variant = sd_json_variant_by_index(pair, 1));
|
||||
|
||||
ASSERT_OK(sd_json_variant_format(sd_json_variant_by_key(variant, "data"), 0, &s));
|
||||
string_replace_char(s, '"', '\'');
|
||||
|
||||
log_debug("%s → %s %s %s",
|
||||
assignment,
|
||||
sd_json_variant_string(sd_json_variant_by_index(pair, 0)),
|
||||
sd_json_variant_string(sd_json_variant_by_key(variant, "type")),
|
||||
s);
|
||||
|
||||
ASSERT_STREQ(sd_json_variant_string(sd_json_variant_by_index(pair, 0)), name);
|
||||
ASSERT_STREQ(sd_json_variant_string(sd_json_variant_by_key(variant, "type")), signature);
|
||||
ASSERT_STREQ(s, expected);
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
ASSERT_EQ(sd_json_variant_elements(data), n);
|
||||
}
|
||||
|
||||
#define test_setting(type, assignment, ...) test_setting_full(type, assignment, __VA_ARGS__, NULL)
|
||||
|
||||
/* The tests data below is in a format intended to be easy to read and write:
|
||||
* Examples can be plain or prefixed with a negative numeric error code:
|
||||
* - unadorned examples must return 1 (success),
|
||||
@@ -1159,6 +1214,130 @@ TEST(unit_properties) {
|
||||
/* All unit types. */
|
||||
}
|
||||
|
||||
TEST(values_basic) {
|
||||
test_setting(UNIT_SERVICE, "Slice=foo.slice",
|
||||
"Slice", "s", "'foo.slice'");
|
||||
test_setting(UNIT_SERVICE, "MemoryAccounting=yes",
|
||||
"MemoryAccounting", "b", "true");
|
||||
test_setting(UNIT_SERVICE, "MemoryAccounting=0",
|
||||
"MemoryAccounting", "b", "false");
|
||||
test_setting(UNIT_SERVICE, "Nice=-5",
|
||||
"Nice", "i", "-5");
|
||||
test_setting(UNIT_SERVICE, "KillSignal=SIGKILL",
|
||||
"KillSignal", "i", "9");
|
||||
test_setting(UNIT_SERVICE, "RuntimeDirectoryMode=0750",
|
||||
"RuntimeDirectoryMode", "u", "488");
|
||||
test_setting(UNIT_SERVICE, "TimerSlackNSec=1ms",
|
||||
"TimerSlackNSec", "t", "1000000");
|
||||
|
||||
/* Boolean or string, with the "Ex" suffix added or dropped as appropriate */
|
||||
test_setting(UNIT_SERVICE, "PrivateTmp=yes",
|
||||
"PrivateTmp", "b", "true");
|
||||
test_setting(UNIT_SERVICE, "PrivateTmp=disconnected",
|
||||
"PrivateTmpEx", "s", "'disconnected'");
|
||||
test_setting(UNIT_SERVICE, "PrivateTmpEx=no",
|
||||
"PrivateTmp", "b", "false");
|
||||
|
||||
test_setting(UNIT_SERVICE, "Delegate=yes",
|
||||
"Delegate", "b", "true");
|
||||
test_setting(UNIT_SERVICE, "Delegate=cpu memory",
|
||||
"DelegateControllers", "as", "['cpu','memory']");
|
||||
test_setting(UNIT_SERVICE, "CPUAffinity=numa",
|
||||
"CPUAffinityFromNUMA", "b", "true");
|
||||
|
||||
/* Deprecated settings are accepted, but nothing is sent. */
|
||||
test_setting_full(UNIT_SERVICE, "MemoryLimit=1G", NULL);
|
||||
}
|
||||
|
||||
TEST(values_strv) {
|
||||
test_setting(UNIT_SERVICE, "DisableControllers=cpu memory",
|
||||
"DisableControllers", "as", "['cpu','memory']");
|
||||
test_setting(UNIT_SERVICE, "ExecSearchPath=/a:/b /c",
|
||||
"ExecSearchPath", "as", "['/a','/b','/c']");
|
||||
test_setting(UNIT_SERVICE, "Environment=\"A=1 2\" B=\\x41",
|
||||
"Environment", "as", "['A=1 2','B=A']");
|
||||
test_setting(UNIT_SERVICE, "Environment=",
|
||||
"Environment", "as", "[]");
|
||||
}
|
||||
|
||||
TEST(values_time_and_size) {
|
||||
test_setting(UNIT_SERVICE, "MemoryPressureThresholdSec=5min",
|
||||
"MemoryPressureThresholdUSec", "t", "300000000");
|
||||
test_setting(UNIT_SERVICE, "CPUQuotaPeriodSec=",
|
||||
"CPUQuotaPeriodUSec", "t", "18446744073709551615");
|
||||
test_setting(UNIT_SERVICE, "TimeoutSec=1s",
|
||||
"TimeoutStartUSec", "t", "1000000",
|
||||
"TimeoutStopUSec", "t", "1000000");
|
||||
test_setting(UNIT_SOCKET, "ReceiveBuffer=1M",
|
||||
"ReceiveBuffer", "t", "1048576");
|
||||
test_setting(UNIT_SERVICE, "MemoryMax=1G",
|
||||
"MemoryMax", "t", "1073741824");
|
||||
test_setting(UNIT_SERVICE, "MemoryMax=infinity",
|
||||
"MemoryMax", "t", "18446744073709551615");
|
||||
test_setting(UNIT_SERVICE, "MemoryLow=100%",
|
||||
"MemoryLowScale", "u", "4294967295");
|
||||
test_setting(UNIT_SERVICE, "CPUQuota=50%",
|
||||
"CPUQuotaPerSecUSec", "t", "500000");
|
||||
test_setting(UNIT_SERVICE, "ManagedOOMMemoryPressureLimit=100%",
|
||||
"ManagedOOMMemoryPressureLimit", "u", "4294967295");
|
||||
test_setting(UNIT_SERVICE, "LimitNOFILE=1024:4096",
|
||||
"LimitNOFILE", "t", "4096",
|
||||
"LimitNOFILESoft", "t", "1024");
|
||||
test_setting(UNIT_TIMER, "OnBootSec=10s",
|
||||
"TimersMonotonic", "a(st)", "[['OnBootSec',10000000]]");
|
||||
}
|
||||
|
||||
TEST(values_filter_lists) {
|
||||
test_setting(UNIT_SERVICE, "RestrictAddressFamilies=AF_INET AF_INET6",
|
||||
"RestrictAddressFamilies", "(bas)", "[true,['AF_INET','AF_INET6']]");
|
||||
/* Names are passed through verbatim, normalization is done by the manager. */
|
||||
test_setting(UNIT_SERVICE, "RestrictAddressFamilies=INET,INET6,netlink",
|
||||
"RestrictAddressFamilies", "(bas)", "[true,['INET','INET6','netlink']]");
|
||||
test_setting(UNIT_SERVICE, "RestrictAddressFamilies=AF_INET, AF_INET6 ,AF_UNIX",
|
||||
"RestrictAddressFamilies", "(bas)", "[true,['AF_INET','AF_INET6','AF_UNIX']]");
|
||||
test_setting(UNIT_SERVICE, "RestrictAddressFamilies=~AF_NETLINK",
|
||||
"RestrictAddressFamilies", "(bas)", "[false,['AF_NETLINK']]");
|
||||
test_setting(UNIT_SERVICE, "RestrictAddressFamilies=",
|
||||
"RestrictAddressFamilies", "(bas)", "[true,[]]");
|
||||
test_setting(UNIT_SERVICE, "RestrictAddressFamilies=~",
|
||||
"RestrictAddressFamilies", "(bas)", "[false,[]]");
|
||||
|
||||
test_setting(UNIT_SERVICE, "SystemCallFilter=read,write,open,close",
|
||||
"SystemCallFilter", "(bas)", "[true,['read','write','open','close']]");
|
||||
test_setting(UNIT_SERVICE, "SystemCallFilter=~@debug @mount",
|
||||
"SystemCallFilter", "(bas)", "[false,['@debug','@mount']]");
|
||||
test_setting(UNIT_SERVICE, "SystemCallFilter=\"read write\"",
|
||||
"SystemCallFilter", "(bas)", "[true,['read write']]");
|
||||
test_setting(UNIT_SERVICE, "SystemCallLog=@system-service",
|
||||
"SystemCallLog", "(bas)", "[true,['@system-service']]");
|
||||
test_setting(UNIT_SERVICE, "RestrictFileSystems=~tmpfs,ext4",
|
||||
"RestrictFileSystems", "(bas)", "[false,['tmpfs','ext4']]");
|
||||
test_setting(UNIT_SERVICE, "RestrictNetworkInterfaces=~eth0 lo",
|
||||
"RestrictNetworkInterfaces", "(bas)", "[false,['eth0','lo']]");
|
||||
test_setting(UNIT_SERVICE, "RestrictNetworkInterfaces=~iface,wo,comma 'iface,w,comma'",
|
||||
"RestrictNetworkInterfaces", "(bas)", "[false,['iface','wo','comma','iface,w,comma']]");
|
||||
}
|
||||
|
||||
TEST(values_exec) {
|
||||
test_setting(UNIT_SERVICE, "ExecStart=/bin/true a b",
|
||||
"ExecStart", "a(sasb)", "[['/bin/true',['/bin/true','a','b'],false]]");
|
||||
test_setting(UNIT_SERVICE, "ExecStart=-/bin/true",
|
||||
"ExecStart", "a(sasb)", "[['/bin/true',['/bin/true'],true]]");
|
||||
test_setting(UNIT_SERVICE, "ExecStart=:/bin/true",
|
||||
"ExecStartEx", "a(sasas)", "[['/bin/true',['/bin/true'],['no-env-expand']]]");
|
||||
test_setting(UNIT_SERVICE, "ExecStartEx=/bin/true",
|
||||
"ExecStart", "a(sasb)", "[['/bin/true',['/bin/true'],false]]");
|
||||
|
||||
test_setting(UNIT_SERVICE, "StandardInputText=hi",
|
||||
"StandardInputData", "ay", "[104,105,10]");
|
||||
test_setting(UNIT_SERVICE, "LogExtraFields=A=B",
|
||||
"LogExtraFields", "aay", "[[65,61,66]]");
|
||||
test_setting(UNIT_SERVICE, "EnvironmentFile=-/etc/foo",
|
||||
"EnvironmentFiles", "a(sb)", "[['/etc/foo',true]]");
|
||||
test_setting(UNIT_SERVICE, "BindPaths=/a:/b:rbind",
|
||||
"BindPaths", "a(ssbt)", "[['/a','/b',false,16384]]");
|
||||
}
|
||||
|
||||
TEST(bus_dump_transient_settings) {
|
||||
for (UnitType t = 0; t < _UNIT_TYPE_MAX; t++) {
|
||||
log_info("==================== %s ====================", t < 0 ? "unit" : unit_type_to_string(t));
|
||||
|
||||
Reference in new issue
Block a user