summary refs log tree commit diff
path: root/src/libnm-core-impl/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnm-core-impl/tests')
-rw-r--r--src/libnm-core-impl/tests/meson.build1
-rw-r--r--src/libnm-core-impl/tests/test-compare.c231
-rw-r--r--src/libnm-core-impl/tests/test-general.c330
-rw-r--r--src/libnm-core-impl/tests/test-setting.c250
4 files changed, 419 insertions, 393 deletions
diff --git a/src/libnm-core-impl/tests/meson.build b/src/libnm-core-impl/tests/meson.build
index 988c60db..80b58827 100644
--- a/src/libnm-core-impl/tests/meson.build
+++ b/src/libnm-core-impl/tests/meson.build
@@ -8,7 +8,6 @@ enum_sources = gnome.mkenums_simple(
 )
 
 test_units = [
-  'test-compare',
   'test-crypto',
   'test-general',
   'test-keyfile',
diff --git a/src/libnm-core-impl/tests/test-compare.c b/src/libnm-core-impl/tests/test-compare.c
deleted file mode 100644
index 77d2e17b..00000000
--- a/src/libnm-core-impl/tests/test-compare.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2007 - 2014 Red Hat, Inc.
- * Copyright (C) 2007 - 2008 Novell, Inc.
- */
-
-#include "libnm-core-impl/nm-default-libnm-core.h"
-
-#include <arpa/inet.h>
-#include <netinet/in.h>
-
-#include "nm-property-compare.h"
-
-#include "libnm-glib-aux/nm-test-utils.h"
-
-static void
-compare_ints(void)
-{
-    GVariant *value1, *value2;
-
-    value1 = g_variant_new_int32(5);
-    value2 = g_variant_new_int32(5);
-    g_assert(nm_property_compare(value1, value2) == 0);
-
-    g_variant_unref(value2);
-    value2 = g_variant_new_int32(10);
-    g_assert(nm_property_compare(value1, value2) < 0);
-
-    g_variant_unref(value2);
-    value2 = g_variant_new_int32(-1);
-    g_assert(nm_property_compare(value1, value2) > 0);
-
-    g_variant_unref(value1);
-    g_variant_unref(value2);
-}
-
-static void
-compare_strings(void)
-{
-    GVariant   *value1, *value2;
-    const char *str1 = "hello";
-    const char *str2 = "world";
-
-    value1 = g_variant_new_string(str1);
-    value2 = g_variant_new_string(str1);
-    g_assert(nm_property_compare(value1, value2) == 0);
-
-    g_variant_unref(value2);
-    value2 = g_variant_new_string(str2);
-    g_assert(nm_property_compare(value1, value2) < 0);
-
-    g_assert(nm_property_compare(value2, value1) > 0);
-
-    g_variant_unref(value1);
-    g_variant_unref(value2);
-}
-
-static void
-compare_strv(void)
-{
-    GVariant         *value1, *value2;
-    const char *const strv1[] = {"foo", "bar", "baz", NULL};
-    const char *const strv2[] = {"foo", "bar", "bar", NULL};
-    const char *const strv3[] = {"foo", "bar", NULL};
-    const char *const strv4[] = {"foo", "bar", "baz", "bam", NULL};
-
-    value1 = g_variant_new_strv(strv1, -1);
-    value2 = g_variant_new_strv(strv1, -1);
-    g_assert(nm_property_compare(value1, value2) == 0);
-
-    g_variant_unref(value2);
-    value2 = g_variant_new_strv(strv2, -1);
-    g_assert(nm_property_compare(value1, value2) != 0);
-
-    g_variant_unref(value2);
-    value2 = g_variant_new_strv(strv3, -1);
-    g_assert(nm_property_compare(value1, value2) != 0);
-
-    g_variant_unref(value2);
-    value2 = g_variant_new_strv(strv4, -1);
-    g_assert(nm_property_compare(value1, value2) != 0);
-
-    g_variant_unref(value1);
-    g_variant_unref(value2);
-}
-
-static void
-compare_arrays(void)
-{
-    GVariant *value1, *value2;
-    guint32   array[] = {0, 1, 2, 3, 4};
-
-    value1 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
-                                       array,
-                                       G_N_ELEMENTS(array),
-                                       sizeof(guint32));
-    value2 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
-                                       array,
-                                       G_N_ELEMENTS(array),
-                                       sizeof(guint32));
-
-    g_assert(nm_property_compare(value1, value2) == 0);
-
-    g_variant_unref(value2);
-    value2 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
-                                       array + 1,
-                                       G_N_ELEMENTS(array) - 1,
-                                       sizeof(guint32));
-    g_assert(nm_property_compare(value1, value2) != 0);
-
-    array[0] = 7;
-    g_variant_unref(value2);
-    value2 = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
-                                       array,
-                                       G_N_ELEMENTS(array),
-                                       sizeof(guint32));
-    g_assert(nm_property_compare(value1, value2) != 0);
-
-    g_variant_unref(value1);
-    g_variant_unref(value2);
-}
-
-static void
-compare_str_hash(void)
-{
-    GVariant       *value1, *value2;
-    GVariantBuilder builder;
-
-    g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}"));
-    g_variant_builder_add(&builder, "{ss}", "key1", "hello");
-    g_variant_builder_add(&builder, "{ss}", "key2", "world");
-    g_variant_builder_add(&builder, "{ss}", "key3", "!");
-    value1 = g_variant_builder_end(&builder);
-
-    g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}"));
-    g_variant_builder_add(&builder, "{ss}", "key3", "!");
-    g_variant_builder_add(&builder, "{ss}", "key2", "world");
-    g_variant_builder_add(&builder, "{ss}", "key1", "hello");
-    value2 = g_variant_builder_end(&builder);
-
-    g_assert(nm_property_compare(value1, value2) == 0);
-
-    g_variant_unref(value2);
-    g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}"));
-    g_variant_builder_add(&builder, "{ss}", "key1", "hello");
-    g_variant_builder_add(&builder, "{ss}", "key3", "!");
-    value2 = g_variant_builder_end(&builder);
-
-    g_assert(nm_property_compare(value1, value2) != 0);
-    g_assert(nm_property_compare(value2, value1) != 0);
-
-    g_variant_unref(value2);
-    g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}"));
-    g_variant_builder_add(&builder, "{ss}", "key1", "hello");
-    g_variant_builder_add(&builder, "{ss}", "key2", "moon");
-    g_variant_builder_add(&builder, "{ss}", "key3", "!");
-    value2 = g_variant_builder_end(&builder);
-
-    g_assert(nm_property_compare(value1, value2) != 0);
-
-    g_variant_unref(value1);
-    g_variant_unref(value2);
-}
-
-static void
-compare_ip6_addresses(void)
-{
-    GVariant       *value1, *value2;
-    struct in6_addr addr1;
-    struct in6_addr addr2;
-    struct in6_addr addr3;
-    guint32         prefix1 = 64;
-    guint32         prefix2 = 64;
-    guint32         prefix3 = 0;
-
-    inet_pton(AF_INET6, "1:2:3:4:5:6:7:8", &addr1);
-    inet_pton(AF_INET6, "ffff:2:3:4:5:6:7:8", &addr2);
-    inet_pton(AF_INET6, "::", &addr3);
-
-    value1 = g_variant_new(
-        "(@ayu@ay)",
-        g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr1.s6_addr, 16, 1),
-        prefix1,
-        g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1));
-
-    value2 = g_variant_new(
-        "(@ayu@ay)",
-        g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr1.s6_addr, 16, 1),
-        prefix1,
-        g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1));
-
-    g_assert(nm_property_compare(value1, value2) == 0);
-
-    g_variant_unref(value2);
-    value2 = g_variant_new(
-        "(@ayu@ay)",
-        g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr2.s6_addr, 16, 1),
-        prefix2,
-        g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1));
-
-    g_assert(nm_property_compare(value1, value2) != 0);
-
-    g_variant_unref(value2);
-    value2 = g_variant_new(
-        "(@ayu@ay)",
-        g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1),
-        prefix3,
-        g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, (guint8 *) addr3.s6_addr, 16, 1));
-
-    g_assert(nm_property_compare(value1, value2) != 0);
-
-    g_variant_unref(value1);
-    g_variant_unref(value2);
-}
-
-NMTST_DEFINE();
-
-int
-main(int argc, char *argv[])
-{
-    nmtst_init(&argc, &argv, TRUE);
-
-    g_test_add_func("/libnm/compare/ints", compare_ints);
-    g_test_add_func("/libnm/compare/strings", compare_strings);
-    g_test_add_func("/libnm/compare/strv", compare_strv);
-    g_test_add_func("/libnm/compare/arrays", compare_arrays);
-    g_test_add_func("/libnm/compare/str_hash", compare_str_hash);
-    g_test_add_func("/libnm/compare/ip6_addresses", compare_ip6_addresses);
-
-    return g_test_run();
-}
diff --git a/src/libnm-core-impl/tests/test-general.c b/src/libnm-core-impl/tests/test-general.c
index 30b1ca5d..4acf33e0 100644
--- a/src/libnm-core-impl/tests/test-general.c
+++ b/src/libnm-core-impl/tests/test-general.c
@@ -292,6 +292,7 @@ test_device_wifi_capabilities(void)
     _E(NM_WIFI_DEVICE_CAP_FREQ_VALID);
     _E(NM_WIFI_DEVICE_CAP_FREQ_2GHZ);
     _E(NM_WIFI_DEVICE_CAP_FREQ_5GHZ);
+    _E(NM_WIFI_DEVICE_CAP_FREQ_6GHZ);
     _E(NM_WIFI_DEVICE_CAP_MESH);
     _E(NM_WIFI_DEVICE_CAP_IBSS_RSN);
 #undef _E
@@ -556,6 +557,21 @@ test_nm_hash(void)
 #endif
 
     NM_STATIC_ASSERT_EXPR_VOID(NM_HASH_COMBINE_BOOLS(int, 1, 0, 1) == 5);
+
+    g_assert_cmpmem(NM_HASH_SEED_16(55, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
+                    16,
+                    ((guint8[16]){55, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}),
+                    16);
+
+    g_assert_cmpmem(NM_HASH_SEED_16_U64(1), 16, ((guint8[16]){0, 0, 0, 0, 0, 0, 0, 1, 0}), 16);
+    g_assert_cmpmem(NM_HASH_SEED_16_U64(0x1234567890ABCDEFu),
+                    16,
+                    ((guint8[16]){0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0}),
+                    16);
+
+    g_assert_cmpint(c_siphash_hash(NM_HASH_SEED_16_U64(0x780E21E45489CC6Fu), (guint8 *) "foo", 3),
+                    ==,
+                    0XA5A41E5C1B4153BFu);
 }
 
 /*****************************************************************************/
@@ -2627,7 +2643,7 @@ test_setting_gsm_apn_bad_chars(void)
 
     /* Make sure a valid APN works */
     g_object_set(s_gsm, NM_SETTING_GSM_APN, "foobar123.-baz", NULL);
-    g_assert(nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL));
+    nmtst_assert_setting_verifies(s_gsm);
 
     /* Random invalid chars */
     g_object_set(s_gsm, NM_SETTING_GSM_APN, "@#%$@#%@#%", NULL);
@@ -2639,7 +2655,7 @@ test_setting_gsm_apn_bad_chars(void)
 
     /* 0 characters long */
     g_object_set(s_gsm, NM_SETTING_GSM_APN, "", NULL);
-    g_assert(nm_setting_verify(NM_SETTING(s_gsm), NULL, NULL));
+    nmtst_assert_setting_verifies(s_gsm);
 
     /* 65-character long */
     g_object_set(s_gsm,
@@ -3946,7 +3962,7 @@ typedef struct {
 
 typedef struct {
     const char *name;
-    DiffKey     keys[30];
+    DiffKey     keys[31];
 } DiffSetting;
 
 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
@@ -4003,7 +4019,9 @@ test_connection_diff_a_only(void)
           {NM_SETTING_CONNECTION_PERMISSIONS, NM_SETTING_DIFF_RESULT_IN_A},
           {NM_SETTING_CONNECTION_ZONE, NM_SETTING_DIFF_RESULT_IN_A},
           {NM_SETTING_CONNECTION_MASTER, NM_SETTING_DIFF_RESULT_IN_A},
+          {NM_SETTING_CONNECTION_CONTROLLER, NM_SETTING_DIFF_RESULT_IN_A},
           {NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_DIFF_RESULT_IN_A},
+          {NM_SETTING_CONNECTION_PORT_TYPE, NM_SETTING_DIFF_RESULT_IN_A},
           {NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, NM_SETTING_DIFF_RESULT_IN_A},
           {NM_SETTING_CONNECTION_SECONDARIES, NM_SETTING_DIFF_RESULT_IN_A},
           {NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A},
@@ -5295,6 +5313,7 @@ test_setting_ip4_changed_signal(void)
     NMIPAddress       *addr;
     NMIPRoute         *route;
     GError            *error = NULL;
+    gs_strfreev char **strv  = NULL;
 
     connection = nm_simple_connection_new();
     g_signal_connect(connection,
@@ -5319,7 +5338,8 @@ test_setting_ip4_changed_signal(void)
     ASSERT_CHANGED(nm_setting_ip_config_add_dns_search(s_ip4, "foobar.com"));
     ASSERT_CHANGED(nm_setting_ip_config_remove_dns_search(s_ip4, 0));
 
-    NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns_search->len));
+    NMTST_EXPECT_LIBNM_CRITICAL(
+        NMTST_G_RETURN_MSG(idx >= 0 && idx < nm_g_array_len(priv->dns_search.arr)));
     ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns_search(s_ip4, 1));
     g_test_assert_expected_messages();
 
@@ -5351,10 +5371,51 @@ test_setting_ip4_changed_signal(void)
     nm_setting_ip_config_add_route(s_ip4, route);
     ASSERT_CHANGED(nm_setting_ip_config_clear_routes(s_ip4));
 
+    g_assert(!nm_setting_ip_config_has_dns_options(s_ip4));
+    g_assert_cmpint(nm_setting_ip_config_get_num_dns_options(s_ip4), ==, 0);
+
+    g_object_get(s_ip4, NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL);
+    g_assert_null(strv);
+
+    g_assert_null(nm_setting_ip_config_get_dns_option(s_ip4, 0));
+    NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(_idx <= _len));
+    g_assert_null(nm_setting_ip_config_get_dns_option(s_ip4, 1));
+    g_test_assert_expected_messages();
+
     ASSERT_CHANGED(nm_setting_ip_config_add_dns_option(s_ip4, "debug"));
+
+    g_assert(nm_setting_ip_config_has_dns_options(s_ip4));
+    g_assert_cmpint(nm_setting_ip_config_get_num_dns_options(s_ip4), ==, 1);
+
+    g_object_get(s_ip4, NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL);
+    g_assert_nonnull(strv);
+    g_assert_cmpstr(strv[0], ==, "debug");
+    g_assert_cmpstr(strv[1], ==, NULL);
+    nm_clear_pointer(&strv, g_strfreev);
+
+    g_assert_cmpstr(nm_setting_ip_config_get_dns_option(s_ip4, 0), ==, "debug");
+    g_assert_null(nm_setting_ip_config_get_dns_option(s_ip4, 1));
+    NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(_idx <= _len));
+    g_assert_null(nm_setting_ip_config_get_dns_option(s_ip4, 2));
+    g_test_assert_expected_messages();
+
     ASSERT_CHANGED(nm_setting_ip_config_remove_dns_option(s_ip4, 0));
 
-    NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns_options->len));
+    g_assert(nm_setting_ip_config_has_dns_options(s_ip4));
+    g_assert_cmpint(nm_setting_ip_config_get_num_dns_options(s_ip4), ==, 0);
+
+    g_object_get(s_ip4, NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL);
+    g_assert_nonnull(strv);
+    g_assert_cmpstr(strv[0], ==, NULL);
+    nm_clear_pointer(&strv, g_strfreev);
+
+    g_assert_null(nm_setting_ip_config_get_dns_option(s_ip4, 0));
+    NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(_idx <= _len));
+    g_assert_null(nm_setting_ip_config_get_dns_option(s_ip4, 1));
+    g_test_assert_expected_messages();
+
+    NMTST_EXPECT_LIBNM_CRITICAL(
+        NMTST_G_RETURN_MSG(idx >= 0 && idx < nm_g_array_len(priv->dns_options.arr)));
     ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns_option(s_ip4, 1));
     g_test_assert_expected_messages();
 
@@ -5366,6 +5427,7 @@ test_setting_ip4_changed_signal(void)
 static void
 test_setting_ip6_changed_signal(void)
 {
+    gs_strfreev char **strv = NULL;
     NMConnection      *connection;
     gboolean           changed = FALSE;
     NMSettingIPConfig *s_ip6;
@@ -5393,10 +5455,35 @@ test_setting_ip6_changed_signal(void)
     nm_setting_ip_config_add_dns(s_ip6, "1:2:3::4:5:6");
     ASSERT_CHANGED(nm_setting_ip_config_clear_dns(s_ip6));
 
+    g_object_get(s_ip6, NM_SETTING_IP_CONFIG_DNS_SEARCH, &strv, NULL);
+    g_assert_null(strv);
+
     ASSERT_CHANGED(nm_setting_ip_config_add_dns_search(s_ip6, "foobar.com"));
+
+    g_object_get(s_ip6, NM_SETTING_IP_CONFIG_DNS_SEARCH, &strv, NULL);
+    g_assert_nonnull(strv);
+    g_assert_cmpstr(strv[0], ==, "foobar.com");
+    g_assert_cmpstr(strv[1], ==, NULL);
+    nm_clear_pointer(&strv, g_strfreev);
+
+    g_assert_cmpstr(nm_setting_ip_config_get_dns_search(s_ip6, 0), ==, "foobar.com");
+    g_assert_cmpstr(nm_setting_ip_config_get_dns_search(s_ip6, 1), ==, NULL);
+
+    NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(_idx <= _len));
+    g_assert_cmpstr(nm_setting_ip_config_get_dns_search(s_ip6, -1), ==, NULL);
+    g_test_assert_expected_messages();
+
+    NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(_idx <= _len));
+    g_assert_cmpstr(nm_setting_ip_config_get_dns_search(s_ip6, 2), ==, NULL);
+    g_test_assert_expected_messages();
+
     ASSERT_CHANGED(nm_setting_ip_config_remove_dns_search(s_ip6, 0));
 
-    NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns_search->len));
+    g_object_get(s_ip6, NM_SETTING_IP_CONFIG_DNS_SEARCH, &strv, NULL);
+    g_assert_null(strv);
+
+    NMTST_EXPECT_LIBNM_CRITICAL(
+        NMTST_G_RETURN_MSG(idx >= 0 && idx < nm_g_array_len(priv->dns_search.arr)));
     ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns_search(s_ip6, 1));
     g_test_assert_expected_messages();
 
@@ -5591,9 +5678,13 @@ test_setting_wireless_security_changed_signal(void)
                                                         "wep-key0",
                                                         NM_SETTING_SECRET_FLAG_AGENT_OWNED,
                                                         NULL)));
+    ASSERT_UNCHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec),
+                                                          "wep-key1",
+                                                          NM_SETTING_SECRET_FLAG_AGENT_OWNED,
+                                                          NULL)));
     ASSERT_CHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec),
                                                         "wep-key1",
-                                                        NM_SETTING_SECRET_FLAG_AGENT_OWNED,
+                                                        NM_SETTING_SECRET_FLAG_NOT_SAVED,
                                                         NULL)));
     ASSERT_CHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec),
                                                         "wep-key2",
@@ -5601,7 +5692,7 @@ test_setting_wireless_security_changed_signal(void)
                                                         NULL)));
     ASSERT_CHANGED(g_assert(nm_setting_set_secret_flags(NM_SETTING(s_wsec),
                                                         "wep-key3",
-                                                        NM_SETTING_SECRET_FLAG_AGENT_OWNED,
+                                                        NM_SETTING_SECRET_FLAG_NOT_SAVED,
                                                         NULL)));
 
     g_object_unref(connection);
@@ -6146,9 +6237,9 @@ test_connection_normalize_slave_type_1(void)
                                           &s_con);
 
     g_object_set(s_con,
-                 NM_SETTING_CONNECTION_MASTER,
+                 NM_SETTING_CONNECTION_CONTROLLER,
                  "master0",
-                 NM_SETTING_CONNECTION_SLAVE_TYPE,
+                 NM_SETTING_CONNECTION_PORT_TYPE,
                  "invalid-type",
                  NULL);
 
@@ -6157,7 +6248,7 @@ test_connection_normalize_slave_type_1(void)
                                            NM_CONNECTION_ERROR_INVALID_PROPERTY);
     g_assert(!nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
 
-    g_object_set(s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, "bridge", NULL);
+    g_object_set(s_con, NM_SETTING_CONNECTION_PORT_TYPE, "bridge", NULL);
 
     g_assert(!nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
     nmtst_assert_connection_verifies_after_normalization(con,
@@ -6165,9 +6256,7 @@ test_connection_normalize_slave_type_1(void)
                                                          NM_CONNECTION_ERROR_MISSING_SETTING);
     nmtst_connection_normalize(con);
     g_assert(nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
-    g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con),
-                    ==,
-                    NM_SETTING_BRIDGE_SETTING_NAME);
+    g_assert_cmpstr(nm_setting_connection_get_port_type(s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME);
 }
 
 static void
@@ -6182,9 +6271,9 @@ test_connection_normalize_slave_type_2(void)
                                           &s_con);
 
     g_object_set(s_con,
-                 NM_SETTING_CONNECTION_MASTER,
+                 NM_SETTING_CONNECTION_CONTROLLER,
                  "master0",
-                 NM_SETTING_CONNECTION_SLAVE_TYPE,
+                 NM_SETTING_CONNECTION_PORT_TYPE,
                  "invalid-type",
                  NULL);
 
@@ -6193,19 +6282,17 @@ test_connection_normalize_slave_type_2(void)
                                            NM_CONNECTION_ERROR_INVALID_PROPERTY);
     g_assert(!nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
 
-    g_object_set(s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, NULL, NULL);
+    g_object_set(s_con, NM_SETTING_CONNECTION_PORT_TYPE, NULL, NULL);
     nm_connection_add_setting(con, nm_setting_bridge_port_new());
 
     g_assert(nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
-    g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con), ==, NULL);
+    g_assert_cmpstr(nm_setting_connection_get_port_type(s_con), ==, NULL);
     nmtst_assert_connection_verifies_after_normalization(con,
                                                          NM_CONNECTION_ERROR,
                                                          NM_CONNECTION_ERROR_MISSING_PROPERTY);
     nmtst_connection_normalize(con);
     g_assert(nm_connection_get_setting_by_name(con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
-    g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con),
-                    ==,
-                    NM_SETTING_BRIDGE_SETTING_NAME);
+    g_assert_cmpstr(nm_setting_connection_get_port_type(s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME);
 }
 
 static void
@@ -6483,9 +6570,9 @@ test_connection_normalize_ovs_interface_type_system(gconstpointer test_data)
     switch (TEST_CASE) {
     case 1:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
 
@@ -6504,9 +6591,9 @@ test_connection_normalize_ovs_interface_type_system(gconstpointer test_data)
         break;
     case 2:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
 
@@ -6527,9 +6614,9 @@ test_connection_normalize_ovs_interface_type_system(gconstpointer test_data)
         break;
     case 3:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
 
@@ -6545,9 +6632,9 @@ test_connection_normalize_ovs_interface_type_system(gconstpointer test_data)
         break;
     case 4:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
 
@@ -6561,7 +6648,7 @@ test_connection_normalize_ovs_interface_type_system(gconstpointer test_data)
                                                NM_CONNECTION_ERROR_INVALID_PROPERTY);
         break;
     case 5:
-        g_object_set(s_con, NM_SETTING_CONNECTION_MASTER, "master0", NULL);
+        g_object_set(s_con, NM_SETTING_CONNECTION_CONTROLLER, "master0", NULL);
 
         s_ovs_if = NM_SETTING_OVS_INTERFACE(nm_setting_ovs_interface_new());
         nm_connection_add_setting(con, NM_SETTING(s_ovs_if));
@@ -6576,15 +6663,15 @@ test_connection_normalize_ovs_interface_type_system(gconstpointer test_data)
                                              NM_SETTING_WIRED_SETTING_NAME,
                                              NM_SETTING_OVS_INTERFACE_SETTING_NAME);
         g_assert(s_con == nm_connection_get_setting_connection(con));
-        g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con),
+        g_assert_cmpstr(nm_setting_connection_get_port_type(s_con),
                         ==,
                         NM_SETTING_OVS_PORT_SETTING_NAME);
         break;
     case 6:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_BRIDGE_SETTING_NAME,
                      NULL);
 
@@ -6598,9 +6685,9 @@ test_connection_normalize_ovs_interface_type_system(gconstpointer test_data)
         break;
     case 7:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_BRIDGE_SETTING_NAME,
                      NULL);
 
@@ -6646,7 +6733,7 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
                                                NM_CONNECTION_ERROR_INVALID_PROPERTY);
         break;
     case 2:
-        g_object_set(s_con, NM_SETTING_CONNECTION_MASTER, "master0", NULL);
+        g_object_set(s_con, NM_SETTING_CONNECTION_CONTROLLER, "master0", NULL);
         nmtst_assert_connection_verifies_after_normalization(con,
                                                              NM_CONNECTION_ERROR,
                                                              NM_CONNECTION_ERROR_MISSING_PROPERTY);
@@ -6659,16 +6746,16 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
                                              NM_SETTING_OVS_INTERFACE_SETTING_NAME);
         g_assert(s_con == nm_connection_get_setting_connection(con));
         g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con));
-        g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con),
+        g_assert_cmpstr(nm_setting_connection_get_port_type(s_con),
                         ==,
                         NM_SETTING_OVS_PORT_SETTING_NAME);
         g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal");
         break;
     case 3:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
         nmtst_assert_connection_verifies_after_normalization(con,
@@ -6683,13 +6770,13 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
                                              NM_SETTING_OVS_INTERFACE_SETTING_NAME);
         g_assert(s_con == nm_connection_get_setting_connection(con));
         g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con));
-        g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con),
+        g_assert_cmpstr(nm_setting_connection_get_port_type(s_con),
                         ==,
                         NM_SETTING_OVS_PORT_SETTING_NAME);
         g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal");
         break;
     case 4:
-        g_object_set(s_con, NM_SETTING_CONNECTION_MASTER, "master0", NULL);
+        g_object_set(s_con, NM_SETTING_CONNECTION_CONTROLLER, "master0", NULL);
         g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL);
         nmtst_assert_connection_verifies_after_normalization(con,
                                                              NM_CONNECTION_ERROR,
@@ -6703,16 +6790,16 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
                                              NM_SETTING_OVS_INTERFACE_SETTING_NAME);
         g_assert(s_con == nm_connection_get_setting_connection(con));
         g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con));
-        g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con),
+        g_assert_cmpstr(nm_setting_connection_get_port_type(s_con),
                         ==,
                         NM_SETTING_OVS_PORT_SETTING_NAME);
         g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal");
         break;
     case 5:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
         g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL);
@@ -6733,9 +6820,9 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
         break;
     case 6:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
         g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "internal", NULL);
@@ -6749,16 +6836,16 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
                                              NM_SETTING_OVS_INTERFACE_SETTING_NAME);
         g_assert(s_con == nm_connection_get_setting_connection(con));
         g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con));
-        g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con),
+        g_assert_cmpstr(nm_setting_connection_get_port_type(s_con),
                         ==,
                         NM_SETTING_OVS_PORT_SETTING_NAME);
         g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "internal");
         break;
     case 7:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
         g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "system", NULL);
@@ -6768,9 +6855,9 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
         break;
     case 8:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
         g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "bogus", NULL);
@@ -6780,9 +6867,9 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
         break;
     case 9:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
         g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL);
@@ -6792,9 +6879,9 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
         break;
     case 10:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
         g_object_set(s_ovs_if, NM_SETTING_OVS_INTERFACE_TYPE, "patch", NULL);
@@ -6805,9 +6892,9 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
         break;
     case 11:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NM_SETTING_CONNECTION_INTERFACE_NAME,
                      "adsf",
@@ -6820,9 +6907,9 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
         break;
     case 12:
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NM_SETTING_CONNECTION_INTERFACE_NAME,
                      "adsf",
@@ -6842,7 +6929,7 @@ test_connection_normalize_ovs_interface_type_ovs_interface(gconstpointer test_da
                                              NM_SETTING_OVS_PATCH_SETTING_NAME);
         g_assert(s_con == nm_connection_get_setting_connection(con));
         g_assert(s_ovs_if == nm_connection_get_setting_ovs_interface(con));
-        g_assert_cmpstr(nm_setting_connection_get_slave_type(s_con),
+        g_assert_cmpstr(nm_setting_connection_get_port_type(s_con),
                         ==,
                         NM_SETTING_OVS_PORT_SETTING_NAME);
         g_assert_cmpstr(nm_setting_ovs_interface_get_interface_type(s_ovs_if), ==, "patch");
@@ -8713,23 +8800,35 @@ test_nm_ptrarray_len(void)
 
 static void
 test_nm_utils_dns_option_validate_do(char                       *option,
-                                     gboolean                    ipv6,
+                                     int                         addr_family,
                                      const NMUtilsDNSOptionDesc *descs,
                                      gboolean                    exp_result,
                                      char                       *exp_name,
                                      gboolean                    exp_value)
 {
-    char    *name;
-    long     value = 0;
-    gboolean result;
+    gs_free char *name  = NULL;
+    long          value = 0;
+    gboolean      result;
+
+    if (!descs) {
+        g_assert(addr_family == AF_UNSPEC);
+        addr_family = nmtst_rand_select(AF_UNSPEC, AF_INET, AF_INET6);
+    }
 
-    result = _nm_utils_dns_option_validate(option, &name, &value, ipv6, descs);
+    result = _nm_utils_dns_option_validate(option, &name, &value, addr_family, descs);
 
     g_assert(result == exp_result);
     g_assert_cmpstr(name, ==, exp_name);
     g_assert(value == exp_value);
 
-    g_free(name);
+    nm_clear_g_free(&name);
+
+    if (result && descs) {
+        result = _nm_utils_dns_option_validate(option, &name, &value, AF_UNSPEC, descs);
+        g_assert(result == exp_result);
+        g_assert_cmpstr(name, ==, exp_name);
+        g_assert(value == exp_value);
+    }
 }
 
 static const NMUtilsDNSOptionDesc opt_descs[] = {
@@ -8743,57 +8842,56 @@ static const NMUtilsDNSOptionDesc opt_descs[] = {
 static void
 test_nm_utils_dns_option_validate(void)
 {
-    /*                                    opt            ipv6    descs        result name       value */
-    test_nm_utils_dns_option_validate_do("", FALSE, NULL, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do(":", FALSE, NULL, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do(":1", FALSE, NULL, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do(":val", FALSE, NULL, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do("opt", FALSE, NULL, TRUE, "opt", -1);
-    test_nm_utils_dns_option_validate_do("opt:", FALSE, NULL, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do("opt:12", FALSE, NULL, TRUE, "opt", 12);
-    test_nm_utils_dns_option_validate_do("opt:12 ", FALSE, NULL, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do("opt:val", FALSE, NULL, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do("opt:2val", FALSE, NULL, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do("opt:2:3", FALSE, NULL, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do("opt-6", FALSE, NULL, TRUE, "opt-6", -1);
+    /*                                  (opt, addr_family, descs, result, name, value) */
+    test_nm_utils_dns_option_validate_do("", AF_UNSPEC, NULL, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do(":", AF_UNSPEC, NULL, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do(":1", AF_UNSPEC, NULL, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do(":val", AF_UNSPEC, NULL, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt", AF_UNSPEC, NULL, TRUE, "opt", -1);
+    test_nm_utils_dns_option_validate_do("opt:", AF_UNSPEC, NULL, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt:12", AF_UNSPEC, NULL, TRUE, "opt", 12);
+    test_nm_utils_dns_option_validate_do("opt:12 ", AF_UNSPEC, NULL, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt:val", AF_UNSPEC, NULL, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt:2val", AF_UNSPEC, NULL, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt:2:3", AF_UNSPEC, NULL, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt-6", AF_UNSPEC, NULL, TRUE, "opt-6", -1);
 
-    test_nm_utils_dns_option_validate_do("opt1", FALSE, opt_descs, TRUE, "opt1", -1);
-    test_nm_utils_dns_option_validate_do("opt1", TRUE, opt_descs, TRUE, "opt1", -1);
-    test_nm_utils_dns_option_validate_do("opt1:3", FALSE, opt_descs, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt1", AF_INET, opt_descs, TRUE, "opt1", -1);
+    test_nm_utils_dns_option_validate_do("opt1", AF_INET6, opt_descs, TRUE, "opt1", -1);
+    test_nm_utils_dns_option_validate_do("opt1:3", AF_INET, opt_descs, FALSE, NULL, -1);
 
-    test_nm_utils_dns_option_validate_do("opt2", FALSE, opt_descs, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do("opt2:5", FALSE, opt_descs, TRUE, "opt2", 5);
+    test_nm_utils_dns_option_validate_do("opt2", AF_INET, opt_descs, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt2:5", AF_INET, opt_descs, TRUE, "opt2", 5);
 
-    test_nm_utils_dns_option_validate_do("opt3", FALSE, opt_descs, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do("opt3", TRUE, opt_descs, TRUE, "opt3", -1);
+    test_nm_utils_dns_option_validate_do("opt3", AF_INET, opt_descs, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt3", AF_INET6, opt_descs, TRUE, "opt3", -1);
 
-    test_nm_utils_dns_option_validate_do("opt4", FALSE, opt_descs, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do("opt4", TRUE, opt_descs, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do("opt4:40", FALSE, opt_descs, FALSE, NULL, -1);
-    test_nm_utils_dns_option_validate_do("opt4:40", TRUE, opt_descs, TRUE, "opt4", 40);
+    test_nm_utils_dns_option_validate_do("opt4", AF_INET, opt_descs, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt4", AF_INET6, opt_descs, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt4:40", AF_INET, opt_descs, FALSE, NULL, -1);
+    test_nm_utils_dns_option_validate_do("opt4:40", AF_INET6, opt_descs, TRUE, "opt4", 40);
 }
 
 static void
 test_nm_utils_dns_option_find_idx(void)
 {
-    GPtrArray *options;
-
-    options = g_ptr_array_new();
-
-    g_ptr_array_add(options, "debug");
-    g_ptr_array_add(options, "timeout:5");
-    g_ptr_array_add(options, "edns0");
+    const char *const options[] = {
+        "debug",
+        "timeout:5",
+        "edns0",
+    };
 
-    g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "debug"), ==, 0);
-    g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "debug:1"), ==, 0);
-    g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "timeout"), ==, 1);
-    g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "timeout:5"), ==, 1);
-    g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "timeout:2"), ==, 1);
-    g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "edns0"), ==, 2);
-    g_assert_cmpint(_nm_utils_dns_option_find_idx(options, "rotate"), ==, -1);
-    g_assert_cmpint(_nm_utils_dns_option_find_idx(options, ""), ==, -1);
+#define _find_idx(options, option) \
+    _nm_utils_dns_option_find_idx((options), G_N_ELEMENTS(options), ("" option ""))
 
-    g_ptr_array_free(options, TRUE);
+    g_assert_cmpint(_find_idx(options, "debug"), ==, 0);
+    g_assert_cmpint(_find_idx(options, "debug:1"), ==, 0);
+    g_assert_cmpint(_find_idx(options, "timeout"), ==, 1);
+    g_assert_cmpint(_find_idx(options, "timeout:5"), ==, 1);
+    g_assert_cmpint(_find_idx(options, "timeout:2"), ==, 1);
+    g_assert_cmpint(_find_idx(options, "edns0"), ==, 2);
+    g_assert_cmpint(_find_idx(options, "rotate"), ==, -1);
+    g_assert_cmpint(_find_idx(options, ""), ==, -1);
 }
 
 /*****************************************************************************/
@@ -10601,9 +10699,9 @@ test_connection_ovs_ifname(gconstpointer test_data)
                                               &s_con);
 
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_BRIDGE_SETTING_NAME,
                      NULL);
 
@@ -10619,9 +10717,9 @@ test_connection_ovs_ifname(gconstpointer test_data)
         g_assert(s_ovs_iface);
 
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
 
@@ -10646,9 +10744,9 @@ test_connection_ovs_ifname(gconstpointer test_data)
         g_assert(s_ovs_iface);
 
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
 
@@ -10662,9 +10760,9 @@ test_connection_ovs_ifname(gconstpointer test_data)
                                               &s_con);
 
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
 
@@ -10688,9 +10786,9 @@ test_connection_ovs_ifname(gconstpointer test_data)
         g_assert(s_ovs_iface);
 
         g_object_set(s_con,
-                     NM_SETTING_CONNECTION_MASTER,
+                     NM_SETTING_CONNECTION_CONTROLLER,
                      "master0",
-                     NM_SETTING_CONNECTION_SLAVE_TYPE,
+                     NM_SETTING_CONNECTION_PORT_TYPE,
                      NM_SETTING_OVS_PORT_SETTING_NAME,
                      NULL);
 
diff --git a/src/libnm-core-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c
index b30758ff..4b1aa2c1 100644
--- a/src/libnm-core-impl/tests/test-setting.c
+++ b/src/libnm-core-impl/tests/test-setting.c
@@ -2303,6 +2303,79 @@ test_ethtool_pause(void)
     g_assert_true(out_value);
 }
 
+static void
+test_ethtool_eee(void)
+{
+    gs_unref_object NMConnection   *con     = NULL;
+    gs_unref_object NMConnection   *con2    = NULL;
+    gs_unref_object NMConnection   *con3    = NULL;
+    gs_unref_variant GVariant      *variant = NULL;
+    gs_free_error GError           *error   = NULL;
+    nm_auto_unref_keyfile GKeyFile *keyfile = NULL;
+    NMSettingConnection            *s_con;
+    NMSettingEthtool               *s_ethtool;
+    NMSettingEthtool               *s_ethtool2;
+    NMSettingEthtool               *s_ethtool3;
+    gboolean                        out_value;
+
+    con =
+        nmtst_create_minimal_connection("ethtool-eee", NULL, NM_SETTING_WIRED_SETTING_NAME, &s_con);
+    s_ethtool = NM_SETTING_ETHTOOL(nm_setting_ethtool_new());
+    nm_connection_add_setting(con, NM_SETTING(s_ethtool));
+
+    nm_setting_option_set_boolean(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_EEE_ENABLED, FALSE);
+
+    g_assert_true(nm_setting_option_get_boolean(NM_SETTING(s_ethtool),
+                                                NM_ETHTOOL_OPTNAME_EEE_ENABLED,
+                                                &out_value));
+    g_assert_true(!out_value);
+
+    nmtst_connection_normalize(con);
+
+    variant = nm_connection_to_dbus(con, NM_CONNECTION_SERIALIZE_ALL);
+
+    con2 = nm_simple_connection_new_from_dbus(variant, &error);
+    nmtst_assert_success(con2, error);
+
+    s_ethtool2 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con2, NM_TYPE_SETTING_ETHTOOL));
+
+    g_assert_true(nm_setting_option_get_boolean(NM_SETTING(s_ethtool2),
+                                                NM_ETHTOOL_OPTNAME_EEE_ENABLED,
+                                                &out_value));
+    g_assert_true(!out_value);
+
+    nmtst_assert_connection_verifies_without_normalization(con2);
+
+    nmtst_assert_connection_equals(con, FALSE, con2, FALSE);
+
+    con2 = nm_simple_connection_new_from_dbus(variant, &error);
+    nmtst_assert_success(con2, error);
+
+    keyfile = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error);
+    nmtst_assert_success(keyfile, error);
+
+    con3 = nm_keyfile_read(keyfile,
+                           "/ignored/current/working/directory/for/loading/relative/paths",
+                           NM_KEYFILE_HANDLER_FLAGS_NONE,
+                           NULL,
+                           NULL,
+                           &error);
+    nmtst_assert_success(con3, error);
+
+    nm_keyfile_read_ensure_id(con3, "unused-because-already-has-id");
+    nm_keyfile_read_ensure_uuid(con3, "unused-because-already-has-uuid");
+
+    nmtst_connection_normalize(con3);
+
+    nmtst_assert_connection_equals(con, FALSE, con3, FALSE);
+
+    s_ethtool3 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con3, NM_TYPE_SETTING_ETHTOOL));
+
+    g_assert_true(nm_setting_option_get_boolean(NM_SETTING(s_ethtool3),
+                                                NM_ETHTOOL_OPTNAME_EEE_ENABLED,
+                                                &out_value));
+    g_assert_true(!out_value);
+}
 /*****************************************************************************/
 
 static void
@@ -4492,7 +4565,7 @@ test_setting_metadata(void)
             GArray                   *property_types_data;
             guint                     prop_idx_val;
             gboolean                  can_set_including_default = FALSE;
-            gboolean                  can_have_direct_hook      = FALSE;
+            gboolean                  can_have_direct_set_fcn   = FALSE;
             int                       n_special_options;
 
             g_assert(sip->name);
@@ -4633,9 +4706,11 @@ test_setting_metadata(void)
                                        INFINIBAND_ALEN));
                 } else {
                     g_assert(g_variant_type_equal(sip->property_type->dbus_type, "s"));
-                    g_assert(sip->property_type->to_dbus_fcn
-                             == _nm_setting_property_to_dbus_fcn_direct);
-                    can_have_direct_hook = TRUE;
+                    g_assert(NM_IN_SET(sip->property_type->to_dbus_fcn,
+                                       _nm_setting_property_to_dbus_fcn_direct,
+                                       _nm_setting_connection_controller_to_dbus,
+                                       _nm_setting_connection_port_type_to_dbus));
+                    can_have_direct_set_fcn = TRUE;
                 }
                 g_assert(sip->param_spec);
                 g_assert(sip->param_spec->value_type == G_TYPE_STRING);
@@ -4663,6 +4738,11 @@ test_setting_metadata(void)
                 g_assert(sip->param_spec);
                 g_assert(!NM_FLAGS_HAS(sip->param_spec->flags, NM_SETTING_PARAM_SECRET));
             }
+            if (sip->direct_strv_preserve_empty)
+                g_assert(sip->property_type->direct_type == NM_VALUE_TYPE_STRV);
+            if (sip->direct_string_allow_empty) {
+                g_assert(sip->property_type->direct_type == NM_VALUE_TYPE_STRING);
+            }
 
             if (sip->direct_set_string_mac_address_len != 0) {
                 g_assert(NM_IN_SET(sip->property_type,
@@ -4671,8 +4751,26 @@ test_setting_metadata(void)
                 g_assert(sip->property_type->direct_type == NM_VALUE_TYPE_STRING);
             }
 
-            if (!can_have_direct_hook)
-                g_assert(!sip->direct_hook.set_string_fcn);
+            if (!can_have_direct_set_fcn)
+                g_assert(!sip->direct_set_fcn.set_string);
+
+            if (sip->property_type->direct_type == NM_VALUE_TYPE_NONE)
+                g_assert(!sip->direct_also_notify);
+            else {
+                if (sip->direct_also_notify) {
+                    guint prop_idx2;
+                    guint cnt = 0;
+
+                    for (prop_idx2 = 0; prop_idx2 < sis->property_infos_len; prop_idx2++) {
+                        const NMSettInfoProperty *sip2 = &sis->property_infos[prop_idx2];
+
+                        if (sip2->param_spec == sip->direct_also_notify)
+                            cnt++;
+                    }
+                    g_assert_cmpint(cnt, ==, 1u);
+                    g_assert(sip->param_spec != sip->direct_also_notify);
+                }
+            }
 
             n_special_options = (sip->direct_set_string_mac_address_len != 0)
                                 + (!!sip->direct_set_string_strip)
@@ -4754,6 +4852,10 @@ check_done:;
                     g_assert(NM_IN_SET(sip->property_type->from_dbus_fcn,
                                        _nm_setting_property_from_dbus_fcn_direct_ip_config_gateway,
                                        _nm_setting_property_from_dbus_fcn_direct_mac_address,
+                                       _nm_setting_connection_controller_from_dbus,
+                                       _nm_setting_connection_master_from_dbus,
+                                       _nm_setting_connection_slave_type_from_dbus,
+                                       _nm_setting_connection_port_type_from_dbus,
                                        _nm_setting_property_from_dbus_fcn_direct));
                 }
             }
@@ -4775,7 +4877,9 @@ check_done:;
                 g_assert(sip->property_type->direct_type != NM_VALUE_TYPE_NONE);
                 g_assert(NM_IN_SET(sip->property_type->to_dbus_fcn,
                                    _nm_setting_property_to_dbus_fcn_direct,
-                                   _nm_setting_property_to_dbus_fcn_direct_mac_address));
+                                   _nm_setting_property_to_dbus_fcn_direct_mac_address,
+                                   _nm_setting_connection_controller_to_dbus,
+                                   _nm_setting_connection_port_type_to_dbus));
             } else if (sip->property_type->compare_fcn == _nm_setting_property_compare_fcn_ignore) {
                 if (NM_IN_SET(sip->property_type,
                               &nm_sett_info_propert_type_deprecated_ignore_i,
@@ -4810,6 +4914,17 @@ check_done:;
             g_array_append_val(property_types_data, prop_idx_val);
 
             if (sip->param_spec) {
+                /* All "direct" properties use G_PARAM_EXPLICIT_NOTIFY.
+                 *
+                 * Warning: this is potentially dangerous, because implementations MUST remember
+                 * to notify the property change in set_property(). Optimally, the property uses
+                 * _nm_setting_property_set_property_direct(), which takes care of that.
+                 */
+                if (sip->property_type->direct_type != NM_VALUE_TYPE_NONE)
+                    g_assert(NM_FLAGS_HAS(sip->param_spec->flags, G_PARAM_EXPLICIT_NOTIFY));
+            }
+
+            if (sip->param_spec) {
                 nm_auto_unset_gvalue GValue val = G_VALUE_INIT;
 
                 g_assert_cmpstr(sip->name, ==, sip->param_spec->name);
@@ -4998,6 +5113,50 @@ check_done:;
 /*****************************************************************************/
 
 static void
+test_setting_connection_empty_address_and_route(void)
+{
+    NMSettingIPConfig            *s_ip4;
+    NMIPRoute                    *route;
+    NMIPAddress                  *addr;
+    gs_unref_object NMConnection *con   = NULL;
+    gs_free_error GError         *error = NULL;
+    gboolean                      success;
+
+    /* IP4 setting */
+    con   = nmtst_create_minimal_connection("wired", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
+    s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
+    nm_connection_add_setting(con, NM_SETTING(s_ip4));
+    g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
+    g_assert(s_ip4 != NULL);
+    g_assert(NM_IS_SETTING_IP4_CONFIG(s_ip4));
+    success = nm_setting_verify((NMSetting *) s_ip4, con, &error);
+    nmtst_assert_no_success(success, error);
+    nm_clear_error(&error);
+
+    route = nm_ip_route_new(AF_INET, "192.168.12.0", 24, NULL, 0, NULL);
+    nm_setting_ip_config_add_route(s_ip4, route);
+    success = nm_setting_verify((NMSetting *) s_ip4, con, &error);
+    nmtst_assert_success(success, error);
+    nm_clear_error(&error);
+
+    nm_setting_ip_config_clear_routes(s_ip4);
+    addr = nm_ip_address_new(AF_INET, "1.1.1.3", 24, NULL);
+    nm_setting_ip_config_add_address(s_ip4, addr);
+    success = nm_setting_verify((NMSetting *) s_ip4, con, &error);
+    nmtst_assert_success(success, error);
+    nm_clear_error(&error);
+
+    nm_setting_ip_config_add_route(s_ip4, route);
+    success = nm_setting_verify((NMSetting *) s_ip4, con, &error);
+    nmtst_assert_success(success, error);
+    nm_ip_address_unref(addr);
+    nm_ip_route_unref(route);
+    nm_clear_error(&error);
+}
+
+/*****************************************************************************/
+
+static void
 test_setting_connection_secondaries_verify(void)
 {
     gs_unref_object NMConnection *con = NULL;
@@ -5035,44 +5194,42 @@ test_setting_connection_secondaries_verify(void)
 
         g_object_set(s_con, NM_SETTING_CONNECTION_SECONDARIES, arr->pdata, NULL);
 
-#define _assert_secondaries(s_con, expected)                                                   \
-    G_STMT_START                                                                               \
-    {                                                                                          \
-        NMSettingConnection *const _s_con    = (s_con);                                        \
-        const char *const         *_expected = (expected);                                     \
-        GArray                    *_secondaries;                                               \
-        const guint                _expected_len = NM_PTRARRAY_LEN(_expected);                 \
-        gs_strfreev char         **_sec_strv     = NULL;                                       \
-        guint                      _i;                                                         \
-                                                                                               \
-        g_assert(_expected);                                                                   \
-                                                                                               \
-        if (nmtst_get_rand_bool()) {                                                           \
-            _secondaries = _nm_setting_connection_get_secondaries(_s_con);                     \
-            g_assert_cmpint(_expected_len, ==, nm_g_array_len(_secondaries));                  \
-            g_assert((_expected_len == 0) == (!_secondaries));                                 \
-            g_assert(nm_strv_equal(_expected,                                                  \
-                                   _secondaries ? nm_strvarray_get_strv(&_secondaries, NULL)   \
-                                                : NM_PTRARRAY_EMPTY(const char *)));           \
-        }                                                                                      \
-                                                                                               \
-        if (nmtst_get_rand_bool()) {                                                           \
-            g_object_get(_s_con, NM_SETTING_CONNECTION_SECONDARIES, &_sec_strv, NULL);         \
-            g_assert_cmpint(_expected_len, ==, NM_PTRARRAY_LEN(_sec_strv));                    \
-            g_assert((_expected_len == 0) == (!_sec_strv));                                    \
-            g_assert(nm_strv_equal(_expected, _sec_strv ?: NM_STRV_EMPTY()));                  \
-        }                                                                                      \
-                                                                                               \
-        g_assert_cmpint(nm_setting_connection_get_num_secondaries(_s_con), ==, _expected_len); \
-        if (nmtst_get_rand_bool()) {                                                           \
-            for (_i = 0; _i < _expected_len; _i++) {                                           \
-                g_assert_cmpstr(nm_setting_connection_get_secondary(_s_con, _i),               \
-                                ==,                                                            \
-                                _expected[_i]);                                                \
-            }                                                                                  \
-            g_assert_null(nm_setting_connection_get_secondary(_s_con, _expected_len));         \
-        }                                                                                      \
-    }                                                                                          \
+#define _assert_secondaries(s_con, expected)                                                       \
+    G_STMT_START                                                                                   \
+    {                                                                                              \
+        NMSettingConnection *const _s_con    = (s_con);                                            \
+        const char *const         *_expected = (expected);                                         \
+        GArray                    *_secondaries;                                                   \
+        const guint                _expected_len = NM_PTRARRAY_LEN(_expected);                     \
+        gs_strfreev char         **_sec_strv     = NULL;                                           \
+        guint                      _i;                                                             \
+                                                                                                   \
+        g_assert(_expected);                                                                       \
+                                                                                                   \
+        if (nmtst_get_rand_bool()) {                                                               \
+            _secondaries = _nm_setting_connection_get_secondaries(_s_con);                         \
+            g_assert_cmpint(_expected_len, ==, nm_g_array_len(_secondaries));                      \
+            g_assert((_expected_len == 0) == (!_secondaries));                                     \
+            g_assert(nm_strv_equal(_expected, nm_strvarray_get_strv_notnull(_secondaries, NULL))); \
+        }                                                                                          \
+                                                                                                   \
+        if (nmtst_get_rand_bool()) {                                                               \
+            g_object_get(_s_con, NM_SETTING_CONNECTION_SECONDARIES, &_sec_strv, NULL);             \
+            g_assert_cmpint(_expected_len, ==, NM_PTRARRAY_LEN(_sec_strv));                        \
+            g_assert((_expected_len == 0) == (!_sec_strv));                                        \
+            g_assert(nm_strv_equal(_expected, _sec_strv ?: NM_STRV_EMPTY()));                      \
+        }                                                                                          \
+                                                                                                   \
+        g_assert_cmpint(nm_setting_connection_get_num_secondaries(_s_con), ==, _expected_len);     \
+        if (nmtst_get_rand_bool()) {                                                               \
+            for (_i = 0; _i < _expected_len; _i++) {                                               \
+                g_assert_cmpstr(nm_setting_connection_get_secondary(_s_con, _i),                   \
+                                ==,                                                                \
+                                _expected[_i]);                                                    \
+            }                                                                                      \
+            g_assert_null(nm_setting_connection_get_secondary(_s_con, _expected_len));             \
+        }                                                                                          \
+    }                                                                                              \
     G_STMT_END
 
         _assert_secondaries(s_con, (const char *const *) arr->pdata);
@@ -5307,6 +5464,8 @@ main(int argc, char **argv)
                          test_8021x);
     g_test_add_data_func("/libnm/setting-8021x/pkcs12", "test-cert.p12, test", test_8021x);
 
+    g_test_add_func("/libnm/settings/test_setting_connection_empty_address_and_route",
+                    test_setting_connection_empty_address_and_route);
     g_test_add_func("/libnm/settings/test_setting_connection_secondaries_verify",
                     test_setting_connection_secondaries_verify);
 
@@ -5326,6 +5485,7 @@ main(int argc, char **argv)
     g_test_add_func("/libnm/settings/ethtool/coalesce", test_ethtool_coalesce);
     g_test_add_func("/libnm/settings/ethtool/ring", test_ethtool_ring);
     g_test_add_func("/libnm/settings/ethtool/pause", test_ethtool_pause);
+    g_test_add_func("/libnm/settings/ethtool/eee", test_ethtool_eee);
 
     g_test_add_func("/libnm/settings/6lowpan/1", test_6lowpan_1);