a853793390b4af61d1101367c348e07a65a19d7b
[vtn.git] /
1 /*
2  * Copyright (c) 2015 NEC Corporation.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.vtn.manager.internal.util;
10
11 import java.io.File;
12 import java.io.FileOutputStream;
13 import java.io.PrintStream;
14 import java.util.HashMap;
15 import java.util.Map;
16 import java.util.Set;
17 import java.util.HashSet;
18
19 import org.junit.Test;
20
21 import org.opendaylight.vtn.manager.VTenantConfig;
22 import org.opendaylight.vtn.manager.util.EtherAddress;
23
24 import org.opendaylight.vtn.manager.internal.config.VTNConfigImpl;
25
26 import org.opendaylight.vtn.manager.internal.TestBase;
27 import org.opendaylight.vtn.manager.internal.config.ConfigType;
28
29 /**
30  * JUnit test for {@link XmlConfigFile}.
31  */
32 public class XmlConfigFileTest extends TestBase {
33     /**
34      * The number of test keys.
35      */
36     private static final int  NUM_KEYS = 100;
37
38     /**
39      * Test case for {@link XmlConfigFile#init()}.
40      *
41      * @throws Exception  An error occurred.
42      */
43     @Test
44     public void testInit() throws Exception {
45         File dir = getConfigDir();
46         assertFalse(dir.exists());
47         XmlConfigFile.init();
48         assertTrue(dir.exists());
49         XmlConfigFile.Type[] types = XmlConfigFile.Type.values();
50         for (XmlConfigFile.Type type: types) {
51             File d = new File(dir, type.toString());
52             assertTrue(d.toString(), d.isDirectory());
53             assertEquals(0, d.list().length);
54         }
55         assertEquals(types.length, dir.list().length);
56
57         // Initialize again.
58         XmlConfigFile.init();
59         assertTrue(dir.exists());
60         for (XmlConfigFile.Type type: types) {
61             File d = new File(dir, type.toString());
62             assertTrue(d.toString(), d.isDirectory());
63             assertEquals(0, d.list().length);
64         }
65         assertEquals(types.length, dir.list().length);
66
67         deleteStartUpHome();
68
69         // Put unexpected regular files.
70         assertTrue(dir.mkdirs());
71         for (XmlConfigFile.Type type: types) {
72             File f = new File(dir, type.toString());
73             assertTrue(f.createNewFile());
74         }
75
76         String[] files = {
77             "aaa",
78             "bbb",
79             "ccc",
80             "ddd",
81         };
82
83         // Unexpected regular files should be deleted.
84         XmlConfigFile.init();
85         assertTrue(dir.isDirectory());
86         for (XmlConfigFile.Type type: types) {
87             File d = new File(dir, type.toString());
88             assertTrue(d.isDirectory());
89             assertEquals(0, d.list().length);
90
91             // Create files under config directories.
92             for (String file: files) {
93                 File f = new File(d, file);
94                 f.createNewFile();
95             }
96             assertEquals(files.length, d.list().length);
97         }
98         assertEquals(types.length, dir.list().length);
99     }
100
101     /**
102      * Ensure that the configuration file can be saved and loaded.
103      *
104      * @throws Exception  An error occurred.
105      */
106     @Test
107     public void testSaveLoad() throws Exception {
108         Object obj = new Object();
109         File baseDir = getConfigDir();
110         Class<VTenantConfig> cls = VTenantConfig.class;
111
112         // Try to access configuration file before initialization.
113         String badKey = "badkey";
114         XmlConfigFile.Type[] types = XmlConfigFile.Type.values();
115         VTenantConfig dummy = new VTenantConfig("tenant 1", 100, 200);
116         for (XmlConfigFile.Type type: types) {
117             assertFalse(XmlConfigFile.save(type, badKey, dummy));
118             assertEquals(null, XmlConfigFile.load(type, badKey, cls));
119             assertFalse(XmlConfigFile.delete(type, badKey));
120         }
121
122         XmlConfigFile.init();
123
124         String[] ignored = {
125             "aaa",
126             ".conf",
127             ".xml",
128             "___test___",
129         };
130         String[] badDirs = {
131             "aaa",
132             "bbb",
133             "foo",
134         };
135         String[] broken = {
136             "broken_1",
137             "broken_2",
138             "broken_3",
139         };
140         Map<XmlConfigFile.Type, Map<String, VTenantConfig>> saved =
141             new HashMap<>();
142         int idle = 0;
143         int hard = 10;
144         for (XmlConfigFile.Type type: types) {
145             Map<String, VTenantConfig> map = new HashMap<>();
146             assertEquals(null, saved.put(type, map));
147             assertEquals(0, XmlConfigFile.getKeys(type).size());
148
149             File dir = new File(baseDir, type.toString());
150             for (String fname: ignored) {
151                 File f = new File(dir, fname);
152                 assertTrue(f.createNewFile());
153             }
154             for (String dname: badDirs) {
155                 File f = new File(dir, dname + ".xml");
156                 assertTrue(f.mkdirs());
157                 assertEquals(null, XmlConfigFile.load(type, dname, cls));
158             }
159             for (String key: broken) {
160                 String fname = key + ".xml";
161                 File f = new File(dir, fname);
162                 assertTrue(f.createNewFile());
163                 assertEquals(null, map.put(key, null));
164             }
165
166             assertEquals(broken.length, XmlConfigFile.getKeys(type).size());
167
168             // Construct test data and save.
169             for (int i = 0; i < NUM_KEYS; i++) {
170                 String key = "key_" + i;
171
172                 // Try to save non-JAXB object.
173                 assertFalse(XmlConfigFile.save(type, key, obj));
174
175                 String desc = key + ": " + idle;
176                 VTenantConfig tconf = new VTenantConfig(desc, idle, hard);
177                 assertEquals(null, map.put(key, tconf));
178                 assertTrue(XmlConfigFile.save(type, key, tconf));
179
180                 Set<String> names = new HashSet<>(XmlConfigFile.getKeys(type));
181                 assertEquals(map.keySet(), names);
182                 idle++;
183                 hard++;
184             }
185             assertEquals(NUM_KEYS + broken.length, map.size());
186         }
187         assertEquals(types.length, saved.size());
188
189         // Load data from configuration files.
190         Map<XmlConfigFile.Type, Map<String, VTenantConfig>> loaded =
191             new HashMap<>();
192         for (XmlConfigFile.Type type: types) {
193             Map<String, VTenantConfig> map = new HashMap<>();
194             assertEquals(null, loaded.put(type, map));
195
196             for (String key: XmlConfigFile.getKeys(type)) {
197                 // Note that this will remove broken files.
198                 VTenantConfig tconf = XmlConfigFile.load(type, key, cls);
199                 if (key.startsWith("broken")) {
200                     assertEquals(null, tconf);
201                 } else {
202                     assertNotNull(tconf);
203                 }
204                 map.put(key, tconf);
205             }
206         }
207         assertEquals(saved, loaded);
208
209         // Delete configuration files.
210         for (XmlConfigFile.Type type: types) {
211             Map<String, VTenantConfig> map = loaded.get(type);
212             Set<String> names = new HashSet<>(XmlConfigFile.getKeys(type));
213             for (Map.Entry<String, VTenantConfig> entry: map.entrySet()) {
214                 String key = entry.getKey();
215                 VTenantConfig tconf = entry.getValue();
216                 if (key.startsWith("broken")) {
217                     assertEquals(null, XmlConfigFile.load(type, key, cls));
218                     assertFalse(XmlConfigFile.delete(type, key));
219                 } else {
220                     assertEquals(tconf, XmlConfigFile.load(type, key, cls));
221                     assertTrue(XmlConfigFile.delete(type, key));
222                     assertTrue(names.remove(key));
223                 }
224                 assertEquals(null, XmlConfigFile.load(type, key, cls));
225                 Set<String> keys = new HashSet<>(XmlConfigFile.getKeys(type));
226                 assertEquals(names, keys);
227             }
228         }
229     }
230
231     /**
232      * Test case for {@link XmlConfigFile#deleteAll(org.opendaylight.vtn.manager.internal.util.XmlConfigFile.Type, Set)}.
233      */
234     @Test
235     public void testDeleteAll() {
236         File baseDir = getConfigDir();
237
238         // Try to access configuration file before initialization.
239         XmlConfigFile.Type[] types = XmlConfigFile.Type.values();
240         for (XmlConfigFile.Type type: types) {
241             assertFalse(XmlConfigFile.deleteAll(type, null));
242         }
243
244         XmlConfigFile.init();
245
246         for (XmlConfigFile.Type type: types) {
247             assertTrue(XmlConfigFile.deleteAll(type, null));
248         }
249
250         // Construct test data and save.
251         for (XmlConfigFile.Type type: types) {
252             int idle = 0;
253             int hard = 10;
254             Set<String> retain = new HashSet<>();
255             Map<String, VTenantConfig> saved = new HashMap<>();
256             for (int i = 0; i < NUM_KEYS; i++) {
257                 String key = "key_" + i;
258                 String desc = key + ": " + idle;
259                 VTenantConfig tconf = new VTenantConfig(desc, idle, hard);
260                 assertEquals(null, saved.put(key, tconf));
261                 assertTrue(XmlConfigFile.save(type, key, tconf));
262                 if ((i % 4) == 0) {
263                     assertTrue(retain.add(key));
264                 }
265                 idle++;
266                 hard++;
267             }
268             assertFalse(retain.isEmpty());
269
270             Set<String> names = new HashSet<>(XmlConfigFile.getKeys(type));
271             assertEquals(saved.keySet(), names);
272
273             // Remove all files except for files in "retain".
274             assertTrue(XmlConfigFile.deleteAll(type, retain));
275             names = new HashSet<>(XmlConfigFile.getKeys(type));
276             assertEquals(retain, names);
277
278             // Remove all files.
279             assertTrue(XmlConfigFile.deleteAll(type, null));
280             assertEquals(0, XmlConfigFile.getKeys(type).size());
281         }
282     }
283
284     /**
285      * Ensure that {@link XmlConfigFile#load(org.opendaylight.vtn.manager.internal.util.XmlConfigFile.Type, String, Class)}
286      * can detect an error in JAXB annotated method.
287      *
288      * @throws Exception  An error occurred.
289      */
290     @Test
291     public void testLoad() throws Exception {
292         XmlConfigFile.init();
293         XmlConfigFile.Type type = XmlConfigFile.Type.CONFIG;
294
295         // Write configuration with the minimum values.
296         String minimum = "minimum";
297         EtherAddress minMac = new EtherAddress(0L);
298         File baseDir = getConfigDir();
299         File dir = new File(baseDir, type.toString());
300         File file = new File(dir, minimum + ".xml");
301         PrintStream ps = new PrintStream(new FileOutputStream(file));
302         ps.printf("<vtn-config>\n");
303         ConfigType[] configTypes = ConfigType.values();
304         for (ConfigType ctype: configTypes) {
305             Object min = ctype.getMinimumValue();
306             if (min == null) {
307                 min = minMac;
308             }
309             ps.println(ctype.getXmlElement(min));
310         }
311         ps.printf("</vtn-config>\n");
312         ps.close();
313
314         // Write configuration with the maximum values.
315         String maximum = "maximum";
316         EtherAddress maxMac = new EtherAddress(0xffffffffffffL);
317         file = new File(dir, maximum + ".xml");
318         ps = new PrintStream(new FileOutputStream(file));
319         ps.printf("<vtn-config>\n");
320         for (ConfigType ctype: configTypes) {
321             Object max = ctype.getMaximumValue();
322             if (max == null) {
323                 max = maxMac;
324             }
325             ps.println(ctype.getXmlElement(max));
326         }
327         ps.printf("</vtn-config>\n");
328         ps.close();
329
330         Class<VTNConfigImpl> cls = VTNConfigImpl.class;
331         for (int i = 0; i < 2; i++) {
332             VTNConfigImpl min = XmlConfigFile.load(type, minimum, cls);
333             assertNotNull(min);
334             for (ConfigType ctype: configTypes) {
335                 Object value = ctype.get(min);
336                 Object expected = ctype.getMinimumValue();
337                 if (expected == null) {
338                     expected = minMac;
339                 }
340                 assertEquals(expected, value);
341             }
342
343             VTNConfigImpl max = XmlConfigFile.load(type, maximum, cls);
344             assertNotNull(max);
345             for (ConfigType ctype: configTypes) {
346                 Object value = ctype.get(max);
347                 Object expected = ctype.getMaximumValue();
348                 if (expected == null) {
349                     expected = maxMac;
350                 }
351                 assertEquals(expected, value);
352             }
353         }
354
355         // Test with broken value.
356         String bad = "bad";
357         for (ConfigType ctype: configTypes) {
358             file = new File(dir, bad + ".xml");
359             ps = new PrintStream(new FileOutputStream(file));
360             ps.printf("<vtn-config>\n");
361             ps.println(ctype.getXmlElement("bad value"));
362             ps.printf("</vtn-config>\n");
363             ps.close();
364             assertEquals(true, file.isFile());
365             assertEquals(ctype.toString(), null,
366                          XmlConfigFile.load(type, bad, cls));
367             assertEquals(false, file.isFile());
368         }
369
370         // Test with too small values.
371         for (ConfigType ctype: configTypes) {
372             Object o = ctype.getMinimumValue();
373             if (o == null) {
374                 continue;
375             }
376             assertTrue(o instanceof Integer);
377             Integer min = (Integer)o;
378             Integer value = Integer.valueOf(min.intValue() - 1);
379
380             file = new File(dir, bad + ".xml");
381             ps = new PrintStream(new FileOutputStream(file));
382             ps.printf("<vtn-config>\n");
383             ps.println(ctype.getXmlElement(value));
384             ps.printf("</vtn-config>\n");
385             ps.close();
386             assertEquals(true, file.isFile());
387             assertEquals(String.format("%s -> %s", ctype, value),
388                          null, XmlConfigFile.load(type, bad, cls));
389             assertEquals(false, file.isFile());
390         }
391
392         // Test with too large values.
393         for (ConfigType ctype: configTypes) {
394             Object o = ctype.getMaximumValue();
395             if (o == null) {
396                 continue;
397             }
398             assertTrue(o instanceof Integer);
399             Integer max = (Integer)o;
400             Integer value = Integer.valueOf(max.intValue() + 1);
401
402             file = new File(dir, bad + ".xml");
403             ps = new PrintStream(new FileOutputStream(file));
404             ps.printf("<vtn-config>\n");
405             ps.println(ctype.getXmlElement(value));
406             ps.printf("</vtn-config>\n");
407             ps.close();
408             assertEquals(true, file.isFile());
409             assertEquals(String.format("%s -> %s", ctype, value),
410                          null, XmlConfigFile.load(type, bad, cls));
411             assertEquals(false, file.isFile());
412         }
413     }
414 }