root/lib/common/tests/xml_element/pcmk__xe_sort_attrs_test.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. assert_order
  2. null_arg
  3. nothing_to_sort
  4. already_sorted
  5. need_sort

   1 /*
   2  * Copyright 2024 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <crm/common/unittest_internal.h>
  13 
  14 #include <glib.h>                           // GHashTable, etc.
  15 
  16 #include "crmcommon_private.h"              // xml_node_private_t
  17 
  18 /*!
  19  * \internal
  20  * \brief Sort an XML element's attributes and compare against a reference
  21  *
  22  * This also verifies that any flags set on the original attributes are
  23  * preserved.
  24  *
  25  * \param[in,out] test_xml       XML whose attributes to sort
  26  * \param[in]     reference_xml  XML whose attribute order to compare against
  27  *                               (attributes must have the same values as in
  28  *                               \p test_xml)
  29  */
  30 static void
  31 assert_order(xmlNode *test_xml, const xmlNode *reference_xml)
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33     GHashTable *attr_flags = pcmk__strkey_table(free, NULL);
  34     xmlAttr *test_attr = NULL;
  35     xmlAttr *ref_attr = NULL;
  36 
  37     // Save original flags
  38     for (xmlAttr *attr = pcmk__xe_first_attr(test_xml); attr != NULL;
  39          attr = attr->next) {
  40 
  41         xml_node_private_t *nodepriv = attr->_private;
  42         uint32_t flags = (nodepriv != NULL)? nodepriv->flags : pcmk__xf_none;
  43 
  44         g_hash_table_insert(attr_flags,
  45                             pcmk__str_copy((const char *) attr->name),
  46                             GUINT_TO_POINTER((guint) flags));
  47     }
  48 
  49     pcmk__xe_sort_attrs(test_xml);
  50 
  51     test_attr = pcmk__xe_first_attr(test_xml);
  52     ref_attr = pcmk__xe_first_attr(reference_xml);
  53 
  54     for (; (test_attr != NULL) && (ref_attr != NULL);
  55          test_attr = test_attr->next, ref_attr = ref_attr->next) {
  56 
  57         const char *test_name = (const char *) test_attr->name;
  58         xml_node_private_t *nodepriv = test_attr->_private;
  59         uint32_t flags = (nodepriv != NULL)? nodepriv->flags : pcmk__xf_none;
  60 
  61         gpointer old_flags_ptr = g_hash_table_lookup(attr_flags, test_name);
  62         uint32_t old_flags = pcmk__xf_none;
  63 
  64         if (old_flags_ptr != NULL) {
  65             old_flags = GPOINTER_TO_UINT(old_flags_ptr);
  66         }
  67 
  68         // Flags must not change
  69         assert_true(flags == old_flags);
  70 
  71         // Attributes must be in expected order with expected values
  72         assert_string_equal(test_name, (const char *) ref_attr->name);
  73         assert_string_equal(pcmk__xml_attr_value(test_attr),
  74                             pcmk__xml_attr_value(ref_attr));
  75     }
  76 
  77     // Attribute lists must be the same length
  78     assert_null(test_attr);
  79     assert_null(ref_attr);
  80 
  81     g_hash_table_destroy(attr_flags);
  82 }
  83 
  84 static void
  85 null_arg(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
  86 {
  87     // Ensure it doesn't crash
  88     pcmk__xe_sort_attrs(NULL);
  89 }
  90 
  91 static void
  92 nothing_to_sort(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94     xmlNode *test_xml = pcmk__xe_create(NULL, "test");
  95     xmlNode *reference_xml = NULL;
  96 
  97     // No attributes
  98     reference_xml = pcmk__xml_copy(NULL, test_xml);
  99     assert_order(test_xml, reference_xml);
 100     pcmk__xml_free(reference_xml);
 101 
 102     // Only one attribute
 103     crm_xml_add(test_xml, "name", "value");
 104     reference_xml = pcmk__xml_copy(NULL, test_xml);
 105     assert_order(test_xml, reference_xml);
 106     pcmk__xml_free(reference_xml);
 107 
 108     pcmk__xml_free(test_xml);
 109 }
 110 
 111 static void
 112 already_sorted(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114     xmlNode *test_xml = pcmk__xe_create(NULL, "test");
 115     xmlNode *reference_xml = pcmk__xe_create(NULL, "test");
 116 
 117     xmlAttr *attr = NULL;
 118 
 119     crm_xml_add(test_xml, "admin", "john");
 120     crm_xml_add(test_xml, "dummy", "value");
 121     crm_xml_add(test_xml, "location", "usa");
 122 
 123     // Set flags in test_xml's attributes for testing flag preservation
 124     attr = xmlHasProp(test_xml, (pcmkXmlStr) "admin");
 125     if (attr != NULL) {
 126         xml_node_private_t *nodepriv = attr->_private;
 127 
 128         if (nodepriv != NULL) {
 129             pcmk__clear_xml_flags(nodepriv, pcmk__xf_created|pcmk__xf_dirty);
 130         }
 131     }
 132 
 133     attr = xmlHasProp(test_xml, (pcmkXmlStr) "location");
 134     if (attr != NULL) {
 135         xml_node_private_t *nodepriv = attr->_private;
 136 
 137         if (nodepriv != NULL) {
 138             pcmk__set_xml_flags(nodepriv, pcmk__xf_lazy);
 139         }
 140     }
 141 
 142     pcmk__xe_set_props(reference_xml,
 143                        "admin", "john",
 144                        "dummy", "value",
 145                        "location", "usa",
 146                        NULL);
 147 
 148     assert_order(test_xml, reference_xml);
 149 
 150     pcmk__xml_free(test_xml);
 151     pcmk__xml_free(reference_xml);
 152 }
 153 
 154 static void
 155 need_sort(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157     xmlNode *test_xml = pcmk__xe_create(NULL, "test");
 158     xmlNode *reference_xml = pcmk__xe_create(NULL, "test");
 159 
 160     xmlAttr *attr = NULL;
 161 
 162     crm_xml_add(test_xml, "location", "usa");
 163     crm_xml_add(test_xml, "admin", "john");
 164     crm_xml_add(test_xml, "dummy", "value");
 165 
 166     // Set flags in test_xml's attributes for testing flag preservation
 167     attr = xmlHasProp(test_xml, (pcmkXmlStr) "location");
 168     if (attr != NULL) {
 169         xml_node_private_t *nodepriv = attr->_private;
 170 
 171         if (nodepriv != NULL) {
 172             pcmk__set_xml_flags(nodepriv, pcmk__xf_lazy);
 173         }
 174     }
 175 
 176     attr = xmlHasProp(test_xml, (pcmkXmlStr) "admin");
 177     if (attr != NULL) {
 178         xml_node_private_t *nodepriv = attr->_private;
 179 
 180         if (nodepriv != NULL) {
 181             pcmk__clear_xml_flags(nodepriv, pcmk__xf_created|pcmk__xf_dirty);
 182         }
 183     }
 184 
 185     pcmk__xe_set_props(reference_xml,
 186                        "admin", "john",
 187                        "dummy", "value",
 188                        "location", "usa",
 189                        NULL);
 190 
 191     assert_order(test_xml, reference_xml);
 192 
 193     pcmk__xml_free(test_xml);
 194     pcmk__xml_free(reference_xml);
 195 }
 196 
 197 PCMK__UNIT_TEST(pcmk__xml_test_setup_group, pcmk__xml_test_teardown_group,
 198                 cmocka_unit_test(null_arg),
 199                 cmocka_unit_test(nothing_to_sort),
 200                 cmocka_unit_test(already_sorted),
 201                 cmocka_unit_test(need_sort))

/* [previous][next][first][last][top][bottom][index][help] */