1 module dunitconversion.tests.convertor;
2 
3 import dunitconversion.convertor;
4 import dunitconversion.linearfunction;
5 import dunitconversion.conversionfamily;
6 import dunitconversion.conversionrule;
7 import dunitconversion.aliasdictionary;
8 
9 import std.exception;
10 import std.math;
11 import std.algorithm;
12 import std.file;
13 import std.json;
14 
15 unittest {
16     auto convertor = new UnitConvertor;
17 
18     convertor.addConversionRule(ConversionRule("length", "m", "km", LinearFunction(0.001, 0)));
19 
20     assert("length" in convertor.m_families);
21     assert("length" in convertor.m_baseUnitsByFamilies);
22     assert("m" in convertor.m_familiesByUnit);
23     assert("km" in convertor.m_familiesByUnit);
24     assert(convertor.m_familiesByUnit.length == 2);
25     assert(convertor.m_families.length == 1);
26     assert(convertor.m_baseUnitsByFamilies.length == 1);
27 
28     convertor.addConversionRule(ConversionRule("length", "m", "cm", LinearFunction(100, 0)));
29     assert("m" in convertor.m_familiesByUnit);
30     assert("km" in convertor.m_familiesByUnit);
31     assert("cm" in convertor.m_familiesByUnit);
32     assert(convertor.m_familiesByUnit.length == 3);
33     assert(convertor.m_families.length == 1);
34     assert(convertor.m_baseUnitsByFamilies.length == 1);
35 
36     convertor.addConversionRule(ConversionRule("length", "m", "mm", LinearFunction(1000, 0)));
37     assert("m" in convertor.m_familiesByUnit);
38     assert("km" in convertor.m_familiesByUnit);
39     assert("cm" in convertor.m_familiesByUnit);
40     assert("mm" in convertor.m_familiesByUnit);
41     assert(convertor.m_familiesByUnit.length == 4);
42     assert(convertor.m_families.length == 1);
43     assert(convertor.m_baseUnitsByFamilies.length == 1);
44 
45     // assert("length" in convertor.m_families());
46 
47     // passing existing family with a differnt base unit
48     assertThrown!Exception(
49         convertor.addConversionRule(ConversionRule("length", "km", "m", LinearFunction(1000, 0))));
50 
51     // passing a different family with an existing base unit
52     assertThrown!Exception(
53         convertor.addConversionRule(ConversionRule("notlength", "m", "km", LinearFunction(0.001, 0))));
54 
55     // passing the same conversion once again should work
56     convertor.addConversionRule(ConversionRule("length", "m", "mm", LinearFunction(1000, 0)));
57 
58     // let's make sure that none of containers did change
59     assert(convertor.m_familiesByUnit.length == 4);
60     assert(convertor.m_families.length == 1);
61     assert(convertor.m_baseUnitsByFamilies.length == 1);
62 
63     // note "min" here, since we have to make sure that all unit names are different
64     // we need to differ minutes from meters
65     convertor.addConversionRule(ConversionRule("time", "s", "min", LinearFunction(double(1) / 60, 0)));
66     assert("length" in convertor.m_families);
67     assert("time" in convertor.m_families);
68     assert(convertor.m_families.length == 2);
69     assert("m" in convertor.m_familiesByUnit);
70     assert("km" in convertor.m_familiesByUnit);
71     assert("cm" in convertor.m_familiesByUnit);
72     assert("mm" in convertor.m_familiesByUnit);
73     assert("s" in convertor.m_familiesByUnit);
74     assert("min" in convertor.m_familiesByUnit);
75     assert("length" in convertor.m_baseUnitsByFamilies);
76     assert("time" in convertor.m_baseUnitsByFamilies);
77     assert(convertor.m_baseUnitsByFamilies["length"] == "m");
78     assert(convertor.m_baseUnitsByFamilies["time"] == "s");
79 
80     auto families = convertor.families();
81     assert(families.canFind("length"));
82     assert(families.canFind("time"));
83 
84     auto units = convertor.units("length");
85     assert(units.length == 4);
86     assert(units.canFind("m"));
87     assert(units.canFind("km"));
88     assert(units.canFind("cm"));
89     assert(units.canFind("mm"));
90 
91     assert(approxEqual(convertor.convert(0, "m", "km"), 0));
92     assert(approxEqual(convertor.convert(50, "m", "km"), 0.05));
93     assert(approxEqual(convertor.convert(50, "km", "m"), 50_000));
94     assert(approxEqual(convertor.convert(500, "cm", "m"), 5));
95     assert(approxEqual(convertor.convert(500, "cm", "km"), 0.005));
96     assert(approxEqual(convertor.convert(500, "m", "m"), 500));
97 
98     auto conversions = convertor.conversions("m");
99     assert(conversions.canFind("m"));
100     assert(conversions.canFind("km"));
101     assert(conversions.canFind("cm"));
102     assert(conversions.canFind("mm"));
103     assert(conversions.length == 4);
104 
105     conversions = convertor.conversions("mm");
106     assert(conversions.canFind("m"));
107     assert(conversions.canFind("km"));
108     assert(conversions.canFind("cm"));
109     assert(conversions.canFind("mm"));
110     assert(conversions.length == 4);
111 
112     conversions = convertor.conversions("mmmm");
113     assert(conversions is null);
114 
115     assert(convertor.family("m") == "length");
116     assert(convertor.family("km") == "length");
117     assertThrown!Exception(convertor.family("mmmmm"));
118 }
119 
120 unittest {
121     auto convertor = new UnitConvertor;
122 
123     convertor.loadFromJson(parseJSON(readText("./test/conversion_rules.json")));
124     convertor.loadAliasesFromJson(parseJSON(readText("./test/aliases.json")));
125 
126     // conversion to an actual unit
127     assert(approxEqual(convertor.convert(0, "m", "km"), 0));
128     assert(approxEqual(convertor.convert(50, "m", "km"), 0.05));
129     assert(approxEqual(convertor.convert(50, "km", "m"), 50_000));
130     assert(approxEqual(convertor.convert(500, "cm", "m"), 5));
131     assert(approxEqual(convertor.convert(500, "cm", "km"), 0.005));
132 
133     assert(approxEqual(convertor.convert(50, "m/s", "km/h"), 180));
134     assert(approxEqual(convertor.convert(50, "m/s", "kmph"), 180));
135     assert(approxEqual(convertor.convert(50, "m/s", "kmh"), 180));
136     assert(approxEqual(convertor.convert(50, "mps", "km/h"), 180));
137     assert(approxEqual(convertor.convert(50, "mps", "kmph"), 180));
138     assert(approxEqual(convertor.convert(50, "mps", "kmh"), 180));
139 
140     assert(approxEqual(convertor.convert(0, "meter", "km"), 0));
141     assert(approxEqual(convertor.convert(50, "meters", "km"), 0.05));
142 
143     assert(approxEqual(convertor.convert(100, "C", "K"), 373.15));
144 
145     assert(approxEqual(convertor.convert(-40, "C", "F"), -40));
146     
147     assert(convertor.family("m") == "length");
148     assert(convertor.family("km") == "length");
149 
150     // should retrieve correct family for unit aliases as well
151     assert(convertor.family("meter") == "length");
152     assert(convertor.family("meters") == "length");
153     
154     assertThrown!Exception(convertor.family("mmmmm"));
155 }