Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #include <kdbcontext.hpp>
10 :
11 : #include <gtest/gtest.h>
12 :
13 :
14 : class MyStaticGetPolicy
15 : {
16 : public:
17 : static kdb::Key get (ELEKTRA_UNUSED kdb::KeySet & ks, ELEKTRA_UNUSED kdb::Key const & spec)
18 : {
19 10 : return kdb::Key ("user/something", KEY_VALUE, "23", KEY_END);
20 : }
21 : };
22 :
23 :
24 20 : TEST (test_contextual_policy, staticGetPolicy)
25 : {
26 : using namespace kdb;
27 4 : KeySet ks;
28 4 : Context c;
29 : // clang-format off
30 : ContextualValue<int, GetPolicyIs<MyStaticGetPolicy>> cv
31 4 : (ks, c, Key("/test",
32 : KEY_CASCADING_NAME,
33 : KEY_VALUE, "/test",
34 : KEY_META, "default", "88",
35 6 : KEY_END));
36 : // clang-format on
37 6 : EXPECT_EQ (cv, 23);
38 4 : EXPECT_EQ (cv, cv);
39 2 : cv = 40;
40 6 : EXPECT_EQ (cv, 40);
41 :
42 4 : ContextualValue<int, GetPolicyIs<MyStaticGetPolicy>> cv2 (cv);
43 4 : EXPECT_EQ (cv, cv2);
44 2 : }
45 :
46 : template <typename T, typename PolicySetter1 = kdb::DefaultPolicyArgs, typename PolicySetter2 = kdb::DefaultPolicyArgs,
47 : typename PolicySetter3 = kdb::DefaultPolicyArgs, typename PolicySetter4 = kdb::DefaultPolicyArgs,
48 : typename PolicySetter5 = kdb::GetPolicyIs<MyStaticGetPolicy>,
49 : typename PolicySetter6 = kdb::DefaultPolicyArgs // unused, for policySelector
50 : >
51 2 : class ValueWrapper : public kdb::ContextualValue<T, PolicySetter1, PolicySetter2, PolicySetter3, PolicySetter4, PolicySetter5>
52 : {
53 : public:
54 : typedef kdb::PolicySelector<PolicySetter1, PolicySetter2, PolicySetter3, PolicySetter4, PolicySetter5, PolicySetter6> Policies;
55 :
56 2 : ValueWrapper<T, PolicySetter1, PolicySetter2, PolicySetter3, PolicySetter4, PolicySetter5, PolicySetter6> (kdb::KeySet & ks,
57 : kdb::Context & context_,
58 : kdb::Key spec)
59 : : kdb::ContextualValue<T, PolicySetter1, PolicySetter2, PolicySetter3, PolicySetter4, PolicySetter5> (ks, context_, spec),
60 8 : value (ks, context_, spec)
61 : {
62 2 : }
63 :
64 : kdb::ContextualValue<T, PolicySetter1, PolicySetter2, PolicySetter3, PolicySetter4, PolicySetter5> value;
65 :
66 : using kdb::ContextualValue<T, PolicySetter1, PolicySetter2, PolicySetter3, PolicySetter4, PolicySetter5>::operator= ;
67 : };
68 :
69 20 : TEST (test_contextual_policy, ValueWrapper)
70 : {
71 : using namespace kdb;
72 4 : KeySet ks;
73 4 : Context c;
74 : // clang-format off
75 : ValueWrapper<int, WritePolicyIs<DefaultWritePolicy>> cv
76 4 : (ks, c, Key("/test",
77 : KEY_CASCADING_NAME,
78 : KEY_VALUE, "/test",
79 : KEY_META, "default", "88",
80 6 : KEY_END));
81 : // clang-format on
82 6 : EXPECT_EQ (cv.value, 23);
83 4 : EXPECT_EQ (cv.value, cv.value);
84 2 : cv.value = 40;
85 6 : EXPECT_EQ (cv.value, 40);
86 :
87 6 : EXPECT_EQ (cv, 23);
88 4 : EXPECT_EQ (cv, cv);
89 2 : cv = 40;
90 6 : EXPECT_EQ (cv, 40);
91 2 : }
92 :
93 : template <typename T>
94 : class MySetPolicy
95 : {
96 : public:
97 : typedef T type;
98 2 : static kdb::Key set (kdb::KeySet & ks, kdb::Key const & spec)
99 : {
100 8 : return kdb::DefaultSetPolicy::setWithNamespace (ks, spec, "dir");
101 : }
102 : };
103 :
104 20 : TEST (test_contextual_policy, setPolicy)
105 : {
106 : using namespace kdb;
107 4 : KeySet ks;
108 4 : Context c;
109 : // clang-format off
110 : ContextualValue<int, SetPolicyIs<MySetPolicy<int>>> cv
111 4 : (ks, c, Key("/test",
112 : KEY_CASCADING_NAME,
113 : KEY_VALUE, "/test",
114 : KEY_META, "default", "88",
115 6 : KEY_END));
116 : // clang-format on
117 6 : EXPECT_EQ (cv, 88);
118 6 : EXPECT_EQ (cv, 88);
119 16 : EXPECT_TRUE (ks.lookup ("/test")) << "did not find /test";
120 18 : EXPECT_FALSE (ks.lookup ("dir/test")) << "found dir/test wrongly";
121 2 : cv = 40;
122 6 : EXPECT_EQ (cv, 40);
123 2 : cv.syncKeySet ();
124 6 : EXPECT_EQ (cv, 40);
125 : // TODO: setPolicy not working correctly
126 16 : EXPECT_TRUE (ks.lookup ("/test")) << "did not find /test";
127 16 : EXPECT_TRUE (ks.lookup ("dir/test")) << "could not find dir/test";
128 2 : }
129 :
130 20 : TEST (test_contextual_policy, readonlyPolicy)
131 : {
132 : using namespace kdb;
133 4 : KeySet ks;
134 4 : Context c;
135 : ContextualValue<int, WritePolicyIs<ReadOnlyPolicy>> cv (
136 6 : ks, c, Key ("/test", KEY_CASCADING_NAME, KEY_VALUE, "/test", KEY_META, "default", "88", KEY_END));
137 6 : EXPECT_EQ (cv, 88);
138 6 : EXPECT_EQ (cv, 88);
139 : // cv = 40; // read only, so this is a compile error
140 2 : }
141 :
142 :
143 : class MyDynamicGetPolicy
144 : {
145 : public:
146 4 : static kdb::Key get (ELEKTRA_UNUSED kdb::KeySet & ks, kdb::Key const & spec)
147 : {
148 12 : return ksLookup (ks.getKeySet (), *spec, ckdb::KDB_O_SPEC);
149 : }
150 : };
151 :
152 20 : TEST (test_contextual_policy, dynamicGetPolicy)
153 : {
154 : using namespace kdb;
155 4 : KeySet ks;
156 6 : ks.append (Key ("user/available", KEY_VALUE, "12", KEY_END));
157 4 : Context c;
158 : // clang-format off
159 : ContextualValue<int, GetPolicyIs<MyDynamicGetPolicy>> cv
160 4 : (ks, c, Key("/test",
161 : KEY_CASCADING_NAME,
162 : KEY_META, "default", "88",
163 : KEY_META, "override/#0", "user/available",
164 6 : KEY_END));
165 : // clang-format on
166 :
167 6 : EXPECT_EQ (cv, 12);
168 4 : EXPECT_EQ (cv, cv);
169 2 : cv = 40;
170 6 : EXPECT_EQ (cv, 40);
171 :
172 4 : ContextualValue<int, GetPolicyIs<MyDynamicGetPolicy>> cv2 (cv);
173 4 : EXPECT_EQ (cv, cv2);
174 2 : }
175 :
176 4 : struct RootLayer : kdb::Layer
177 : {
178 4 : std::string id () const override
179 : {
180 12 : return "root";
181 : }
182 0 : std::string operator() () const override
183 : {
184 0 : return "root";
185 : }
186 : };
187 :
188 20 : TEST (test_contextual_policy, root)
189 : {
190 : using namespace kdb;
191 4 : KeySet ks;
192 6 : ks.append (Key ("user/available", KEY_VALUE, "12", KEY_END));
193 4 : Context c;
194 : // clang-format off
195 : ContextualValue<int, GetPolicyIs<MyDynamicGetPolicy>> cv
196 4 : (ks, c, Key("/",
197 : KEY_CASCADING_NAME,
198 : KEY_META, "default", "88",
199 : KEY_META, "override/#0", "user/available",
200 6 : KEY_END));
201 : // clang-format on
202 :
203 6 : EXPECT_EQ (cv, 12);
204 4 : EXPECT_EQ (cv, cv);
205 2 : cv = 40;
206 6 : EXPECT_EQ (cv, 40);
207 4 : c.activate<RootLayer> ();
208 6 : EXPECT_EQ (cv, 40);
209 :
210 4 : ContextualValue<int, GetPolicyIs<MyDynamicGetPolicy>> cv2 (cv);
211 4 : EXPECT_EQ (cv, cv2);
212 2 : }
213 :
214 :
215 : template <typename T, typename P = kdb::GetPolicyIs<MyStaticGetPolicy>>
216 4 : class MyCV : public kdb::ContextualValue<T, P>
217 : {
218 : public:
219 4 : MyCV<T, P> (kdb::KeySet & ks_, kdb::Context & context_)
220 8 : : kdb::ContextualValue<T, P> (ks_, context_, kdb::Key ("/", KEY_CASCADING_NAME, KEY_END))
221 : {
222 4 : }
223 : };
224 :
225 20 : TEST (test_contextual_policy, myCVRoot)
226 : {
227 : using namespace kdb;
228 4 : KeySet ks;
229 4 : Context c;
230 :
231 4 : MyCV<int> m (ks, c);
232 :
233 6 : EXPECT_EQ (m, 23);
234 2 : }
235 :
236 : class MyNoneGetPolicy
237 : {
238 : public:
239 : static kdb::Key get (ELEKTRA_UNUSED kdb::KeySet & ks, ELEKTRA_UNUSED kdb::Key const & spec)
240 : {
241 2 : return kdb::Key ();
242 : }
243 : };
244 :
245 4 : class MyCV2 : public kdb::ContextualValue<kdb::none_t, kdb::GetPolicyIs<MyNoneGetPolicy>>
246 : {
247 : public:
248 2 : MyCV2 (kdb::KeySet & ks_, kdb::Context & context_)
249 4 : : kdb::ContextualValue<kdb::none_t, kdb::GetPolicyIs<MyNoneGetPolicy>> (ks_, context_, kdb::Key ("/", KEY_CASCADING_NAME, KEY_END)),
250 4 : m_m (ks_, context_)
251 : {
252 2 : }
253 :
254 : MyCV<int> m_m;
255 : };
256 :
257 20 : TEST (test_contextual_policy, myCV2Root)
258 : {
259 : using namespace kdb;
260 4 : KeySet ks;
261 4 : Context c;
262 :
263 2 : MyCV2 m (ks, c);
264 8 : }
|