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