1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.config;
18
19 import static org.apache.juneau.commons.utils.Utils.*;
20 import static org.apache.juneau.junit.bct.BctAssertions.*;
21 import static org.junit.jupiter.api.Assertions.*;
22
23 import org.apache.juneau.*;
24 import org.apache.juneau.config.event.*;
25 import org.apache.juneau.config.store.*;
26 import org.junit.jupiter.api.*;
27
28
29
30
31 class ConfigImportsTest extends TestBase {
32
33
34
35
36
37 @Test void oneSimpleImport() throws Exception {
38 var ms = MemoryStore.create().build();
39 ms.write("A", "", "x=1");
40 ms.write("B", "", "<A>");
41 var c = Config
42 .create("B")
43 .store(ms)
44 .build();
45 assertEquals("1", c.get("x").get());
46
47 c.set("x", "2");
48 c.commit();
49 assertEquals("x=1", ms.read("A"));
50 assertEquals("x = 2\n", ms.read("B"));
51 }
52
53 @Test void twoSimpleImports() throws Exception {
54 var ms = MemoryStore.create().build();
55 ms.write("A1", "", "x=1");
56 ms.write("A2", "", "y=2");
57 ms.write("B", "", "<A1>\n<A2>");
58 var c = Config.create("B").store(ms).build();
59 assertEquals("1", c.get("x").get());
60 assertEquals("2", c.get("y").get());
61
62 c.set("x", "3");
63 c.set("y", "4");
64 c.commit();
65 assertEquals("x=1", ms.read("A1"));
66 assertEquals("y=2", ms.read("A2"));
67 assertEquals("x = 3\ny = 4\n", ms.read("B"));
68 }
69
70 @Test void nestedImports() throws Exception {
71 var ms = MemoryStore.create().build();
72 ms.write("A1", "", "x=1");
73 ms.write("A2", "", "<A1>\ny=2");
74 ms.write("B", "", "<A2>");
75 var c = Config.create("B").store(ms).build();
76 assertEquals("1", c.get("x").get());
77 assertEquals("2", c.get("y").get());
78
79 c.set("x", "3");
80 c.set("y", "4");
81 c.commit();
82 assertEquals("x=1", ms.read("A1"));
83 assertEquals("<A1>\ny=2", ms.read("A2"));
84 assertEquals("x = 3\ny = 4\n", ms.read("B"));
85 }
86
87 @Test void nestedImportsLoop() {
88
89 var ms = MemoryStore.create().build();
90 ms.write("A1", "", "<A2>\nx=1");
91 ms.write("A2", "", "<A1>\ny=2");
92 ms.write("B", "", "<A2>");
93 assertThrows(Exception.class, ()->Config.create("B").store(ms).build());
94 }
95
96 @Test void importNotFound() {
97 var ms = MemoryStore.create().build();
98 ms.write("B", "", "<A>\nx=1");
99 var c = Config.create("B").store(ms).build();
100 assertEquals("1", c.get("x").get());
101 }
102
103 @Test void noOverwriteOnImports() {
104 var ms = MemoryStore.create().build();
105 ms.write("A", "", "x=1");
106 ms.write("B", "", "<A>");
107 var c = Config.create("B").store(ms).build();
108 assertEquals("1", c.get("x").get());
109 c.set("x", "2");
110 assertEquals("2", c.get("x").get());
111 assertEquals("1", Config.create("A").store(ms).build().get("x").get());
112 }
113
114 @Test void overlappingSections() {
115 var ms = MemoryStore.create().build();
116 ms.write("A", "", "x=1\n[A]\na1=1");
117 ms.write("B", "", "<A>\n[A]\na2=2");
118 var c = Config.create("B").store(ms).build();
119 assertEquals("1", c.get("A/a1").get());
120 assertEquals("2", c.get("A/a2").get());
121 }
122
123 @Test void overlappingSectionsImportAtEnd() {
124 var ms = MemoryStore.create().build();
125 ms.write("A", "", "x=1\n[A]\na1=1");
126 ms.write("B", "", "[A]\na2=2\n<A>");
127 var c = Config.create("B").store(ms).build();
128 assertEquals("1", c.get("A/a1").get());
129 assertEquals("2", c.get("A/a2").get());
130 }
131
132 @Test void overlappingSectionsAndValues() {
133 var ms = MemoryStore.create().build();
134 ms.write("A", "", "x=1\n[A]\na1=1");
135 ms.write("B", "", "<A>\n[A]\na1=2");
136 var c = Config.create("B").store(ms).build();
137 assertEquals("2", c.get("A/a1").get());
138 }
139
140
141
142
143
144 public static class TestListener implements ConfigEventListener {
145
146 private boolean triggered;
147 private ConfigEvents events;
148
149 @Override
150 public void onConfigChange(ConfigEvents events) {
151 this.triggered = true;
152 this.events = events;
153 }
154
155 public TestListener reset() {
156 triggered = false;
157 events = null;
158 return this;
159 }
160
161 public boolean isTriggered() {
162 return triggered;
163 }
164
165 public ConfigEvents getEvents() {
166 return events;
167 }
168
169 public String getNewValue(String section, String key) {
170 if (events.isEmpty())
171 return null;
172 for (var ce : events)
173 if (eq(section, ce.getSection()) && eq(key, ce.getKey()))
174 return ce.getValue();
175 return null;
176 }
177 }
178
179 @Test void a01_updateOnParent() {
180 var ms = MemoryStore.create().build();
181
182 ms.write("A", "", "x=1\n[A]\na1=1");
183 ms.write("B", "", "<A>\n[B]\nb1=2");
184
185 var ca = Config.create("A").store(ms).build();
186 var cb = Config.create("B").store(ms).build();
187
188 assertSize(2, ca.getConfigMap().getListeners());
189 assertSize(1, cb.getConfigMap().getListeners());
190
191 var l = new TestListener();
192 cb.addListener(l);
193
194 assertEmpty(ca.getListeners());
195 assertSize(1, cb.getListeners());
196
197 ms.write("A", "x=1\n[A]\na1=1", "x=1\n[A]\na1=2");
198
199 assertTrue(l.isTriggered());
200 assertSize(1, l.getEvents());
201 assertEquals("2", l.getNewValue("A", "a1"));
202
203 assertEquals("2", cb.get("A/a1").get());
204 assertEquals("2", cb.get("B/b1").get());
205
206 l.reset();
207 cb.removeListener(l);
208 assertEmpty(ca.getListeners());
209 assertEmpty(cb.getListeners());
210
211 ms.write("A", "x=1\n[A]\na1=2", "x=1\n[A]\na1=3");
212
213 assertFalse(l.isTriggered());
214
215 assertEquals("3", cb.get("A/a1").get());
216 assertEquals("2", cb.get("B/b1").get());
217 }
218
219 @Test void a02_updateOnGrandParent() {
220 var ms = MemoryStore.create().build();
221
222 ms.write("A", "", "x=1\n[A]\na1=1");
223 ms.write("B", "", "<A>\n[B]\nb1=2");
224 ms.write("C", "", "<B>\n[C]\nc1=3");
225
226 var ca = Config.create("A").store(ms).build();
227 var cb = Config.create("B").store(ms).build();
228 var cc = Config.create("C").store(ms).build();
229
230 assertSize(3, ca.getConfigMap().getListeners());
231 assertSize(2, cb.getConfigMap().getListeners());
232 assertSize(1, cc.getConfigMap().getListeners());
233
234 var l = new TestListener();
235 cc.addListener(l);
236
237 assertEmpty(ca.getListeners());
238 assertEmpty(cb.getListeners());
239 assertSize(1, cc.getListeners());
240
241 ms.write("A", "x=1\n[A]\na1=1", "x=1\n[A]\na1=2");
242
243 assertTrue(l.isTriggered());
244 assertSize(1, l.getEvents());
245 assertEquals("2", l.getNewValue("A", "a1"));
246
247 assertEquals("2", cc.get("A/a1").get());
248 assertEquals("2", cc.get("B/b1").get());
249 assertEquals("3", cc.get("C/c1").get());
250
251 l.reset();
252 cc.removeListener(l);
253 assertEmpty(ca.getListeners());
254 assertEmpty(cb.getListeners());
255 assertEmpty(cc.getListeners());
256
257 ms.write("A", "x=1\n[A]\na1=2", "x=1\n[A]\na1=3");
258
259 assertFalse(l.isTriggered());
260
261 assertEquals("3", cc.get("A/a1").get());
262 assertEquals("2", cc.get("B/b1").get());
263 assertEquals("3", cc.get("C/c1").get());
264 }
265
266 @Test void a03_updateOnParentSameSection() {
267 var ms = MemoryStore.create().build();
268
269 ms.write("A", "", "x=1\n[A]\na1=1");
270 ms.write("B", "", "<A>\n[A]\nb1=2");
271
272 var ca = Config.create("A").store(ms).build();
273 var cb = Config.create("B").store(ms).build();
274
275 assertSize(2, ca.getConfigMap().getListeners());
276 assertSize(1, cb.getConfigMap().getListeners());
277
278 var l = new TestListener();
279 cb.addListener(l);
280
281 ms.write("A", "x=1\n[A]\na1=1", "x=1\n[A]\na1=2");
282
283 assertTrue(l.isTriggered());
284 assertSize(1, l.getEvents());
285 assertEquals("2", l.getNewValue("A", "a1"));
286
287 assertEquals("2", cb.get("A/a1").get());
288 assertEquals("2", cb.get("A/b1").get());
289
290 l.reset();
291 cb.removeListener(l);
292 assertEmpty(ca.getListeners());
293 assertEmpty(cb.getListeners());
294
295 ms.write("A", "x=1\n[A]\na1=2", "x=1\n[A]\na1=3");
296
297 assertFalse(l.isTriggered());
298
299 assertEquals("3", cb.get("A/a1").get());
300 assertEquals("2", cb.get("A/b1").get());
301 }
302
303 @Test void a04_updateOnParentSameSectionSameKey() {
304 var ms = MemoryStore.create().build();
305
306 ms.write("A", "", "x=1\n[A]\na1=1");
307 ms.write("B", "", "<A>\n[A]\na1=2");
308
309 var ca = Config.create("A").store(ms).build();
310 var cb = Config.create("B").store(ms).build();
311
312 assertSize(2, ca.getConfigMap().getListeners());
313 assertSize(1, cb.getConfigMap().getListeners());
314
315 var l = new TestListener();
316 cb.addListener(l);
317
318 ms.write("A", "x=1\n[A]\na1=1", "x=1\n[A]\na1=3");
319
320 assertFalse(l.isTriggered());
321 assertEquals("2", cb.get("A/a1").get());
322 }
323
324 @Test void a05_updateOnGrandParentSameSection() {
325 var ms = MemoryStore.create().build();
326
327 ms.write("A", "", "x=1\n[A]\na1=1");
328 ms.write("B", "", "<A>\n[A]\na1=2");
329 ms.write("C", "", "<B>\n[A]\na1=3");
330
331 var ca = Config.create("A").store(ms).build();
332 var cb = Config.create("B").store(ms).build();
333 var cc = Config.create("C").store(ms).build();
334
335 assertSize(3, ca.getConfigMap().getListeners());
336 assertSize(2, cb.getConfigMap().getListeners());
337 assertSize(1, cc.getConfigMap().getListeners());
338
339 var l = new TestListener();
340 cc.addListener(l);
341
342 ms.write("A", "x=1\n[A]\na1=1", "x=1\n[A]\na1=4");
343
344 assertFalse(l.isTriggered());
345 assertEquals("3", cc.get("A/a1").get());
346 }
347
348
349
350
351
352 @Test void a06_updateOnParentDynamic() {
353 var ms = MemoryStore.create().build();
354
355 ms.write("A", "", "x=1\ny=1\n[A]\na1=1");
356 ms.write("B", "", "x=2\n[B]\nb1=2");
357
358 var ca = Config.create("A").store(ms).build();
359 var cb = Config.create("B").store(ms).build();
360
361 assertSize(1, ca.getConfigMap().getListeners());
362 assertSize(1, cb.getConfigMap().getListeners());
363
364 var l = new TestListener();
365 cb.addListener(l);
366
367 assertEmpty(ca.getListeners());
368 assertSize(1, cb.getListeners());
369
370 ms.write("B", "x=2\n[B]\nb1=2", "x=2\n<A>\n[B]\nb1=2");
371
372 assertTrue(l.isTriggered());
373 assertSize(2, l.getEvents());
374 assertEquals("1", l.getNewValue("A", "a1"));
375
376 assertEquals("1", cb.get("A/a1").get());
377 assertEquals("2", cb.get("B/b1").get());
378
379 assertSize(2, ca.getConfigMap().getListeners());
380 assertSize(1, cb.getConfigMap().getListeners());
381
382 l.reset();
383
384 ms.write("B", "x=2\n<A>\n[B]\nb1=2", "x=2\n[B]\nb1=2");
385
386 assertTrue(l.isTriggered());
387 assertSize(2, l.getEvents());
388 assertEquals(null, l.getNewValue("A", "a1"));
389
390 assertNull(cb.get("A/a1").orElse(null));
391 assertEquals("2", cb.get("B/b1").get());
392
393 l.reset();
394 cb.removeListener(l);
395 assertEmpty(ca.getListeners());
396 assertEmpty(cb.getListeners());
397
398 ms.write("B", "x=2\n[B]\nb1=2", "x=2\n<A>\n[B]\nb1=2");
399
400 assertFalse(l.isTriggered());
401
402 assertEquals("1", cb.get("A/a1").get());
403 assertEquals("2", cb.get("B/b1").get());
404 }
405 }