Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include <sal/config.h>
11 : #include <test/bootstrapfixture.hxx>
12 :
13 : #include <vcl/svapp.hxx>
14 : #include <smdll.hxx>
15 :
16 : #include <document.hxx>
17 : #include <node.hxx>
18 : #include <visitors.hxx>
19 : #include <cursor.hxx>
20 :
21 : typedef tools::SvRef<SmDocShell> SmDocShellRef;
22 :
23 : using namespace ::com::sun::star;
24 :
25 : namespace {
26 :
27 102 : class Test : public test::BootstrapFixture {
28 :
29 : public:
30 : // init
31 : virtual void setUp() SAL_OVERRIDE;
32 : virtual void tearDown() SAL_OVERRIDE;
33 :
34 : // tests
35 : void SimpleUnaryOp();
36 : void SimpleBinaryOp();
37 : void SimpleRelationalOp();
38 : void SimpleSetOp();
39 : void SimpleFunctions();
40 : void SimpleOperators();
41 : void SimpleAttributes();
42 : void SimpleMisc();
43 : void SimpleBrackets();
44 : void SimpleFormats();
45 : void SimpleGreekChars();
46 : void SimpleSpecialChars();
47 : void testBinomInBinHor();
48 : void testBinVerInUnary();
49 : void testBinHorInSubSup();
50 : void testUnaryInMixedNumberAsNumerator();
51 : void testMiscEquivalent();
52 :
53 4 : CPPUNIT_TEST_SUITE(Test);
54 2 : CPPUNIT_TEST(SimpleUnaryOp);
55 2 : CPPUNIT_TEST(SimpleBinaryOp);
56 2 : CPPUNIT_TEST(SimpleRelationalOp);
57 2 : CPPUNIT_TEST(SimpleSetOp);
58 2 : CPPUNIT_TEST(SimpleFunctions);
59 2 : CPPUNIT_TEST(SimpleOperators);
60 2 : CPPUNIT_TEST(SimpleAttributes);
61 2 : CPPUNIT_TEST(SimpleMisc);
62 2 : CPPUNIT_TEST(SimpleBrackets);
63 2 : CPPUNIT_TEST(SimpleFormats);
64 2 : CPPUNIT_TEST(SimpleGreekChars);
65 2 : CPPUNIT_TEST(SimpleSpecialChars);
66 2 : CPPUNIT_TEST(testBinomInBinHor);
67 2 : CPPUNIT_TEST(testBinVerInUnary);
68 2 : CPPUNIT_TEST(testBinHorInSubSup);
69 2 : CPPUNIT_TEST(testUnaryInMixedNumberAsNumerator);
70 2 : CPPUNIT_TEST(testMiscEquivalent);
71 4 : CPPUNIT_TEST_SUITE_END();
72 :
73 : private:
74 : uno::Reference< uno::XComponentContext > m_context;
75 : SmDocShellRef xDocShRef;
76 : void parseandparseagain(const char *input, const char *test_name);
77 : void ParseAndCheck(const char *input, const char *expected, const char *test_name);
78 : void ParseAndCompare(const char *formula1, const char *formula2, const char *test_name);
79 : };
80 :
81 34 : void Test::setUp()
82 : {
83 34 : BootstrapFixture::setUp();
84 :
85 34 : SmGlobals::ensure();
86 :
87 34 : xDocShRef = new SmDocShell(SFXOBJECTSHELL_STD_NORMAL);
88 34 : }
89 :
90 34 : void Test::tearDown()
91 : {
92 34 : xDocShRef.Clear();
93 34 : BootstrapFixture::tearDown();
94 34 : }
95 :
96 : /*
97 : * Most of the formula commands in this file came from:
98 : * http://wiki.openoffice.org/wiki/Template:Math_commands_reference
99 : * which was licensed with a
100 : * Creative Common Attribution 3.0 license and written by:
101 : * Jeanweber, Weegreenblobbie, Jdpipe, TJFrazier, Ysangkok, B michaelsen, Spellbreaker
102 : */
103 :
104 2 : void Test::SimpleUnaryOp()
105 : {
106 2 : parseandparseagain("+1", "Positive (plus)");
107 2 : parseandparseagain("-2", "Negative (minus)");
108 2 : parseandparseagain("+-3", "Plus/minus");
109 2 : parseandparseagain("-+4", "Minus/plus");
110 2 : parseandparseagain("neg a", "Boolean 'not'");
111 2 : parseandparseagain("fact a", "Factorial");
112 2 : parseandparseagain(" - { 1 over 2 } ", "BinVer in Unary 1");
113 2 : ParseAndCheck(" - { 1 over 2 } ", " - { 1 over 2 } ", "BinVer in Unary 1");
114 2 : parseandparseagain(" { - { 1 over 2 } } ", "BinVer in Unary 2");
115 2 : parseandparseagain(" - 1 over 2 ", "Unary in BinVer as numerator 1");
116 2 : parseandparseagain(" { - 1 } over 2 ", "Unary in BinVer as numerator 2");
117 2 : parseandparseagain(" 1 over - 2 ", "Unary in BinVer as denominator 1");
118 2 : parseandparseagain(" 1 over { - 2 } ", "Unary in BinVer as denominator 2");
119 2 : parseandparseagain(" 2 { - 1 over 2 } ", "Mixed number with Unary in denominator 1");
120 2 : parseandparseagain(" 2 { - 1 } over 2 ", "Mixed number with Unary in denominator 2");
121 2 : parseandparseagain(" - 1 + 2 ", "Unary in BinHor");
122 2 : }
123 :
124 2 : void Test::SimpleBinaryOp()
125 : {
126 2 : parseandparseagain("a + b", "Addition");
127 2 : parseandparseagain("a cdot b", "Dot product");
128 2 : parseandparseagain("a times b", "Cross product");
129 2 : parseandparseagain("a * b", "Multiplication (asterisk)");
130 2 : parseandparseagain("a and b", "Boolean 'and'");
131 2 : parseandparseagain("a - b", "Subtraction");
132 2 : parseandparseagain("a over b", "Division (as a fraction)");
133 2 : parseandparseagain("a div b", "Division (as an operator)");
134 2 : parseandparseagain("a / b", "Division (with a slash)");
135 2 : parseandparseagain("a or b", "Boolean 'or'");
136 2 : parseandparseagain("a circ b", "Concatenation");
137 2 : }
138 :
139 2 : void Test::SimpleRelationalOp()
140 : {
141 2 : parseandparseagain("a = b", "Is equal");
142 2 : parseandparseagain("a <> b", "Is not equal");
143 2 : parseandparseagain("a approx 2", "Approximately");
144 2 : parseandparseagain("a divides b", "Divides");
145 2 : parseandparseagain("a ndivides b", "Does not divide");
146 2 : parseandparseagain("a < 2", "Less than");
147 2 : parseandparseagain("a > 2", "Greater than");
148 2 : parseandparseagain("a simeq b", "Similar to or equal");
149 2 : parseandparseagain("a parallel b", "Parallel");
150 2 : parseandparseagain("a ortho b", "Orthogonal to");
151 2 : parseandparseagain("a leslant b", "Less than or equal to");
152 2 : parseandparseagain("a geslant b", "Greater than or equal to");
153 2 : parseandparseagain("a sim b", "Similar to");
154 2 : parseandparseagain("a equiv b", "Congruent");
155 2 : parseandparseagain("a <= b", "Less than or equal to");
156 2 : parseandparseagain("a >= b", "Greater than or equal to");
157 2 : parseandparseagain("a prop b", "Proportional");
158 2 : parseandparseagain("a toward b", "Toward");
159 2 : parseandparseagain("a dlarrow b", "Arrow left");
160 2 : parseandparseagain("a dlrarrow b", "Double arrow left and right");
161 2 : parseandparseagain("drarrow b", "Arrow right");
162 2 : }
163 :
164 2 : void Test::SimpleSetOp()
165 : {
166 2 : parseandparseagain("a in B", "Is in");
167 2 : parseandparseagain("a notin B", "Is not in");
168 2 : parseandparseagain("A owns b", "Owns");
169 2 : parseandparseagain("emptyset", "Empty set");
170 2 : parseandparseagain("A intersection B", "Intersection");
171 2 : parseandparseagain("A union B", "Union");
172 2 : parseandparseagain("A setminus B", "Difference");
173 2 : parseandparseagain("A slash B", "Quotient");
174 2 : parseandparseagain("aleph", "Aleph");
175 2 : parseandparseagain("A subset B", "Subset");
176 2 : parseandparseagain("A subseteq B", "Subset or equal to");
177 2 : parseandparseagain("A supset B", "Superset");
178 2 : parseandparseagain("A supseteq B", "Superset or equal to");
179 2 : parseandparseagain("A nsubset B", "Not subset");
180 2 : parseandparseagain("A nsubseteq B", "Not subset or equal");
181 2 : parseandparseagain("A nsupset B", "Not superset");
182 2 : parseandparseagain("A nsupseteq B", "Not superset or equal");
183 2 : parseandparseagain("setN", "Set of natural numbers");
184 2 : parseandparseagain("setZ", "Set of integers");
185 2 : parseandparseagain("setQ", "Set of rational numbers");
186 2 : parseandparseagain("setR", "Set of real numbers");
187 2 : parseandparseagain("setC", "Set of complex numbers");
188 2 : }
189 :
190 2 : void Test::SimpleFunctions()
191 : {
192 2 : parseandparseagain("func e^{a}", "Exponential");
193 2 : parseandparseagain("ln(a)", "Natural logarithm");
194 2 : parseandparseagain("exp(a)", "Exponential function");
195 2 : parseandparseagain("log(a)", "Logarithm");
196 2 : parseandparseagain("a^{b}", "Power");
197 2 : parseandparseagain("sin(a)", "Sine");
198 2 : parseandparseagain("cos(a)", "Cosine");
199 2 : parseandparseagain("tan(a)", "Tangent");
200 2 : parseandparseagain("cot(a)", "Cotangent");
201 2 : parseandparseagain("sqrt{a}", "Square root");
202 2 : parseandparseagain("arcsin(a)", "Arcsine");
203 2 : parseandparseagain("arccos(a)", "Arccosine");
204 2 : parseandparseagain("arctan(a)", "Arctangent");
205 2 : parseandparseagain("arccot(a)", "Arc cotangent");
206 2 : parseandparseagain("nroot{a}{b}", "nth root");
207 2 : parseandparseagain("sinh(a)", "Hyperbolic sine");
208 2 : parseandparseagain("cosh(a)", "Hyperbolic cosine");
209 2 : parseandparseagain("tanh(a)", "Hyperbolic tangent");
210 2 : parseandparseagain("coth(a)", "Hyperbolic cotangent");
211 2 : parseandparseagain("abs{a}", "Absolute value");
212 2 : parseandparseagain("arsinh(a)", "Arc hyperbolic sine");
213 2 : parseandparseagain("arcosh(a)", "Arc hyperbolic cosine");
214 2 : parseandparseagain("artanh(a)", "Arc hyperbolic tangent");
215 2 : parseandparseagain("arcoth(a)", "Arc hyperbolic cotangent");
216 2 : }
217 :
218 2 : void Test::SimpleOperators()
219 : {
220 2 : parseandparseagain("lim{a}", "Limit");
221 2 : parseandparseagain("sum{a}", "Sum");
222 2 : parseandparseagain("prod{a}", "Product");
223 2 : parseandparseagain("coprod{a}", "Coproduct");
224 : //FIXME parseandparseagain("int from {r_0} to {r_t} a", "Upper and lower bounds shown with integral (from & to)");
225 : //FIXME ParseAndCheck("int csup {r_0} csub {r_t} a", "int csup { r rsub 0 } csub { r rsub t } a ", "Upper and lower bounds shown with integral (csub & csup)");
226 : //FIXME ParseAndCheck("sum csup { size 8 { x - 1 } } csub { size 8 a } b ", "sum csup { size 8 { x - 1 } } csub { size 8 a } b ", "Sum with sized upper and lower bounds");
227 2 : parseandparseagain("int{a}", "Integral");
228 2 : parseandparseagain("iint{a}", "Double integral");
229 2 : parseandparseagain("iiint{a}", "Triple integral");
230 2 : parseandparseagain("sum from{3}b", "Lower bound shown with summation symbol");
231 2 : parseandparseagain("lint a", "Contour integral");
232 2 : parseandparseagain("llint a", "Double curved integral");
233 2 : parseandparseagain("lllint a", "Triple curved integral");
234 2 : parseandparseagain("prod from {i=1} to {n} {(i+1)}", "Product with range");
235 2 : ParseAndCheck("%Ux2135", "%Ux2135", "fdo#77831");
236 2 : }
237 :
238 2 : void Test::SimpleAttributes()
239 : {
240 2 : parseandparseagain("acute a", "Acute accent");
241 2 : parseandparseagain("grave a", "Grave accent");
242 2 : parseandparseagain("check a", "Reverse circumflex");
243 2 : parseandparseagain("breve a", "Breve");
244 2 : parseandparseagain("circle a", "Circle");
245 2 : parseandparseagain("vec a", "Vector arrow");
246 2 : parseandparseagain("tilde a", "Tilde");
247 2 : parseandparseagain("hat a", "Circumflex");
248 2 : parseandparseagain("bar a", "Line above");
249 2 : parseandparseagain("dot a", "Dot");
250 2 : parseandparseagain("widevec abc", "Wide vector arrow");
251 2 : parseandparseagain("widetilde abc", "Wide tilde");
252 2 : parseandparseagain("widehat abc", "Wide circumflex");
253 2 : parseandparseagain("ddot a", "Double dot");
254 2 : parseandparseagain("overline abc", "Line over");
255 2 : parseandparseagain("underline abc", "Line under");
256 2 : parseandparseagain("overstrike abc", "Line through");
257 2 : parseandparseagain("dddot a", "Triple dot");
258 2 : parseandparseagain("phantom a", "Transparent (useful to get a placeholder of a given size)");
259 2 : parseandparseagain("bold a", "Bold font");
260 2 : parseandparseagain("ital a", "Italic font");
261 2 : parseandparseagain("nitalic a", "Roman (non-italic) font 1");
262 2 : parseandparseagain("\"a\"", "Roman (non-italic) font 2");
263 2 : parseandparseagain("size 16 qv", "Resize font");
264 2 : parseandparseagain("font sans qv", "Sans serif font");
265 2 : parseandparseagain("font serif qv", "Serif font");
266 2 : parseandparseagain("font fixed qv", "Fixed font");
267 2 : parseandparseagain("color cyan qv", "Cyan color");
268 2 : parseandparseagain("color yellow qv", "Yellow color");
269 2 : parseandparseagain("color white qv", "White color");
270 2 : parseandparseagain("color green qv", "Green color");
271 2 : parseandparseagain("color blue qv", "Blue color");
272 2 : parseandparseagain("color red qv", "Red color");
273 2 : parseandparseagain("color green X qv", "Green color changes back");
274 2 : parseandparseagain("color green {X qv}", "Green color, more than one item");
275 2 : }
276 :
277 2 : void Test::SimpleMisc()
278 : {
279 2 : parseandparseagain("infinity", "Infinity");
280 2 : parseandparseagain("partial", "Partial");
281 2 : parseandparseagain("nabla", "Nabla");
282 2 : parseandparseagain("exists", "There exists");
283 2 : parseandparseagain("notexists", "There not exists");
284 2 : parseandparseagain("forall", "For all");
285 2 : parseandparseagain("hbar", "H bar");
286 2 : parseandparseagain("lambdabar", "Lambda bar");
287 2 : parseandparseagain("re", "Real part");
288 2 : parseandparseagain("im", "Imaginary part");
289 2 : parseandparseagain("wp", "Weierstrass p");
290 2 : parseandparseagain("leftarrow", "Left arrow");
291 2 : parseandparseagain("rightarrow", "Right arrow");
292 2 : parseandparseagain("uparrow", "Up arrow");
293 2 : parseandparseagain("downarrow", "Down arrow");
294 2 : parseandparseagain("dotslow", "Dots at bottom");
295 2 : parseandparseagain("dotsaxis", "Dots at middle");
296 2 : parseandparseagain("dotsvert", "Dots vertical");
297 2 : parseandparseagain("dotsup", "Dots diagonal upward");
298 2 : parseandparseagain("dotsdown", "Dots diagonal downward");
299 2 : }
300 :
301 2 : void Test::SimpleBrackets()
302 : {
303 2 : parseandparseagain("(a)", "Round Brackets");
304 2 : parseandparseagain("[b]", "Square Brackets");
305 2 : parseandparseagain("ldbracket c rdbracket", "Double Square Brackets");
306 2 : parseandparseagain("lline a rline", "Single line or absolute");
307 2 : parseandparseagain("abs a", "Single line or absolute 2");
308 2 : parseandparseagain("ldline a rdline", "Double line");
309 2 : parseandparseagain("lbrace w rbrace", "Braces");
310 2 : parseandparseagain("left lbrace stack{0, n <> 0 # 1, n = 1} right none", "Single left brace");
311 2 : parseandparseagain("langle d rangle", "Angle Brackets");
312 2 : parseandparseagain("langle a mline b rangle", "Operator Brackets");
313 2 : parseandparseagain("{a}", "Group brackets (used for program control)");
314 2 : parseandparseagain("left ( stack{a # b # z} right )", "Round brackets scalable");
315 2 : parseandparseagain("left [ stack{x # y} right ]", "Square brackets scalable");
316 2 : parseandparseagain("left ldbracket c right rdbracket", "Double square brackets scalable");
317 2 : parseandparseagain("left lline a right rline", "Line scalable");
318 2 : parseandparseagain("left ldline d right rdline", "Double line scalable");
319 2 : parseandparseagain("left lbrace e right rbrace", "Brace scalable");
320 2 : parseandparseagain("left langle f right rangle", "Angle bracket scalable");
321 2 : parseandparseagain("left langle g mline h right rangle", "Operator brackets scalable");
322 2 : parseandparseagain("{a} overbrace b", "Over brace scalable");
323 2 : parseandparseagain("{b} underbrace a", "Under brace scalable");
324 2 : }
325 :
326 2 : void Test::SimpleFormats()
327 : {
328 2 : parseandparseagain("a lsup{b}", "Left superscript");
329 2 : parseandparseagain("a csup{b}", "Center superscript");
330 2 : parseandparseagain("a^{b}", "Right superscript");
331 2 : parseandparseagain("a lsub{b}", "Left subscript");
332 2 : parseandparseagain("a csub{b}", "Center subscript");
333 2 : parseandparseagain("a_{b}", "Right subscript");
334 2 : parseandparseagain("stack { Hello world # alignl (a) }", "Align character to left");
335 2 : parseandparseagain("stack{Hello world # alignc(a)}", "Align character to center");
336 2 : parseandparseagain("stack { Hello world # alignr(a)}", "Align character to right");
337 2 : parseandparseagain("binom{a}{b}", "Vertical stack of 2");
338 2 : parseandparseagain("stack{a # b # z}", "Vertical stack, more than 2");
339 2 : parseandparseagain("matrix{a # b ## c # d}", "Matrix");
340 2 : parseandparseagain("matrix{a # \"=\" # alignl{b} ## {} # \"=\" # alignl{c+1}}", "Equations aligned at '=' (using 'matrix') ");
341 2 : parseandparseagain("stack{alignl{a} = b # alignl{phantom{a} = c+1}}", "Equations aligned at '=' (using 'phantom') ");
342 2 : parseandparseagain("asldkfjo newline sadkfj", "New line");
343 2 : parseandparseagain("stuff `stuff", "Small gap (grave)");
344 2 : parseandparseagain("stuff~stuff", "Large gap (tilde)");
345 2 : }
346 :
347 2 : void Test::SimpleGreekChars()
348 : {
349 2 : parseandparseagain("%ALPHA", "Capital alpha");
350 2 : parseandparseagain("%BETA", "Capital beta");
351 2 : parseandparseagain("%CHI", "Capital chi");
352 2 : parseandparseagain("%DELTA", "Capital delta");
353 2 : parseandparseagain("%EPSILON", "Capital epsilon");
354 2 : parseandparseagain("%ETA", "Capital eta");
355 2 : parseandparseagain("%GAMMA", "Capital gamma");
356 2 : parseandparseagain("%IOTA", "Capital iota");
357 2 : parseandparseagain("%LAMBDA", "Capital lambda");
358 2 : parseandparseagain("%MU", "Capital mu");
359 2 : parseandparseagain("%NU", "Capital nu");
360 2 : parseandparseagain("%OMEGA", "Capital omega");
361 2 : parseandparseagain("%OMICRON", "Capital omicron");
362 2 : parseandparseagain("%PHI", "Capital phi");
363 2 : parseandparseagain("%PI", "Capital pi");
364 2 : parseandparseagain("%PSI", "Capital psi");
365 2 : parseandparseagain("%RHO", "Capital rho");
366 2 : parseandparseagain("%SIGMA", "Capital sigma");
367 2 : parseandparseagain("%TAU", "Capital tau");
368 2 : parseandparseagain("%THETA", "Capital theta");
369 2 : parseandparseagain("%UPSILON", "Capital upsilon");
370 2 : parseandparseagain("%XI", "Capital xi");
371 2 : parseandparseagain("%ZETA", "Capital zeta");
372 2 : parseandparseagain("%alpha", "lowercase alpha");
373 2 : parseandparseagain("%beta", "lowercase beta");
374 2 : parseandparseagain("%chi", "lowercase chi");
375 2 : parseandparseagain("%delta", "lowercase delta");
376 2 : parseandparseagain("%epsilon", "lowercase epsilon");
377 2 : parseandparseagain("%eta", "lowercase eta");
378 2 : parseandparseagain("%gamma", "lowercase gamma");
379 2 : parseandparseagain("%iota", "lowercase iota");
380 2 : parseandparseagain("%kappa", "lowercase kappa");
381 2 : parseandparseagain("%lambda", "lowercase lambda");
382 2 : parseandparseagain("%mu", "lowercase mu");
383 2 : parseandparseagain("%nu", "lowercase nu");
384 2 : parseandparseagain("%omega", "lowercase omega");
385 2 : parseandparseagain("%omicron", "lowercase omicron");
386 2 : parseandparseagain("%phi", "lowercase phi");
387 2 : parseandparseagain("%pi", "lowercase pi");
388 2 : parseandparseagain("%psi", "lowercase psi");
389 2 : parseandparseagain("%rho", "lowercase rho");
390 2 : parseandparseagain("%sigma", "lowercase sigma");
391 2 : parseandparseagain("%tau", "lowercase tau");
392 2 : parseandparseagain("%theta", "lowercase theta");
393 2 : parseandparseagain("%upsilon", "lowercase upsilon");
394 2 : parseandparseagain("%varepsilon", "Varepsilon");
395 2 : parseandparseagain("%varphi", "Varphi");
396 2 : parseandparseagain("%varpi", "Varpi");
397 2 : parseandparseagain("%varrho", "Varrho");
398 2 : parseandparseagain("%varsigma", "Varsigma");
399 2 : parseandparseagain("%vartheta", "Vartheta");
400 2 : parseandparseagain("%xi", "lowercase xi");
401 2 : parseandparseagain("%zeta", "lowercase zeta");
402 2 : }
403 :
404 2 : void Test::SimpleSpecialChars()
405 : {
406 2 : parseandparseagain("%and", "And");
407 2 : parseandparseagain("%angle", "Angle");
408 2 : parseandparseagain("%element", "Element");
409 2 : parseandparseagain("%identical", "Identical");
410 2 : parseandparseagain("%infinite", "Infinite");
411 2 : parseandparseagain("%noelement", "No element");
412 2 : parseandparseagain("%notequal", "Not equal");
413 2 : parseandparseagain("%or", "Or");
414 2 : parseandparseagain("%perthousand", "Per thousand");
415 2 : parseandparseagain("%strictlygreaterthan", "Strictly greater than");
416 2 : parseandparseagain("%strictlylessthan", "Strictly less than");
417 2 : parseandparseagain("%tendto", "Tend to");
418 2 : }
419 :
420 : /* This test takes a formula command, parses it, converts the node to text,
421 : * parses it again, converts it to text again, and compares the values.
422 : * Doing this doesn't prove that it is correct, but it should prove that the
423 : * meaning of the original command is not being changed.
424 : */
425 526 : void Test::parseandparseagain(const char *formula, const char *test_name)
426 : {
427 1052 : OUString output1, output2;
428 : SmNode *pNode1, *pNode2;
429 :
430 : // parse 1
431 1052 : OUString input = OUString::createFromAscii(formula);
432 526 : pNode1 = SmParser().ParseExpression(input);
433 526 : pNode1->Prepare(xDocShRef->GetFormat(), *xDocShRef);
434 526 : SmNodeToTextVisitor(pNode1, output1);
435 :
436 : // parse 2
437 526 : pNode2 = SmParser().ParseExpression(output1);
438 526 : pNode2->Prepare(xDocShRef->GetFormat(), *xDocShRef);
439 526 : SmNodeToTextVisitor(pNode2, output2);
440 :
441 : // compare
442 1052 : CPPUNIT_ASSERT_EQUAL_MESSAGE(test_name,
443 : output1,
444 526 : output2);
445 :
446 526 : delete pNode1;
447 1052 : delete pNode2;
448 526 : }
449 :
450 4 : void Test::ParseAndCheck(const char *formula, const char * expected, const char *test_name)
451 : {
452 4 : OUString sOutput;
453 : SmNode *pNode;
454 :
455 : // parse
456 8 : OUString sInput = OUString::createFromAscii(formula);
457 4 : pNode = SmParser().ParseExpression(sInput);
458 4 : pNode->Prepare(xDocShRef->GetFormat(), *xDocShRef);
459 4 : SmNodeToTextVisitor(pNode, sOutput);
460 :
461 : // compare
462 8 : OUString sExpected = OUString::createFromAscii(expected);
463 8 : CPPUNIT_ASSERT_EQUAL_MESSAGE(test_name,
464 : sExpected,
465 4 : sOutput);
466 :
467 8 : delete pNode;
468 4 : }
469 :
470 : // Parse two formula commands and verify that they give the same output
471 12 : void Test::ParseAndCompare(const char *formula1, const char *formula2, const char *test_name)
472 : {
473 24 : OUString sOutput1, sOutput2;
474 : SmNode *pNode1, *pNode2;
475 :
476 : // parse formula1
477 24 : OUString sInput1 = OUString::createFromAscii(formula1);
478 12 : pNode1 = SmParser().ParseExpression(sInput1);
479 12 : pNode1->Prepare(xDocShRef->GetFormat(), *xDocShRef);
480 12 : SmNodeToTextVisitor(pNode1, sOutput1);
481 :
482 : // parse formula2
483 24 : OUString sInput2 = OUString::createFromAscii(formula2);
484 12 : pNode2 = SmParser().ParseExpression(sInput2);
485 12 : pNode2->Prepare(xDocShRef->GetFormat(), *xDocShRef);
486 12 : SmNodeToTextVisitor(pNode2, sOutput2);
487 :
488 12 : CPPUNIT_ASSERT_EQUAL_MESSAGE(test_name, sOutput1, sOutput2);
489 :
490 12 : delete pNode1;
491 24 : delete pNode2;
492 12 : }
493 :
494 2 : void Test::testBinomInBinHor()
495 : {
496 4 : OUString sInput, sExpected;
497 : SmNode* pTree;
498 :
499 : // set up a binom (table) node
500 2 : sInput += "binom a b + c";
501 2 : pTree = SmParser().Parse(sInput);
502 2 : pTree->Prepare(xDocShRef->GetFormat(), *xDocShRef);
503 :
504 4 : SmCursor aCursor(pTree, xDocShRef);
505 4 : VirtualDevice aOutputDevice;
506 :
507 : // move forward (more than) enough places to be at the end
508 : int i;
509 18 : for (i = 0; i < 8; ++i)
510 16 : aCursor.Move(&aOutputDevice, MoveRight);
511 :
512 : // tack +d on the end, which will put the binom into an SmBinHorNode
513 2 : aCursor.InsertElement(PlusElement);
514 2 : aCursor.InsertText("d");
515 :
516 2 : sExpected += " { { binom a b + c } + d } ";
517 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("Binom Node in BinHor Node", sExpected, xDocShRef->GetText());
518 :
519 4 : delete pTree;
520 2 : }
521 :
522 2 : void Test::testBinVerInUnary()
523 : {
524 4 : OUString sInput, sExpected;
525 : SmNode* pTree;
526 :
527 : // set up a unary operator with operand
528 2 : sInput += "- 1";
529 2 : pTree = SmParser().Parse(sInput);
530 2 : pTree->Prepare(xDocShRef->GetFormat(), *xDocShRef);
531 :
532 4 : SmCursor aCursor(pTree, xDocShRef);
533 4 : VirtualDevice aOutputDevice;
534 :
535 : // move forward (more than) enough places to be at the end
536 : int i;
537 8 : for (i = 0; i < 3; ++i)
538 6 : aCursor.Move(&aOutputDevice, MoveRight);
539 :
540 : // select the operand
541 2 : aCursor.Move(&aOutputDevice, MoveLeft, false);
542 : // set up a fraction
543 2 : aCursor.InsertFraction();
544 2 : aCursor.Move(&aOutputDevice, MoveDown);
545 2 : aCursor.InsertText("2");
546 :
547 2 : sExpected += " - { 1 over 2 } ";
548 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("Binary Vertical in Unary Operator", sExpected, xDocShRef->GetText());
549 :
550 4 : delete pTree;
551 2 : }
552 :
553 2 : void Test::testBinHorInSubSup()
554 : {
555 2 : OUString sInput;
556 :
557 : // set up a blank formula
558 2 : SmNode* pTree = SmParser().Parse(sInput);
559 2 : pTree->Prepare(xDocShRef->GetFormat(), *xDocShRef);
560 :
561 4 : SmCursor aCursor(pTree, xDocShRef);
562 4 : VirtualDevice aOutputDevice;
563 :
564 : // Insert an RSup expression with a BinHor for the exponent
565 2 : aCursor.InsertText("a");
566 2 : aCursor.InsertSubSup(RSUP);
567 2 : aCursor.InsertText("b");
568 2 : aCursor.InsertElement(PlusElement);
569 2 : aCursor.InsertText("c");
570 :
571 : // Move to the end and add d to the expression
572 2 : aCursor.Move(&aOutputDevice, MoveRight);
573 2 : aCursor.InsertElement(PlusElement);
574 2 : aCursor.InsertText("d");
575 :
576 : //FIXME OUString sExpected = " { a rsup { b + c } + d } ";
577 : //FIXME CPPUNIT_ASSERT_EQUAL_MESSAGE("BinHor in SubSup", sExpected, xDocShRef->GetText());
578 :
579 4 : delete pTree;
580 2 : }
581 :
582 2 : void Test::testUnaryInMixedNumberAsNumerator()
583 : {
584 : // set up a unary operator
585 2 : OUString sInput = "- 1";
586 2 : SmNode* pTree = SmParser().Parse(sInput);
587 2 : pTree->Prepare(xDocShRef->GetFormat(), *xDocShRef);
588 :
589 4 : SmCursor aCursor(pTree, xDocShRef);
590 4 : VirtualDevice aOutputDevice;
591 :
592 : // move forward (more than) enough places to be at the end
593 8 : for (size_t i = 0; i < 3; ++i)
594 6 : aCursor.Move(&aOutputDevice, MoveRight);
595 :
596 : // Select the whole Unary Horizontal Node
597 2 : aCursor.Move(&aOutputDevice, MoveLeft, false);
598 2 : aCursor.Move(&aOutputDevice, MoveLeft, false);
599 :
600 : // Set up a fraction
601 2 : aCursor.InsertFraction();
602 2 : aCursor.Move(&aOutputDevice, MoveDown);
603 2 : aCursor.InsertText("2");
604 :
605 : // Move left and turn this into a mixed number
606 : // (bad form, but this could happen right?)
607 2 : aCursor.Move(&aOutputDevice, MoveLeft);
608 2 : aCursor.Move(&aOutputDevice, MoveLeft);
609 2 : aCursor.InsertText("2");
610 :
611 : // move forward (more than) enough places to be at the end
612 18 : for (size_t i = 0; i < 8; ++i)
613 16 : aCursor.Move(&aOutputDevice, MoveRight);
614 :
615 : // add 4 to the end
616 2 : aCursor.InsertElement(PlusElement);
617 2 : aCursor.InsertText("4");
618 :
619 4 : OUString sExpected = " { 2 { - 1 over 2 } + 4 } ";
620 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("Unary in mixed number as Numerator", sExpected, xDocShRef->GetText());
621 :
622 4 : delete pTree;
623 2 : }
624 :
625 2 : void Test::testMiscEquivalent()
626 : {
627 : // fdo#55853
628 2 : ParseAndCompare("2x", "2 x", "Number times variable");
629 2 : ParseAndCompare("3x^2", "3 x^2", "Number times power");
630 :
631 : // i#11752 and fdo#55853
632 2 : ParseAndCompare("x_2n", "x_{2 n}", "Number times variable in subscript");
633 2 : ParseAndCompare("x^2n", "x^{2 n}", "Number times variable in supscript");
634 :
635 : // fdo#66081
636 2 : ParseAndCompare("{x}", "x", "Variable in brace");
637 2 : ParseAndCompare("{{x+{{y}}}}", "x+y", "Nested braces");
638 2 : }
639 :
640 2 : CPPUNIT_TEST_SUITE_REGISTRATION(Test);
641 :
642 6 : }
643 :
644 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|