blob: 9740db6a7d58c7d1e8217c800b9285862a75ff56 [file] [log] [blame]
Václav Kubernát73109382018-09-14 19:52:03 +02001/*
2 * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
3 * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
4 *
5 * Written by Václav Kubernát <kubervac@fit.cvut.cz>
6 *
7*/
8
Jan Kundráta33cf082019-03-28 11:55:57 +01009#include "trompeloeil_doctest.h"
Václav Kubernát73109382018-09-14 19:52:03 +020010
Václav Kubernátc31bd602019-03-07 11:44:48 +010011#ifdef sysrepo_BACKEND
Václav Kubernát73109382018-09-14 19:52:03 +020012#include "sysrepo_access.hpp"
Václav Kubernátc31bd602019-03-07 11:44:48 +010013#elif defined(netconf_BACKEND)
14#include "netconf_access.hpp"
15#include "netopeer_vars.hpp"
16#else
17#error "Unknown backend"
18#endif
Václav Kubernát73109382018-09-14 19:52:03 +020019#include "sysrepo_subscription.hpp"
Václav Kubernát8e121ff2019-10-15 15:47:45 +020020#include "utils.hpp"
Václav Kubernát73109382018-09-14 19:52:03 +020021
Václav Kubernát69aabe92020-01-24 16:53:12 +010022class MockRecorder : public trompeloeil::mock_interface<Recorder> {
Václav Kubernát73109382018-09-14 19:52:03 +020023public:
Václav Kubernát69aabe92020-01-24 16:53:12 +010024 IMPLEMENT_MOCK3(write);
Václav Kubernát73109382018-09-14 19:52:03 +020025};
26
Václav Kubernát8e121ff2019-10-15 15:47:45 +020027namespace std {
Václav Kubernát69aabe92020-01-24 16:53:12 +010028std::ostream& operator<<(std::ostream& s, const std::optional<std::string>& opt)
29{
30 s << (opt ? *opt : "std::nullopt");
31 return s;
32}
33
Jan Kundrátb331b552020-01-23 15:25:29 +010034std::ostream& operator<<(std::ostream& s, const DatastoreAccess::Tree& map)
Václav Kubernát8e121ff2019-10-15 15:47:45 +020035{
36 s << std::endl
37 << "{";
38 for (const auto& it : map) {
39 s << "{\"" << it.first << "\", " << leafDataToString(it.second) << "}" << std::endl;
40 }
41 s << "}" << std::endl;
42 return s;
43}
44}
45
46TEST_CASE("setting/getting values")
Václav Kubernát73109382018-09-14 19:52:03 +020047{
Václav Kubernát73109382018-09-14 19:52:03 +020048 trompeloeil::sequence seq1;
49 MockRecorder mock;
50 SysrepoSubscription subscription(&mock);
Václav Kubernátc31bd602019-03-07 11:44:48 +010051
52#ifdef sysrepo_BACKEND
Václav Kubernát73109382018-09-14 19:52:03 +020053 SysrepoAccess datastore("netconf-cli-test");
Václav Kubernátc31bd602019-03-07 11:44:48 +010054#elif defined(netconf_BACKEND)
55 NetconfAccess datastore(NETOPEER_SOCKET_PATH);
56#else
57#error "Unknown backend"
58#endif
Václav Kubernát73109382018-09-14 19:52:03 +020059
Václav Kubernát69aabe92020-01-24 16:53:12 +010060 using namespace std::literals::string_literals;
61
Václav Kubernát134d78f2019-09-03 16:42:29 +020062 SECTION("set leafInt8 to -128")
Václav Kubernát73109382018-09-14 19:52:03 +020063 {
Václav Kubernát69aabe92020-01-24 16:53:12 +010064 REQUIRE_CALL(mock, write("/example-schema:leafInt8", std::nullopt, "-128"s));
Václav Kubernát134d78f2019-09-03 16:42:29 +020065 datastore.setLeaf("/example-schema:leafInt8", int8_t{-128});
66 datastore.commitChanges();
67 }
68
69 SECTION("set leafInt16 to -32768")
70 {
Václav Kubernát69aabe92020-01-24 16:53:12 +010071 REQUIRE_CALL(mock, write("/example-schema:leafInt16", std::nullopt, "-32768"s));
Václav Kubernát134d78f2019-09-03 16:42:29 +020072 datastore.setLeaf("/example-schema:leafInt16", int16_t{-32768});
73 datastore.commitChanges();
74 }
75
76 SECTION("set leafInt32 to -2147483648")
77 {
Václav Kubernát69aabe92020-01-24 16:53:12 +010078 REQUIRE_CALL(mock, write("/example-schema:leafInt32", std::nullopt, "-2147483648"s));
Václav Kubernát134d78f2019-09-03 16:42:29 +020079 datastore.setLeaf("/example-schema:leafInt32", int32_t{-2147483648});
80 datastore.commitChanges();
81 }
82
83 SECTION("set leafInt64 to -50000000000")
84 {
Václav Kubernát69aabe92020-01-24 16:53:12 +010085 REQUIRE_CALL(mock, write("/example-schema:leafInt64", std::nullopt, "-50000000000"s));
Václav Kubernát134d78f2019-09-03 16:42:29 +020086 datastore.setLeaf("/example-schema:leafInt64", int64_t{-50000000000});
87 datastore.commitChanges();
88 }
89
90 SECTION("set leafUInt8 to 255")
91 {
Václav Kubernát69aabe92020-01-24 16:53:12 +010092 REQUIRE_CALL(mock, write("/example-schema:leafUInt8", std::nullopt, "255"s));
Václav Kubernát134d78f2019-09-03 16:42:29 +020093 datastore.setLeaf("/example-schema:leafUInt8", uint8_t{255});
94 datastore.commitChanges();
95 }
96
97 SECTION("set leafUInt16 to 65535")
98 {
Václav Kubernát69aabe92020-01-24 16:53:12 +010099 REQUIRE_CALL(mock, write("/example-schema:leafUInt16", std::nullopt, "65535"s));
Václav Kubernát134d78f2019-09-03 16:42:29 +0200100 datastore.setLeaf("/example-schema:leafUInt16", uint16_t{65535});
101 datastore.commitChanges();
102 }
103
104 SECTION("set leafUInt32 to 4294967295")
105 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100106 REQUIRE_CALL(mock, write("/example-schema:leafUInt32", std::nullopt, "4294967295"s));
Václav Kubernát134d78f2019-09-03 16:42:29 +0200107 datastore.setLeaf("/example-schema:leafUInt32", uint32_t{4294967295});
108 datastore.commitChanges();
109 }
110
111 SECTION("set leafUInt64 to 50000000000")
112 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100113 REQUIRE_CALL(mock, write("/example-schema:leafUInt64", std::nullopt, "50000000000"s));
Václav Kubernát134d78f2019-09-03 16:42:29 +0200114 datastore.setLeaf("/example-schema:leafUInt64", uint64_t{50000000000});
Václav Kubernát73109382018-09-14 19:52:03 +0200115 datastore.commitChanges();
116 }
117
118 SECTION("set leafEnum to coze")
119 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100120 REQUIRE_CALL(mock, write("/example-schema:leafEnum", std::nullopt, "coze"s));
Václav Kubernát73109382018-09-14 19:52:03 +0200121 datastore.setLeaf("/example-schema:leafEnum", enum_{"coze"});
122 datastore.commitChanges();
123 }
124
125 SECTION("set leafDecimal to 123.544")
126 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100127 REQUIRE_CALL(mock, write("/example-schema:leafDecimal", std::nullopt, "123.544"s));
Václav Kubernát73109382018-09-14 19:52:03 +0200128 datastore.setLeaf("/example-schema:leafDecimal", 123.544);
129 datastore.commitChanges();
130 }
131
132 SECTION("create presence container")
133 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100134 REQUIRE_CALL(mock, write("/example-schema:pContainer", std::nullopt, ""s));
Václav Kubernát73109382018-09-14 19:52:03 +0200135 datastore.createPresenceContainer("/example-schema:pContainer");
136 datastore.commitChanges();
137 }
138
Václav Kubernát45f4a822019-05-29 21:10:50 +0200139 SECTION("create a list instance")
140 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100141 REQUIRE_CALL(mock, write("/example-schema:person[name='Nguyen']", std::nullopt, ""s));
142 REQUIRE_CALL(mock, write("/example-schema:person[name='Nguyen']/name", std::nullopt, "Nguyen"s));
Václav Kubernát45f4a822019-05-29 21:10:50 +0200143 datastore.createListInstance("/example-schema:person[name='Nguyen']");
144 datastore.commitChanges();
145 }
146
Václav Kubernát3efb5ca2019-10-09 20:07:40 +0200147 SECTION("leafref pointing to a key of a list")
148 {
149 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100150 REQUIRE_CALL(mock, write("/example-schema:person[name='Dan']", std::nullopt, ""s));
151 REQUIRE_CALL(mock, write("/example-schema:person[name='Dan']/name", std::nullopt, "Dan"s));
152 REQUIRE_CALL(mock, write("/example-schema:person[name='Elfi']", std::nullopt, ""s));
153 REQUIRE_CALL(mock, write("/example-schema:person[name='Elfi']/name", std::nullopt, "Elfi"s));
154 REQUIRE_CALL(mock, write("/example-schema:person[name='Kolafa']", std::nullopt, ""s));
155 REQUIRE_CALL(mock, write("/example-schema:person[name='Kolafa']/name", std::nullopt, "Kolafa"s));
Václav Kubernát3efb5ca2019-10-09 20:07:40 +0200156 datastore.createListInstance("/example-schema:person[name='Dan']");
157 datastore.createListInstance("/example-schema:person[name='Elfi']");
158 datastore.createListInstance("/example-schema:person[name='Kolafa']");
159 datastore.commitChanges();
160 }
161
162 // The commitChanges method has to be called in each of the
163 // SECTIONs, because the REQUIRE_CALL only works inside the given
164 // SECTION.
165 SECTION("Dan")
166 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100167 REQUIRE_CALL(mock, write("/example-schema:bossPerson", std::nullopt, "Dan"s));
Václav Kubernát3efb5ca2019-10-09 20:07:40 +0200168 datastore.setLeaf("/example-schema:bossPerson", std::string{"Dan"});
169 datastore.commitChanges();
170 }
171
172 SECTION("Elfi")
173 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100174 REQUIRE_CALL(mock, write("/example-schema:bossPerson", std::nullopt, "Elfi"s));
Václav Kubernát3efb5ca2019-10-09 20:07:40 +0200175 datastore.setLeaf("/example-schema:bossPerson", std::string{"Elfi"});
176 datastore.commitChanges();
177 }
178
179 SECTION("Kolafa")
180 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100181 REQUIRE_CALL(mock, write("/example-schema:bossPerson", std::nullopt, "Kolafa"s));
Václav Kubernát3efb5ca2019-10-09 20:07:40 +0200182 datastore.setLeaf("/example-schema:bossPerson", std::string{"Kolafa"});
183 datastore.commitChanges();
184 }
185 }
Václav Kubernát8e121ff2019-10-15 15:47:45 +0200186 SECTION("bool values get correctly represented as bools")
187 {
188 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100189 REQUIRE_CALL(mock, write("/example-schema:down", std::nullopt, "true"s));
Václav Kubernát8e121ff2019-10-15 15:47:45 +0200190 datastore.setLeaf("/example-schema:down", bool{true});
191 datastore.commitChanges();
192 }
193
Jan Kundrátb331b552020-01-23 15:25:29 +0100194 DatastoreAccess::Tree expected{{"/example-schema:down", bool{true}}};
Václav Kubernát8e121ff2019-10-15 15:47:45 +0200195 REQUIRE(datastore.getItems("/example-schema:down") == expected);
196 }
Václav Kubernát3efb5ca2019-10-09 20:07:40 +0200197
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200198 SECTION("getting items from the whole module")
199 {
200 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100201 REQUIRE_CALL(mock, write("/example-schema:up", std::nullopt, "true"s));
202 REQUIRE_CALL(mock, write("/example-schema:down", std::nullopt, "false"s));
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200203 datastore.setLeaf("/example-schema:up", bool{true});
204 datastore.setLeaf("/example-schema:down", bool{false});
205 datastore.commitChanges();
206 }
207
Jan Kundrátb331b552020-01-23 15:25:29 +0100208 DatastoreAccess::Tree expected{{"/example-schema:down", bool{false}},
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200209 // Sysrepo always returns containers when getting values, but
210 // libnetconf does not. This is fine by the YANG standard:
211 // https://tools.ietf.org/html/rfc7950#section-7.5.7 Furthermore,
212 // NetconfAccess implementation actually only iterates over leafs,
213 // so even if libnetconf did include containers, they wouldn't get
214 // shown here anyway. With sysrepo2, this won't be necessary,
215 // because it'll use the same data structure as libnetconf, so the
216 // results will be consistent.
217#ifdef sysrepo_BACKEND
Václav Kubernát144729d2020-01-08 15:20:35 +0100218 {"/example-schema:lol", special_{SpecialValue::Container}},
Václav Kubernát9456b5c2019-10-02 21:14:52 +0200219#endif
220 {"/example-schema:up", bool{true}}};
221 REQUIRE(datastore.getItems("/example-schema:*") == expected);
222 }
223
Václav Kubernát152ce222019-12-19 12:23:32 +0100224 SECTION("getItems returns correct datatypes")
225 {
226 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100227 REQUIRE_CALL(mock, write("/example-schema:leafEnum", std::nullopt, "lol"s));
Václav Kubernát152ce222019-12-19 12:23:32 +0100228 datastore.setLeaf("/example-schema:leafEnum", enum_{"lol"});
229 datastore.commitChanges();
230 }
Jan Kundrátb331b552020-01-23 15:25:29 +0100231 DatastoreAccess::Tree expected{{"/example-schema:leafEnum", enum_{"lol"}}};
Václav Kubernát152ce222019-12-19 12:23:32 +0100232
233 REQUIRE(datastore.getItems("/example-schema:leafEnum") == expected);
234 }
235
Václav Kubernátd812cfb2020-01-07 17:30:20 +0100236 SECTION("getItems on a list")
237 {
238 {
Václav Kubernát69aabe92020-01-24 16:53:12 +0100239 REQUIRE_CALL(mock, write("/example-schema:person[name='Jan']", std::nullopt, ""s));
240 REQUIRE_CALL(mock, write("/example-schema:person[name='Jan']/name", std::nullopt, "Jan"s));
241 REQUIRE_CALL(mock, write("/example-schema:person[name='Michal']", std::nullopt, ""s));
242 REQUIRE_CALL(mock, write("/example-schema:person[name='Michal']/name", std::nullopt, "Michal"s));
243 REQUIRE_CALL(mock, write("/example-schema:person[name='Petr']", std::nullopt, ""s));
244 REQUIRE_CALL(mock, write("/example-schema:person[name='Petr']/name", std::nullopt, "Petr"s));
Václav Kubernátd812cfb2020-01-07 17:30:20 +0100245 datastore.createListInstance("/example-schema:person[name='Jan']");
246 datastore.createListInstance("/example-schema:person[name='Michal']");
247 datastore.createListInstance("/example-schema:person[name='Petr']");
248 datastore.commitChanges();
249 }
Jan Kundrátb331b552020-01-23 15:25:29 +0100250 DatastoreAccess::Tree expected{
Václav Kubernát144729d2020-01-08 15:20:35 +0100251 {"/example-schema:person[name='Jan']", special_{SpecialValue::List}},
Václav Kubernátd812cfb2020-01-07 17:30:20 +0100252 {"/example-schema:person[name='Jan']/name", std::string{"Jan"}},
Václav Kubernát144729d2020-01-08 15:20:35 +0100253 {"/example-schema:person[name='Michal']", special_{SpecialValue::List}},
Václav Kubernátd812cfb2020-01-07 17:30:20 +0100254 {"/example-schema:person[name='Michal']/name", std::string{"Michal"}},
Václav Kubernát144729d2020-01-08 15:20:35 +0100255 {"/example-schema:person[name='Petr']", special_{SpecialValue::List}},
Václav Kubernátd812cfb2020-01-07 17:30:20 +0100256 {"/example-schema:person[name='Petr']/name", std::string{"Petr"}}
257 };
258
259 REQUIRE(datastore.getItems("/example-schema:person") == expected);
260 }
261
Václav Kubernát69aabe92020-01-24 16:53:12 +0100262 SECTION("presence containers")
263 {
264 DatastoreAccess::Tree expected;
265 // Make sure it's not there before we create it
266 REQUIRE(datastore.getItems("/example-schema:pContainer") == expected);
267
268 {
269 REQUIRE_CALL(mock, write("/example-schema:pContainer", std::nullopt, ""s));
270 datastore.createPresenceContainer("/example-schema:pContainer");
271 datastore.commitChanges();
272 }
273 expected = {
274 {"/example-schema:pContainer", special_{SpecialValue::PresenceContainer}}
275 };
276 REQUIRE(datastore.getItems("/example-schema:pContainer") == expected);
277
278 // Make sure it's not there after we delete it
279 {
280 REQUIRE_CALL(mock, write("/example-schema:pContainer", ""s, std::nullopt));
281 datastore.deletePresenceContainer("/example-schema:pContainer");
282 datastore.commitChanges();
283 }
284 expected = {};
285 REQUIRE(datastore.getItems("/example-schema:pContainer") == expected);
286
287 }
288
Václav Kubernát73109382018-09-14 19:52:03 +0200289 waitForCompletionAndBitMore(seq1);
290}