1 #include <cxxtest/TestSuite.h>
3 #include "svg/svg-length.h"
4 #include <glib.h>
5 #include <utility>
7 // function internal to svg-length.cpp:
8 gchar const *sp_svg_length_get_css_units(SVGLength::Unit unit);
10 class SvgLengthTest : public CxxTest::TestSuite
11 {
12 private:
13 struct test_t {
14 char const* str; SVGLength::Unit unit; float value; float computed;
15 };
16 struct testd_t {
17 char const* str; double val; int prec; int minexp;
18 };
19 static test_t const absolute_tests[12];
20 static test_t const relative_tests[3];
21 static char const * fail_tests[8];
23 public:
24 SvgLengthTest() {
25 }
27 // createSuite and destroySuite get us per-suite setup and teardown
28 // without us having to worry about static initialization order, etc.
29 static SvgLengthTest *createSuite() { return new SvgLengthTest(); }
30 static void destroySuite( SvgLengthTest *suite ) { delete suite; }
32 void testRead()
33 {
34 for(size_t i=0; i<G_N_ELEMENTS(absolute_tests); i++) {
35 SVGLength len;
36 TSM_ASSERT(absolute_tests[i].str , len.read(absolute_tests[i].str));
37 TSM_ASSERT_EQUALS(absolute_tests[i].str , len.unit , absolute_tests[i].unit);
38 TSM_ASSERT_EQUALS(absolute_tests[i].str , len.value , absolute_tests[i].value);
39 TSM_ASSERT_EQUALS(absolute_tests[i].str , len.computed , absolute_tests[i].computed);
40 }
41 for(size_t i=0; i<G_N_ELEMENTS(relative_tests); i++) {
42 SVGLength len;
43 TSM_ASSERT(relative_tests[i].str , len.read(relative_tests[i].str));
44 len.update(7,13,19);
45 TSM_ASSERT_EQUALS(relative_tests[i].str , len.unit , relative_tests[i].unit);
46 TSM_ASSERT_EQUALS(relative_tests[i].str , len.value , relative_tests[i].value);
47 TSM_ASSERT_EQUALS(relative_tests[i].str , len.computed , relative_tests[i].computed);
48 }
49 for(size_t i=0; i<G_N_ELEMENTS(fail_tests); i++) {
50 SVGLength len;
51 TSM_ASSERT(fail_tests[i] , !len.read(fail_tests[i]));
52 }
53 }
55 void testReadOrUnset()
56 {
57 for(size_t i=0; i<G_N_ELEMENTS(absolute_tests); i++) {
58 SVGLength len;
59 len.readOrUnset(absolute_tests[i].str);
60 TSM_ASSERT_EQUALS(absolute_tests[i].str , len.unit , absolute_tests[i].unit);
61 TSM_ASSERT_EQUALS(absolute_tests[i].str , len.value , absolute_tests[i].value);
62 TSM_ASSERT_EQUALS(absolute_tests[i].str , len.computed , absolute_tests[i].computed);
63 }
64 for(size_t i=0; i<G_N_ELEMENTS(relative_tests); i++) {
65 SVGLength len;
66 len.readOrUnset(relative_tests[i].str);
67 len.update(7,13,19);
68 TSM_ASSERT_EQUALS(relative_tests[i].str , len.unit , relative_tests[i].unit);
69 TSM_ASSERT_EQUALS(relative_tests[i].str , len.value , relative_tests[i].value);
70 TSM_ASSERT_EQUALS(relative_tests[i].str , len.computed , relative_tests[i].computed);
71 }
72 for(size_t i=0; i<G_N_ELEMENTS(fail_tests); i++) {
73 SVGLength len;
74 len.readOrUnset(fail_tests[i], SVGLength::INCH, 123, 456);
75 TSM_ASSERT_EQUALS(fail_tests[i] , len.unit , SVGLength::INCH);
76 TSM_ASSERT_EQUALS(fail_tests[i] , len.value , 123);
77 TSM_ASSERT_EQUALS(fail_tests[i] , len.computed , 456);
78 }
79 }
81 void testReadAbsolute()
82 {
83 for(size_t i=0; i<G_N_ELEMENTS(absolute_tests); i++) {
84 SVGLength len;
85 TSM_ASSERT(absolute_tests[i].str , len.readAbsolute(absolute_tests[i].str));
86 TSM_ASSERT_EQUALS(absolute_tests[i].str , len.unit , absolute_tests[i].unit);
87 TSM_ASSERT_EQUALS(absolute_tests[i].str , len.value , absolute_tests[i].value);
88 TSM_ASSERT_EQUALS(absolute_tests[i].str , len.computed , absolute_tests[i].computed);
89 }
90 for(size_t i=0; i<G_N_ELEMENTS(relative_tests); i++) {
91 SVGLength len;
92 TSM_ASSERT(relative_tests[i].str , !len.readAbsolute(relative_tests[i].str));
93 }
94 for(size_t i=0; i<G_N_ELEMENTS(fail_tests); i++) {
95 SVGLength len;
96 TSM_ASSERT(fail_tests[i] , !len.readAbsolute(fail_tests[i]));
97 }
98 }
100 void testEnumMappedToString()
101 {
102 for ( int i = (static_cast<int>(SVGLength::NONE) + 1); i <= static_cast<int>(SVGLength::LAST_UNIT); i++ ) {
103 SVGLength::Unit target = static_cast<SVGLength::Unit>(i);
104 // PX is a special case where we don't have a unit string
105 if ( (target != SVGLength::PX) && (target != SVGLength::FOOT) ) {
106 gchar const* val = sp_svg_length_get_css_units(target);
107 TSM_ASSERT_DIFFERS(i, val, "");
108 }
109 }
110 }
112 // Ensure that all unit suffix strings used are allowed by SVG
113 void testStringsAreValidSVG()
114 {
115 gchar const* valid[] = {"", "em", "ex", "px", "pt", "pc", "cm", "mm", "in", "%"};
116 std::set<std::string> validStrings(valid, valid + G_N_ELEMENTS(valid));
117 for ( int i = (static_cast<int>(SVGLength::NONE) + 1); i <= static_cast<int>(SVGLength::LAST_UNIT); i++ ) {
118 SVGLength::Unit target = static_cast<SVGLength::Unit>(i);
119 gchar const* val = sp_svg_length_get_css_units(target);
120 TSM_ASSERT(i, validStrings.find(std::string(val)) != validStrings.end());
121 }
122 }
124 // Ensure that all unit suffix strings allowed by SVG are covered by enum
125 void testValidSVGStringsSupported()
126 {
127 // Note that "px" is ommitted from the list, as it will be assumed to be so if not explicitly set.
128 gchar const* valid[] = {"em", "ex", "pt", "pc", "cm", "mm", "in", "%"};
129 std::set<std::string> validStrings(valid, valid + G_N_ELEMENTS(valid));
130 for ( int i = (static_cast<int>(SVGLength::NONE) + 1); i <= static_cast<int>(SVGLength::LAST_UNIT); i++ ) {
131 SVGLength::Unit target = static_cast<SVGLength::Unit>(i);
132 gchar const* val = sp_svg_length_get_css_units(target);
133 std::set<std::string>::iterator iter = validStrings.find(std::string(val));
134 if (iter != validStrings.end()) {
135 validStrings.erase(iter);
136 }
137 }
138 TSM_ASSERT_EQUALS(validStrings, validStrings.size(), 0u);
139 }
141 void testPlaces()
142 {
143 testd_t const precTests[] = {
144 {"760", 761.92918978947023, 2, -8},
145 {"761.9", 761.92918978947023, 4, -8},
146 };
148 for ( size_t i = 0; i < G_N_ELEMENTS(precTests); i++ ) {
149 char buf[256] = {0};
150 memset(buf, 0xCC, sizeof(buf)); // Make it easy to detect an overrun.
151 unsigned int retval = sp_svg_number_write_de( buf, sizeof(buf), precTests[i].val, precTests[i].prec, precTests[i].minexp );
152 TSM_ASSERT_EQUALS("Number of chars written", retval, strlen(precTests[i].str));
153 TSM_ASSERT_EQUALS("Numeric string written", std::string(buf), std::string(precTests[i].str));
154 TSM_ASSERT_EQUALS(std::string("Buffer overrun ") + precTests[i].str, '\xCC', buf[retval + 1]);
155 }
156 }
158 // TODO: More tests
159 };
161 SvgLengthTest::test_t const SvgLengthTest::absolute_tests[12] = {
162 {"0", SVGLength::NONE, 0 , 0},
163 {"1", SVGLength::NONE, 1 , 1},
164 {"1.00001", SVGLength::NONE, 1.00001 , 1.00001},
165 {"1px", SVGLength::PX , 1 , 1},
166 {".1px", SVGLength::PX , 0.1 , 0.1},
167 {"100pt", SVGLength::PT , 100 , 125},
168 {"1e2pt", SVGLength::PT , 100 , 125},
169 {"3pc", SVGLength::PC , 3 , 45},
170 {"-3.5pc", SVGLength::PC , -3.5 , -3.5*15.},
171 {"1.2345678mm", SVGLength::MM , 1.2345678, 1.2345678*3.543307}, // TODO: More precise constants? (a 7 digit constant when the default precision is 8 digits?)
172 {"123.45678cm", SVGLength::CM , 123.45678 , 123.45678*35.43307},
173 {"73.162987in", SVGLength::INCH, 73.162987 , 73.162987*90}};
174 SvgLengthTest::test_t const SvgLengthTest::relative_tests[3] = {
175 {"123em", SVGLength::EM, 123, 123. * 7.},
176 {"123ex", SVGLength::EX, 123, 123. * 13.},
177 {"123%", SVGLength::PERCENT, 1.23, 1.23 * 19.}};
178 char const * SvgLengthTest::fail_tests[8] = {
179 "123 px",
180 "123e",
181 "123e+m",
182 "123ec",
183 "123pxt",
184 "--123",
185 "",
186 "px"};
188 /*
189 Local Variables:
190 mode:c++
191 c-file-style:"stroustrup"
192 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
193 indent-tabs-mode:nil
194 fill-column:99
195 End:
196 */
197 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :