1 module d_properties;
2 
3 public import d_properties.properties;
4 public import d_properties.writer;
5 public import d_properties.reader;
6 
7 unittest {
8     import std.format;
9     import std.file;
10     import std.stdio;
11 
12     // First test all valid cases.
13 
14     void readWriteValidTest(uint testCase) {
15         string filename = format("test_cases/valid/%d.properties", testCase);
16         string outFilename = format("test_cases/valid/%d-out.properties", testCase);
17         auto p1 = Properties(filename);
18         p1.writeToFile(outFilename);
19         auto p2 = Properties(outFilename);
20         remove(outFilename); // Remove the extra file now that we're done.
21         assert(p1 == p2, "Properties are not equal after read/write cycle.");
22     }
23 
24     readWriteValidTest(1);
25     readWriteValidTest(2);
26 
27     // Test some specifics to ensure reading produces the expected values.
28     auto p = Properties("test_cases/valid/2.properties");
29     assert("my.value" in p);
30     assert(p["my.value"] == "Hello world!");
31     assert(p["another.value"] == "\"This is a quoted string\"");
32     assert(p["This is an indented value"] == "12345");
33     assert(p.get!int("This is an indented value") == 12_345);
34     import std.conv : ConvException;
35     try {
36         p.get!char("This is an indented value");
37         assert(false); // We expect an exception to be thrown.
38     } catch (ConvException e) {
39         // All good.
40     }
41     assert(p["multiline_2"] == "abc");
42     assert("missing_key" !in p);
43     assert(p.get("missing_key", "none") == "none");
44     p["missing_key"] = "yes";
45     assert("missing_key" in p);
46 
47     // Test property overwriting.
48     p = Properties("test_cases/valid/2.properties", "test_cases/valid/3.properties");
49     assert(p["my.value"] == "Goodbye world!");
50     assert(p["another.value"] == "test");
51 
52     p = Properties("test_cases/valid/3.properties", "test_cases/valid/2.properties");
53     assert(p["my.value"] == "Hello world!");
54     assert(p["another.value"] == "\"This is a quoted string\"");
55 
56     p = Properties("test_cases/valid/2.properties");
57     auto p2 = Properties("test_cases/valid/3.properties");
58     p.addAll(p2);
59     assert(p["my.value"] == "Goodbye world!");
60     p.addAll("test_cases/valid/1.properties");
61     assert("language" in p);
62 
63     // Test property subsets.
64     p = Properties("test_cases/valid/subs.properties");
65     auto one = p.getAll("one");
66     assert(one["a"] == "1");
67     assert(one["b"] == "2");
68     assert(one["c"] == "3");
69     assert(!one.has("name"));
70     assert(!one.has("url"));
71     auto two = p.getAll("two");
72     assert(two["name"] == "Andrew");
73     assert(two["url"] == "google.com");
74     assert(!two.has("a"));
75     assert(!two.has("b"));
76     assert(!two.has("c"));
77 
78     struct TestOne {
79         int a, b, c;
80     }
81     auto oneStruct = p.getAll!TestOne("one");
82     assert(oneStruct.a == 1);
83     assert(oneStruct.b == 2);
84     assert(oneStruct.c == 3);
85 
86     // Then test all invalid cases, one-by-one, to check line number and/or message.
87 
88     try {
89         readFromFile("test_cases/invalid/1.json");
90     } catch (PropertiesParseException e) {
91         assert(e.lineNumber == 1);
92     }
93 
94     try {
95         readFromFile("test_cases/invalid/2.properties");
96     } catch (PropertiesParseException e) {
97         assert(e.lineNumber == 2);
98     }
99 
100     try {
101         readFromFile("test_cases/invalid/3.properties");
102     } catch (PropertiesParseException e) {
103         assert(e.lineNumber == 3);
104     }
105 }