pacemaker  2.1.7-0f7f88312f
Scalable High-Availability cluster resource manager
pcmk__set_env_option_test.c
Go to the documentation of this file.
1 /*
2  * Copyright 2022-2023 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>
12 
13 #include "mock_private.h"
14 
15 static void
16 bad_input_string(void **state)
17 {
18  // Bad setenv()/unsetenv() input: NULL, empty, or containing '='
19 
20  // Never call setenv()
21  pcmk__mock_setenv = true;
22 
23  pcmk__set_env_option(NULL, "new_value", true);
24  pcmk__set_env_option("", "new_value", true);
25  pcmk__set_env_option("name=val", "new_value", true);
26 
27  pcmk__mock_setenv = false;
28 
29  // Never call unsetenv()
30  pcmk__mock_unsetenv = true;
31 
32  pcmk__set_env_option(NULL, NULL, true);
33  pcmk__set_env_option("", NULL, true);
34  pcmk__set_env_option("name=val", NULL, true);
35 
36  pcmk__mock_unsetenv = false;
37 }
38 
39 static void
40 input_too_long_for_both(void **state)
41 {
42  /* pcmk__set_env_option() wants to set "PCMK_<option>" and "HA_<option>". If
43  * "PCMK_<option>" is too long for the buffer, it simply moves on to
44  * "HA_<option>". A string of length (NAME_MAX - 3) will set us just over
45  * the edge for both tries.
46  */
47  char long_opt[NAME_MAX - 2];
48 
49  for (int i = 0; i < NAME_MAX - 3; i++) {
50  long_opt[i] = 'a';
51  }
52  long_opt[NAME_MAX - 3] = '\0';
53 
54  // Never call setenv() or unsetenv()
55  pcmk__mock_setenv = true;
56  pcmk__set_env_option(long_opt, "new_value", true);
57  pcmk__mock_setenv = false;
58 
59  pcmk__mock_unsetenv = true;
60  pcmk__set_env_option(long_opt, NULL, true);
61  pcmk__mock_unsetenv = false;
62 }
63 
64 static void
65 input_too_long_for_pcmk(void **state)
66 {
67  /* If an input is too long to set "PCMK_<option>", make sure we fall through
68  * to try to set "HA_<option>".
69  *
70  * A string of length (NAME_MAX - 5) will set us just over the edge for
71  * "PCMK_<option>", while still short enough for "HA_<option>" to fit.
72  */
73  char long_opt[NAME_MAX - 4];
74  char buf[NAME_MAX];
75 
76  for (int i = 0; i < NAME_MAX - 5; i++) {
77  long_opt[i] = 'a';
78  }
79  long_opt[NAME_MAX - 5] = '\0';
80 
81  snprintf(buf, NAME_MAX, "HA_%s", long_opt);
82 
83  // Call setenv() for "HA_" only
84  pcmk__mock_setenv = true;
85 
86  expect_string(__wrap_setenv, name, buf);
87  expect_string(__wrap_setenv, value, "new_value");
88  expect_value(__wrap_setenv, overwrite, 1);
89  will_return(__wrap_setenv, 0);
90  pcmk__set_env_option(long_opt, "new_value", true);
91 
92  pcmk__mock_setenv = false;
93 
94  // Call unsetenv() for "HA_" only
95  pcmk__mock_unsetenv = true;
96 
97  expect_string(__wrap_unsetenv, name, buf);
98  will_return(__wrap_unsetenv, 0);
99  pcmk__set_env_option(long_opt, NULL, true);
100 
101  pcmk__mock_unsetenv = false;
102 }
103 
104 static void
105 valid_inputs_set(void **state)
106 {
107  // Make sure we set "PCMK_<option>" and "HA_<option>"
108  pcmk__mock_setenv = true;
109 
110  expect_string(__wrap_setenv, name, "PCMK_env_var");
111  expect_string(__wrap_setenv, value, "new_value");
112  expect_value(__wrap_setenv, overwrite, 1);
113  will_return(__wrap_setenv, 0);
114  expect_string(__wrap_setenv, name, "HA_env_var");
115  expect_string(__wrap_setenv, value, "new_value");
116  expect_value(__wrap_setenv, overwrite, 1);
117  will_return(__wrap_setenv, 0);
118  pcmk__set_env_option("env_var", "new_value", true);
119 
120  // Empty string is also a valid value
121  expect_string(__wrap_setenv, name, "PCMK_env_var");
122  expect_string(__wrap_setenv, value, "");
123  expect_value(__wrap_setenv, overwrite, 1);
124  will_return(__wrap_setenv, 0);
125  expect_string(__wrap_setenv, name, "HA_env_var");
126  expect_string(__wrap_setenv, value, "");
127  expect_value(__wrap_setenv, overwrite, 1);
128  will_return(__wrap_setenv, 0);
129  pcmk__set_env_option("env_var", "", true);
130 
131  pcmk__mock_setenv = false;
132 }
133 
134 static void
135 valid_inputs_unset(void **state)
136 {
137  // Make sure we unset "PCMK_<option>" and "HA_<option>"
138  pcmk__mock_unsetenv = true;
139 
140  expect_string(__wrap_unsetenv, name, "PCMK_env_var");
141  will_return(__wrap_unsetenv, 0);
142  expect_string(__wrap_unsetenv, name, "HA_env_var");
143  will_return(__wrap_unsetenv, 0);
144  pcmk__set_env_option("env_var", NULL, true);
145 
146  pcmk__mock_unsetenv = false;
147 }
148 
149 static void
150 disable_compat(void **state)
151 {
152  // Make sure we set only "PCMK_<option>" and not "HA_<option>"
153  pcmk__mock_setenv = true;
154 
155  expect_string(__wrap_setenv, name, "PCMK_env_var");
156  expect_string(__wrap_setenv, value, "new_value");
157  expect_value(__wrap_setenv, overwrite, 1);
158  will_return(__wrap_setenv, 0);
159  pcmk__set_env_option("env_var", "new_value", false);
160 
161  pcmk__mock_setenv = false;
162 
163  // Make sure we clear both "PCMK_<option>" and "HA_<option>"
164  pcmk__mock_unsetenv = true;
165 
166  expect_string(__wrap_unsetenv, name, "PCMK_env_var");
167  will_return(__wrap_unsetenv, 0);
168  expect_string(__wrap_unsetenv, name, "HA_env_var");
169  will_return(__wrap_unsetenv, 0);
170  pcmk__set_env_option("env_var", NULL, false);
171 
172  pcmk__mock_unsetenv = false;
173 }
174 
175 PCMK__UNIT_TEST(NULL, NULL,
176  cmocka_unit_test(bad_input_string),
177  cmocka_unit_test(input_too_long_for_both),
178  cmocka_unit_test(input_too_long_for_pcmk),
179  cmocka_unit_test(valid_inputs_set),
180  cmocka_unit_test(valid_inputs_unset),
181  cmocka_unit_test(disable_compat))
const char * name
Definition: cib.c:26
PCMK__UNIT_TEST(NULL, NULL, cmocka_unit_test(bad_input), cmocka_unit_test(not_found), cmocka_unit_test(find_attrB), cmocka_unit_test(find_attrA_matching))
void pcmk__set_env_option(const char *option, const char *value, bool compat)
Set or unset a Pacemaker environment variable option.
Definition: options.c:108
bool pcmk__mock_setenv
Definition: mock.c:120
#define NAME_MAX
Definition: logging.c:109
int __wrap_setenv(const char *name, const char *value, int overwrite)
Definition: mock.c:123
bool pcmk__mock_unsetenv
Definition: mock.c:148
int __wrap_unsetenv(const char *name)
Definition: mock.c:151