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