Skip to content

Commit 11de31d

Browse files
committed
[#3198] make data a key for option-data in code
- Add ability to set list element that only has keys in Translator::setItem. - Explicitly set list elements in case they contain only keys which can be more common now that data is a key since it is likely one can have entries that only have code, space, and data. - Handle no data as empty data when setting, and empty data as no data when getting. This avoids the need to add an empty "data" element to all options that lack it in all-options.json so that the unit tests pass. But this goes to show that data-less entries may be encountered in production as well, so more importantly this caters to that scenario. - Adjust data in kea4/all-options.json to not contain singlequotes. There was only one occurrence of it. This is a limitation related to unit testing only. Opened issue 3216 about it. - Add missing tests that are not strictly related to the data key, but they are related to option data: - TranslatorOptionDataListTestv6.getEmpty - TranslatorOptionDataListTestv4.get - TranslatorOptionDataListTestv6.setEmpty - TranslatorOptionDataListTestv4.set - Add unit tests: - TranslatorOptionDataListTestv4.optionsSameCodeAndSpace - TranslatorOptionDataListTestv6.optionsSameCodeAndSpace - Add snippet that tests setting of list element with keys only in TranslatorTest.setItem.
1 parent 5202cd1 commit 11de31d

14 files changed

+348
-52
lines changed

doc/examples/kea4/all-options.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@
689689
// Type: string
690690
{
691691
"code": 56,
692-
"data": "Error: here's a DHCPNAK!",
692+
"data": "Error: here is a DHCPNAK!",
693693
"name": "dhcp-message"
694694
},
695695

src/lib/yang/tests/translator_option_data_unittests.cc

Lines changed: 244 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <yang/translator_option_data.h>
1313
#include <yang/yang_models.h>
1414

15+
#include <sysrepo-cpp/utils/exception.hpp>
16+
1517
using namespace std;
1618
using namespace isc;
1719
using namespace isc::data;
@@ -44,7 +46,7 @@ class TranslatorOptionDataListTestv6 :
4446
}; // TranslatorOptionDataListTestv6
4547

4648
// This test verifies that an empty option data list can be properly
47-
// translated from YANG to JSON.
49+
// translated from YANG to JSON for v4.
4850
TEST_F(TranslatorOptionDataListTestv4, getEmpty) {
4951
// Get the option data list and check if it is empty.
5052
const string& xpath = "/kea-dhcp4-server:config";
@@ -53,20 +55,65 @@ TEST_F(TranslatorOptionDataListTestv4, getEmpty) {
5355
ASSERT_FALSE(options);
5456
}
5557

58+
// This test verifies that an empty option data list can be properly
59+
// translated from YANG to JSON for v6.
60+
TEST_F(TranslatorOptionDataListTestv6, getEmpty) {
61+
// Get the option data list and check if it is empty.
62+
const string& xpath = "/kea-dhcp6-server:config";
63+
ConstElementPtr options;
64+
EXPECT_NO_THROW_LOG(options = translator_->getOptionDataListFromAbsoluteXpath(xpath));
65+
ASSERT_FALSE(options);
66+
}
67+
68+
// This test verifies that one option data can be properly translated
69+
// from YANG to JSON for v4.
70+
TEST_F(TranslatorOptionDataListTestv4, get) {
71+
// Create the option code 100.
72+
const string& xpath = "/kea-dhcp4-server:config";
73+
const string& xoption = xpath + "/option-data[code='100'][space='dns'][data='12121212']";
74+
const string& xformat = xoption + "/csv-format";
75+
const string& xalways = xoption + "/always-send";
76+
const string& xnever = xoption + "/never-send";
77+
string const s_false("false");
78+
ASSERT_NO_THROW_LOG(sess_->setItem(xformat, s_false));
79+
ASSERT_NO_THROW_LOG(sess_->setItem(xalways, s_false));
80+
ASSERT_NO_THROW_LOG(sess_->setItem(xnever, s_false));
81+
sess_->applyChanges();
82+
83+
// Get the option data.
84+
ConstElementPtr option;
85+
EXPECT_NO_THROW_LOG(option = translator_->getOptionDataFromAbsoluteXpath(xoption));
86+
ASSERT_TRUE(option);
87+
EXPECT_EQ("{"
88+
" \"always-send\": false,"
89+
" \"code\": 100,"
90+
" \"csv-format\": false,"
91+
" \"data\": \"12121212\","
92+
" \"never-send\": false,"
93+
" \"space\": \"dns\""
94+
" }",
95+
option->str());
96+
97+
// Get the option data list.
98+
ConstElementPtr options;
99+
EXPECT_NO_THROW_LOG(options = translator_->getOptionDataListFromAbsoluteXpath(xpath));
100+
ASSERT_TRUE(options);
101+
ASSERT_EQ(Element::list, options->getType());
102+
EXPECT_EQ(1, options->size());
103+
EXPECT_TRUE(option->equals(*options->get(0)));
104+
}
105+
56106
// This test verifies that one option data can be properly translated
57-
// from YANG to JSON.
107+
// from YANG to JSON for v6.
58108
TEST_F(TranslatorOptionDataListTestv6, get) {
59109
// Create the option code 100.
60110
const string& xpath = "/kea-dhcp6-server:config";
61-
const string& xoption = xpath + "/option-data[code='100'][space='dns']";
111+
const string& xoption = xpath + "/option-data[code='100'][space='dns'][data='12121212']";
62112
const string& xformat = xoption + "/csv-format";
63-
const string& xdata = xoption + "/data";
64113
const string& xalways = xoption + "/always-send";
65114
const string& xnever = xoption + "/never-send";
66115
string const s_false("false");
67116
ASSERT_NO_THROW_LOG(sess_->setItem(xformat, s_false));
68-
string const s_data("12121212");
69-
ASSERT_NO_THROW_LOG(sess_->setItem(xdata, s_data));
70117
ASSERT_NO_THROW_LOG(sess_->setItem(xalways, s_false));
71118
ASSERT_NO_THROW_LOG(sess_->setItem(xnever, s_false));
72119
sess_->applyChanges();
@@ -95,7 +142,7 @@ TEST_F(TranslatorOptionDataListTestv6, get) {
95142
}
96143

97144
// This test verifies that an empty option data list can be properly
98-
// translated from JSON to YANG.
145+
// translated from JSON to YANG for v4.
99146
TEST_F(TranslatorOptionDataListTestv4, setEmpty) {
100147
// Set empty list.
101148
const string& xpath = "/kea-dhcp4-server:config";
@@ -108,11 +155,91 @@ TEST_F(TranslatorOptionDataListTestv4, setEmpty) {
108155
ASSERT_FALSE(options);
109156
}
110157

158+
// This test verifies that an empty option data list can be properly
159+
// translated from JSON to YANG for v6.
160+
TEST_F(TranslatorOptionDataListTestv6, setEmpty) {
161+
// Set empty list.
162+
const string& xpath = "/kea-dhcp6-server:config";
163+
ConstElementPtr options = Element::createList();
164+
EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
165+
166+
// Get it back.
167+
options.reset();
168+
EXPECT_NO_THROW_LOG(options = translator_->getOptionDataListFromAbsoluteXpath(xpath));
169+
ASSERT_FALSE(options);
170+
}
171+
111172
// This test verifies that one option data can be properly translated
112-
// from JSON to YANG.
173+
// from JSON to YANG for v4.
174+
TEST_F(TranslatorOptionDataListTestv4, set) {
175+
// Negative tests.
176+
string const xpath("/kea-dhcp4-server:config");
177+
string const xoption(xpath + "/option-data[code='100'][space='dns'][data='12121212']");
178+
string const s_code("15");
179+
string const s_space("dhcp4");
180+
string const s_data("12121212");
181+
EXPECT_THROW_MSG(sess_->setItem(xoption + "/code", s_code), sysrepo::Error,
182+
"Session::setItem: Couldn't set "
183+
"'/kea-dhcp4-server:config/option-data[code='100'][space='dns'][data='12121212']/code' to "
184+
"'15': SR_ERR_INVAL_ARG");
185+
EXPECT_THROW_MSG(sess_->setItem(xoption + "/space", s_space), sysrepo::Error,
186+
"Session::setItem: Couldn't set "
187+
"'/kea-dhcp4-server:config/option-data[code='100'][space='dns'][data='12121212']/space' to "
188+
"'dhcp4': SR_ERR_INVAL_ARG");
189+
EXPECT_THROW_MSG(sess_->setItem(xoption + "/data", s_data), sysrepo::Error,
190+
"Session::setItem: Couldn't set "
191+
"'/kea-dhcp4-server:config/option-data[code='100'][space='dns'][data='12121212']/data' to "
192+
"'12121212': SR_ERR_INVAL_ARG");
193+
194+
// Setting the list element directly should work.
195+
EXPECT_NO_THROW_LOG(sess_->setItem(xoption, std::nullopt));
196+
197+
// Set one option data.
198+
ElementPtr options = Element::createList();
199+
ElementPtr option = Element::createMap();
200+
option->set("code", Element::create(100));
201+
option->set("space", Element::create("dns"));
202+
option->set("csv-format", Element::create(false));
203+
option->set("data", Element::create("12121212"));
204+
option->set("always-send", Element::create(false));
205+
option->set("never-send", Element::create(false));
206+
options->add(option);
207+
EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
208+
209+
// Get it back.
210+
ConstElementPtr got;
211+
EXPECT_NO_THROW_LOG(got = translator_->getOptionDataListFromAbsoluteXpath(xpath));
212+
ASSERT_TRUE(got);
213+
ASSERT_EQ(1, got->size());
214+
EXPECT_TRUE(option->equals(*got->get(0)));
215+
}
216+
217+
// This test verifies that one option data can be properly translated
218+
// from JSON to YANG for v6.
113219
TEST_F(TranslatorOptionDataListTestv6, set) {
220+
// Negative tests.
221+
string const xpath("/kea-dhcp6-server:config");
222+
string const xoption(xpath + "/option-data[code='100'][space='dns'][data='12121212']");
223+
string const s_code("15");
224+
string const s_space("dhcp6");
225+
string const s_data("12121212");
226+
EXPECT_THROW_MSG(sess_->setItem(xoption + "/code", s_code), sysrepo::Error,
227+
"Session::setItem: Couldn't set "
228+
"'/kea-dhcp6-server:config/option-data[code='100'][space='dns'][data='12121212']/code' to "
229+
"'15': SR_ERR_INVAL_ARG");
230+
EXPECT_THROW_MSG(sess_->setItem(xoption + "/space", s_space), sysrepo::Error,
231+
"Session::setItem: Couldn't set "
232+
"'/kea-dhcp6-server:config/option-data[code='100'][space='dns'][data='12121212']/space' to "
233+
"'dhcp6': SR_ERR_INVAL_ARG");
234+
EXPECT_THROW_MSG(sess_->setItem(xoption + "/data", s_data), sysrepo::Error,
235+
"Session::setItem: Couldn't set "
236+
"'/kea-dhcp6-server:config/option-data[code='100'][space='dns'][data='12121212']/data' to "
237+
"'12121212': SR_ERR_INVAL_ARG");
238+
239+
// Setting the list element directly should work.
240+
EXPECT_NO_THROW_LOG(sess_->setItem(xoption, std::nullopt));
241+
114242
// Set one option data.
115-
const string& xpath = "/kea-dhcp6-server:config";
116243
ElementPtr options = Element::createList();
117244
ElementPtr option = Element::createMap();
118245
option->set("code", Element::create(100));
@@ -132,4 +259,112 @@ TEST_F(TranslatorOptionDataListTestv6, set) {
132259
EXPECT_TRUE(option->equals(*got->get(0)));
133260
}
134261

262+
// This test verifies that multiple options of smae code and space but different data can be
263+
// configured for v4.
264+
TEST_F(TranslatorOptionDataListTestv4, optionsSameCodeAndSpace) {
265+
string const xpath("/kea-dhcp4-server:config");
266+
267+
// Set one option data.
268+
ElementPtr options = Element::createList();
269+
ElementPtr option = Element::createMap();
270+
option->set("code", Element::create(100));
271+
option->set("space", Element::create("dns"));
272+
option->set("csv-format", Element::create(false));
273+
option->set("data", Element::create("12121212"));
274+
option->set("always-send", Element::create(false));
275+
option->set("never-send", Element::create(false));
276+
options->add(option);
277+
option = Element::createMap();
278+
option->set("code", Element::create(100));
279+
option->set("space", Element::create("dns"));
280+
option->set("csv-format", Element::create(false));
281+
option->set("data", Element::create("34343434"));
282+
option->set("always-send", Element::create(false));
283+
option->set("never-send", Element::create(false));
284+
options->add(option);
285+
EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
286+
287+
// Get it back.
288+
ConstElementPtr got;
289+
EXPECT_NO_THROW_LOG(got = translator_->getOptionDataListFromAbsoluteXpath(xpath));
290+
ASSERT_TRUE(got);
291+
EXPECT_EQ(2, got->size());
292+
EXPECT_TRUE(options->equals(*got));
293+
294+
// Now with keys only.
295+
options = Element::createList();
296+
option = Element::createMap();
297+
option->set("code", Element::create(100));
298+
option->set("space", Element::create("dns"));
299+
option->set("data", Element::create("56565656"));
300+
options->add(option);
301+
option = Element::createMap();
302+
option->set("code", Element::create(100));
303+
option->set("space", Element::create("dns"));
304+
option->set("data", Element::create("78787878"));
305+
options->add(option);
306+
EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
307+
308+
// Get it back.
309+
EXPECT_NO_THROW_LOG(got = translator_->getOptionDataListFromAbsoluteXpath(xpath));
310+
ASSERT_TRUE(got);
311+
EXPECT_EQ(4, got->size());
312+
EXPECT_TRUE(options->get(0)->equals(*got->get(2)));
313+
EXPECT_TRUE(options->get(1)->equals(*got->get(3)));
314+
}
315+
316+
// This test verifies that multiple options of smae code and space but different data can be
317+
// configured for v6.
318+
TEST_F(TranslatorOptionDataListTestv6, optionsSameCodeAndSpace) {
319+
string const xpath("/kea-dhcp6-server:config");
320+
321+
// Set one option data.
322+
ElementPtr options = Element::createList();
323+
ElementPtr option = Element::createMap();
324+
option->set("code", Element::create(100));
325+
option->set("space", Element::create("dns"));
326+
option->set("csv-format", Element::create(false));
327+
option->set("data", Element::create("12121212"));
328+
option->set("always-send", Element::create(false));
329+
option->set("never-send", Element::create(false));
330+
options->add(option);
331+
option = Element::createMap();
332+
option->set("code", Element::create(100));
333+
option->set("space", Element::create("dns"));
334+
option->set("csv-format", Element::create(false));
335+
option->set("data", Element::create("34343434"));
336+
option->set("always-send", Element::create(false));
337+
option->set("never-send", Element::create(false));
338+
options->add(option);
339+
EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
340+
341+
// Get it back.
342+
ConstElementPtr got;
343+
EXPECT_NO_THROW_LOG(got = translator_->getOptionDataListFromAbsoluteXpath(xpath));
344+
ASSERT_TRUE(got);
345+
EXPECT_EQ(2, got->size());
346+
EXPECT_TRUE(options->equals(*got));
347+
348+
// Now with keys only.
349+
options = Element::createList();
350+
option = Element::createMap();
351+
option->set("code", Element::create(100));
352+
option->set("space", Element::create("dns"));
353+
option->set("data", Element::create("56565656"));
354+
options->add(option);
355+
option = Element::createMap();
356+
option->set("code", Element::create(100));
357+
option->set("space", Element::create("dns"));
358+
option->set("data", Element::create("78787878"));
359+
options->add(option);
360+
EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
361+
362+
// Get it back.
363+
EXPECT_NO_THROW_LOG(got = translator_->getOptionDataListFromAbsoluteXpath(xpath));
364+
ASSERT_TRUE(got);
365+
EXPECT_EQ(4, got->size());
366+
EXPECT_TRUE(options->get(0)->equals(*got->get(2)));
367+
EXPECT_TRUE(options->get(1)->equals(*got->get(3)));
368+
}
369+
135370
} // namespace

src/lib/yang/tests/translator_unittests.cc

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,9 +523,21 @@ TEST_F(TranslatorTest, setItem) {
523523

524524
ElementPtr element;
525525
string xpath;
526+
optional<DataNode> data_node;
527+
528+
// List.
529+
xpath = "/keatest-module:list[key='value']";
530+
element = Element::create("value");
531+
EXPECT_NO_THROW_LOG(translator->setItem(xpath, ElementPtr(), LeafBaseType::Unknown));
532+
EXPECT_NO_THROW_LOG(translator->setItem(xpath, ElementPtr(), LeafBaseType::Unknown));
533+
EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath + "/key"));
534+
ASSERT_TRUE(data_node);
535+
EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath + "/key"));
536+
ASSERT_TRUE(data_node);
537+
ASSERT_EQ(LeafBaseType::String, data_node->schema().asLeaf().valueType().base());
538+
EXPECT_EQ(element->stringValue(), string(data_node->asTerm().valueStr()));
526539

527540
// String.
528-
optional<DataNode> data_node;
529541
xpath = "/keatest-module:main/string";
530542
element = Element::create("str");
531543
EXPECT_NO_THROW_LOG(translator->setItem(xpath, element, LeafBaseType::String));

0 commit comments

Comments
 (0)