File indexing completed on 2024-05-05 11:55:53
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-or-later 0003 SPDX-FileCopyrightText: 2009 Alexander Rieder <alexanderrieder@gmail.com> 0004 SPDX-FileCopyrightText: 2021-2023 Alexander Semke <alexander.semke@web.de> 0005 */ 0006 0007 #include "testoctave.h" 0008 0009 #include "session.h" 0010 #include "backend.h" 0011 #include "expression.h" 0012 #include "result.h" 0013 #include "imageresult.h" 0014 #include "textresult.h" 0015 #include "helpresult.h" 0016 #include "epsresult.h" 0017 #include "completionobject.h" 0018 #include "syntaxhelpobject.h" 0019 #include "defaultvariablemodel.h" 0020 0021 #include "octaveexpression.h" 0022 #include "settings.h" 0023 0024 #include <QDebug> 0025 0026 QString TestOctave::backendName() 0027 { 0028 return QLatin1String("octave"); 0029 } 0030 0031 void TestOctave::initTestCase() { 0032 QSKIP("Octave tests are failing on CI, deactivating for now until the problem is understood and fixed."); 0033 /* 0034 if (QStandardPaths::findExecutable(QLatin1String("octave")).isEmpty()) 0035 QSKIP("Octave executable not found"); 0036 BackendTest::initTestCase(); 0037 */ 0038 } 0039 0040 void TestOctave::testSimpleCommand() 0041 { 0042 auto* e = evalExp( QLatin1String("2+2") ); 0043 0044 QVERIFY( e != nullptr ); 0045 QVERIFY( e->result()!=nullptr ); 0046 0047 QCOMPARE( cleanOutput( e->result()->data().toString() ), QLatin1String("ans = 4") ); 0048 } 0049 void TestOctave::testMultilineCommand() 0050 { 0051 auto* e = evalExp( QLatin1String("a = 2+2, b = 3+3") ); 0052 0053 QVERIFY( e != nullptr ); 0054 QVERIFY( e->result()!=nullptr ); 0055 0056 QString result=e->result()->data().toString(); 0057 0058 QCOMPARE( cleanOutput(result ), QLatin1String("a = 4\nb = 6") ); 0059 } 0060 0061 void TestOctave::testCommandQueue() 0062 { 0063 auto* e1=session()->evaluateExpression(QLatin1String("0+1")); 0064 auto* e2=session()->evaluateExpression(QLatin1String("1+1")); 0065 auto* e3=evalExp(QLatin1String("1+2")); 0066 0067 QVERIFY(e1!=nullptr); 0068 QVERIFY(e2!=nullptr); 0069 QVERIFY(e3!=nullptr); 0070 0071 QVERIFY(e1->result()); 0072 QVERIFY(e2->result()); 0073 QVERIFY(e3->result()); 0074 0075 QCOMPARE(cleanOutput(e1->result()->data().toString()), QLatin1String("ans = 1")); 0076 QCOMPARE(cleanOutput(e2->result()->data().toString()), QLatin1String("ans = 2")); 0077 QCOMPARE(cleanOutput(e3->result()->data().toString()), QLatin1String("ans = 3")); 0078 } 0079 0080 void TestOctave::testVariableDefinition() 0081 { 0082 auto* e = evalExp(QLatin1String("testvar = 1")); 0083 0084 QVERIFY(e != nullptr); 0085 QVERIFY(e->result() != nullptr); 0086 QCOMPARE(cleanOutput(e->result()->data().toString()), QLatin1String("testvar = 1")); 0087 } 0088 0089 void TestOctave::testMatrixDefinition() 0090 { 0091 auto* e = evalExp(QLatin1String( 0092 "M = [1, 2, 3;"\ 0093 " 4, 5, 6;"\ 0094 " 7, 8, 9;]" 0095 )); 0096 0097 QVERIFY(e != nullptr); 0098 QVERIFY(e->result() != nullptr); 0099 QCOMPARE(e->result()->type(), (int) Cantor::TextResult::Type); 0100 0101 Cantor::TextResult* result = static_cast<Cantor::TextResult*>(e->result()); 0102 QCOMPARE(result->plain(), QLatin1String( 0103 "M =\n"\ 0104 "\n" 0105 " 1 2 3\n"\ 0106 " 4 5 6\n"\ 0107 " 7 8 9" 0108 )); 0109 } 0110 0111 //Comments 0112 void TestOctave::testComment00() 0113 { 0114 auto* e = evalExp(QLatin1String("s = 1234 #This is comment")); 0115 0116 QVERIFY(e != nullptr); 0117 QVERIFY(e->result() != nullptr); 0118 QCOMPARE(cleanOutput(e->result()->data().toString()), QLatin1String("s = 1234")); 0119 } 0120 0121 /*! 0122 * simple command containing one single comment only 0123 */ 0124 void TestOctave::testComment01() 0125 { 0126 auto* e = evalExp(QLatin1String("#Only comment")); 0127 0128 QVERIFY(e != nullptr); 0129 QCOMPARE(e->status(), Cantor::Expression::Status::Done); 0130 QCOMPARE(e->results().size(), 0); 0131 } 0132 0133 /*! 0134 * multi-line command with lines containing comments only 0135 */ 0136 void TestOctave::testComment02() 0137 { 0138 auto* e = evalExp(QLatin1String( 0139 "# comment 1 \n" 0140 "5 + 5\n" 0141 "# comment 2\n" 0142 "a = 10" 0143 )); 0144 0145 QVERIFY(e != nullptr); 0146 QCOMPARE(e->status(), Cantor::Expression::Status::Done); 0147 QVERIFY(e->result() != nullptr); 0148 0149 Cantor::TextResult* result = static_cast<Cantor::TextResult*>(e->result()); 0150 QVERIFY(result != nullptr); 0151 QCOMPARE(cleanOutput(result->plain()), QLatin1String( 0152 "ans = 10\n" 0153 "a = 10" 0154 )); 0155 } 0156 0157 /*! 0158 * multi-line command with comments within the line containing also the actual expression 0159 * */ 0160 void TestOctave::testComment03() 0161 { 0162 auto* e = evalExp(QLatin1String( 0163 "a = 2+4 \n" 0164 "6/2 % comment\n" 0165 "q = 'Str' # comment\n" 0166 "b = 4" 0167 )); 0168 0169 QVERIFY(e != nullptr); 0170 QCOMPARE(e->status(), Cantor::Expression::Status::Done); 0171 QVERIFY(e->result() != nullptr); 0172 0173 Cantor::TextResult* result = static_cast<Cantor::TextResult*>(e->result()); 0174 QVERIFY(result != nullptr); 0175 QCOMPARE(cleanOutput(result->plain()), QLatin1String( 0176 "a = 6\n" 0177 "ans = 3\n" 0178 "q = Str\n" 0179 "b = 4" 0180 )); 0181 } 0182 0183 /*! 0184 * multi-line command with comments within the line containing also the actual expression 0185 * and with ' used to transpose the vector. 0186 * */ 0187 void TestOctave::testComment04() 0188 { 0189 QAbstractItemModel* model = session()->variableModel(); 0190 QVERIFY(model != nullptr); 0191 0192 evalExp(QLatin1String("clear();")); 0193 0194 auto* e = evalExp(QLatin1String( 0195 "x=[1,2,3];\n" 0196 "xT=x';\n" 0197 "% comment\n" 0198 "y=1;" 0199 )); 0200 0201 QVERIFY(e != nullptr); 0202 0203 if(session()->status()==Cantor::Session::Running) 0204 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0205 0206 QCOMPARE(e->status(), Cantor::Expression::Status::Done); 0207 QVERIFY(e->result() == nullptr); // empty result output 0208 0209 QCOMPARE(model->rowCount(), 3); 0210 QCOMPARE(model->index(0,0).data().toString(), QLatin1String("x")); 0211 QCOMPARE(model->index(1,0).data().toString(), QLatin1String("xT")); 0212 QCOMPARE(model->index(2,0).data().toString(), QLatin1String("y")); 0213 } 0214 0215 /*! 0216 * multi-line command with comments within the line containing also the actual expression 0217 * and with ' used to transpose the vector. 0218 * */ 0219 void TestOctave::testComment05() 0220 { 0221 QAbstractItemModel* model = session()->variableModel(); 0222 QVERIFY(model != nullptr); 0223 0224 evalExp(QLatin1String("clear();")); 0225 0226 auto* e = evalExp(QLatin1String( 0227 "x=[1,2,3];\n" 0228 "xT=x';\n" 0229 "# comment\n" 0230 "y=1;" 0231 )); 0232 0233 QVERIFY(e != nullptr); 0234 0235 if(session()->status()==Cantor::Session::Running) 0236 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0237 0238 QCOMPARE(e->status(), Cantor::Expression::Status::Done); 0239 QVERIFY(e->result() == nullptr); // empty result output 0240 0241 QCOMPARE(model->rowCount(), 3); 0242 QCOMPARE(model->index(0,0).data().toString(), QLatin1String("x")); 0243 QCOMPARE(model->index(1,0).data().toString(), QLatin1String("xT")); 0244 QCOMPARE(model->index(2,0).data().toString(), QLatin1String("y")); 0245 } 0246 0247 /*! 0248 * multi-line command with comments within the line containing also the actual expression 0249 * and with ' used to transpose the vector. 0250 * */ 0251 void TestOctave::testComment06() 0252 { 0253 QAbstractItemModel* model = session()->variableModel(); 0254 QVERIFY(model != nullptr); 0255 0256 evalExp(QLatin1String("clear();")); 0257 0258 auto* e = evalExp(QLatin1String( 0259 "x=[1,2,3];\n" 0260 "xT=x'; % comment\n" 0261 "y=1;" 0262 )); 0263 0264 QVERIFY(e != nullptr); 0265 0266 if(session()->status()==Cantor::Session::Running) 0267 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0268 0269 QCOMPARE(e->status(), Cantor::Expression::Status::Done); 0270 QVERIFY(e->result() == nullptr); // empty result output 0271 0272 QCOMPARE(model->rowCount(), 3); 0273 QCOMPARE(model->index(0,0).data().toString(), QLatin1String("x")); 0274 QCOMPARE(model->index(1,0).data().toString(), QLatin1String("xT")); 0275 QCOMPARE(model->index(2,0).data().toString(), QLatin1String("y")); 0276 } 0277 0278 /*! 0279 * multi-line command with comments within the line containing also the actual expression 0280 * and with ' used to transpose the vector. 0281 * */ 0282 void TestOctave::testComment07() 0283 { 0284 QAbstractItemModel* model = session()->variableModel(); 0285 QVERIFY(model != nullptr); 0286 0287 evalExp(QLatin1String("clear();")); 0288 0289 auto* e = evalExp(QLatin1String( 0290 "x=[1,2,3];\n" 0291 "xT=x'; # comment\n" 0292 "y=1;" 0293 )); 0294 0295 QVERIFY(e != nullptr); 0296 0297 if(session()->status()==Cantor::Session::Running) 0298 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0299 0300 QCOMPARE(e->status(), Cantor::Expression::Status::Done); 0301 QVERIFY(e->result() == nullptr); // empty result output 0302 0303 QCOMPARE(model->rowCount(), 3); 0304 QCOMPARE(model->index(0,0).data().toString(), QLatin1String("x")); 0305 QCOMPARE(model->index(1,0).data().toString(), QLatin1String("xT")); 0306 QCOMPARE(model->index(2,0).data().toString(), QLatin1String("y")); 0307 } 0308 0309 /*! 0310 * multi-line command with comments within the line containing also the actual expression 0311 * and with ' used to transpose the vector and to quote a string 0312 * */ 0313 void TestOctave::testComment08() 0314 { 0315 QAbstractItemModel* model = session()->variableModel(); 0316 QVERIFY(model != nullptr); 0317 0318 evalExp(QLatin1String("clear();")); 0319 0320 auto* e = evalExp(QLatin1String( 0321 "x=[1,2,3];\n" 0322 "xT=x';\n" 0323 "% comment\n" 0324 "text = 'bla#blub';\n" 0325 "y=1;" 0326 )); 0327 0328 QVERIFY(e != nullptr); 0329 0330 if(session()->status()==Cantor::Session::Running) 0331 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0332 0333 QCOMPARE(e->status(), Cantor::Expression::Status::Done); 0334 QVERIFY(e->result() == nullptr); // empty result output 0335 0336 QCOMPARE(model->rowCount(), 4); 0337 QCOMPARE(model->index(0,0).data().toString(), QLatin1String("text")); 0338 QCOMPARE(model->index(1,0).data().toString(), QLatin1String("x")); 0339 QCOMPARE(model->index(2,0).data().toString(), QLatin1String("xT")); 0340 QCOMPARE(model->index(3,0).data().toString(), QLatin1String("y")); 0341 } 0342 0343 /*! 0344 * multi-line command with comments within the line containing also the actual expression 0345 * and with ' used to transpose the vector and to quote a string 0346 * */ 0347 void TestOctave::testComment09() 0348 { 0349 QAbstractItemModel* model = session()->variableModel(); 0350 QVERIFY(model != nullptr); 0351 0352 evalExp(QLatin1String("clear();")); 0353 0354 auto* e = evalExp(QLatin1String( 0355 "x=[1,2,3];\n" 0356 "xT=x';\n" 0357 "% comment\n" 0358 "text = 'bla%blub';\n" 0359 "y=1;" 0360 )); 0361 0362 QVERIFY(e != nullptr); 0363 0364 if(session()->status()==Cantor::Session::Running) 0365 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0366 0367 QCOMPARE(e->status(), Cantor::Expression::Status::Done); 0368 QVERIFY(e->result() == nullptr); // empty result output 0369 0370 QCOMPARE(model->rowCount(), 4); 0371 QCOMPARE(model->index(0,0).data().toString(), QLatin1String("text")); 0372 QCOMPARE(model->index(1,0).data().toString(), QLatin1String("x")); 0373 QCOMPARE(model->index(2,0).data().toString(), QLatin1String("xT")); 0374 QCOMPARE(model->index(3,0).data().toString(), QLatin1String("y")); 0375 } 0376 0377 void TestOctave::testCompletion() 0378 { 0379 Cantor::CompletionObject* help = session()->completionFor(QLatin1String("as"), 2); 0380 waitForSignal(help, SIGNAL(fetchingDone())); 0381 0382 // Checks some completions for this request (but not all) 0383 // This correct for Octave 4.2.2 at least (and another versions, I think) 0384 const QStringList& completions = help->completions(); 0385 QVERIFY(completions.contains(QLatin1String("asin"))); 0386 QVERIFY(completions.contains(QLatin1String("asctime"))); 0387 QVERIFY(completions.contains(QLatin1String("asec"))); 0388 QVERIFY(completions.contains(QLatin1String("assert"))); 0389 } 0390 0391 void TestOctave::testVariablesCreatingFromCode() 0392 { 0393 QAbstractItemModel* model = session()->variableModel(); 0394 QVERIFY(model != nullptr); 0395 0396 evalExp(QLatin1String("clear();")); 0397 0398 auto* e = evalExp(QLatin1String("a = 15; b = 'S';")); 0399 QVERIFY(e != nullptr); 0400 0401 if(session()->status()==Cantor::Session::Running) 0402 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0403 0404 QCOMPARE(2, model->rowCount()); 0405 0406 QCOMPARE(model->index(0,0).data().toString(), QLatin1String("a")); 0407 QCOMPARE(model->index(0,1).data().toString(), QLatin1String("15")); 0408 0409 QCOMPARE(model->index(1,0).data().toString(), QLatin1String("b")); 0410 QCOMPARE(model->index(1,1).data().toString(), QLatin1String("S")); 0411 } 0412 0413 void TestOctave::testVariablesMultiRowValues() 0414 { 0415 QAbstractItemModel* model = session()->variableModel(); 0416 QVERIFY(model != nullptr); 0417 0418 evalExp(QLatin1String("clear();")); 0419 0420 auto* e1 = evalExp(QLatin1String("rowVec = [1 2 3];")); 0421 QVERIFY(e1 != nullptr); 0422 0423 auto* e2 = evalExp(QLatin1String("columnVec = [1; 2; 3];")); 0424 QVERIFY(e2 != nullptr); 0425 0426 auto* e3 = evalExp(QLatin1String("mat = columnVec * rowVec;")); 0427 QVERIFY(e3 != nullptr); 0428 0429 if(session()->status() == Cantor::Session::Running) 0430 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0431 0432 QCOMPARE(3, model->rowCount()); 0433 0434 QCOMPARE(model->index(0,0).data().toString(), QLatin1String("rowVec")); 0435 QCOMPARE(model->index(0,1).data().toString(), QLatin1String("1 2 3")); 0436 0437 QCOMPARE(model->index(1,0).data().toString(), QLatin1String("columnVec")); 0438 QCOMPARE(model->index(1,1).data().toString(), QLatin1String("1; 2; 3")); 0439 0440 QCOMPARE(model->index(2,0).data().toString(), QLatin1String("mat")); 0441 QCOMPARE(model->index(2,1).data().toString(), QLatin1String("1 2 3; 2 4 6; 3 6 9")); 0442 } 0443 0444 void TestOctave::testVariableChangeSizeType() 0445 { 0446 QAbstractItemModel* model = session()->variableModel(); 0447 QVERIFY(model != nullptr); 0448 0449 evalExp(QLatin1String("clear();")); 0450 0451 // create a text variable 0452 auto* e1 = evalExp(QLatin1String("test = \"abcd\";")); 0453 QVERIFY(e1 != nullptr); 0454 0455 if(session()->status() == Cantor::Session::Running) 0456 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0457 0458 QCOMPARE(1, model->rowCount()); 0459 QCOMPARE(model->index(0,0).data().toString(), QLatin1String("test")); 0460 QCOMPARE(model->index(0,1).data().toString(), QLatin1String("abcd")); 0461 QCOMPARE(model->index(0,2).data().toString(), QLatin1String("string")); 0462 QCOMPARE(model->index(0,3).data().toInt(), 4); // 4 bytes for 4 characters 0463 0464 // change from string to integer 0465 auto* e2 = evalExp(QLatin1String("test = 1;")); 0466 QVERIFY(e2 != nullptr); 0467 0468 if(session()->status() == Cantor::Session::Running) 0469 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0470 0471 QCOMPARE(1, model->rowCount()); 0472 QCOMPARE(model->index(0,0).data().toString(), QLatin1String("test")); 0473 QCOMPARE(model->index(0,1).data().toString(), QLatin1String("1")); 0474 QCOMPARE(model->index(0,2).data().toString(), QLatin1String("scalar")); 0475 QCOMPARE(model->index(0,3).data().toInt(), 8); // 8 bytes for a scalar value 0476 } 0477 0478 void TestOctave::testVariableCreatingFromCodeWithPlot() 0479 { 0480 QAbstractItemModel* model = session()->variableModel(); 0481 QVERIFY(model != nullptr); 0482 0483 evalExp(QLatin1String("clear();")); 0484 0485 auto* e = evalExp(QLatin1String( 0486 "x = -10:0.1:10;\n" 0487 "plot (x, sin (x));\n" 0488 "xlabel (\"x\");\n" 0489 "ylabel (\"sin (x)\");\n" 0490 "title (\"Simple 2-D Plot\");\n" 0491 )); 0492 QVERIFY(e != nullptr); 0493 0494 if(session()->status()==Cantor::Session::Running) 0495 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0496 0497 QCOMPARE(e->status(), Cantor::Expression::Done); 0498 QVERIFY(e->result() != nullptr); 0499 0500 bool eps = (OctaveExpression::plotExtensions[OctaveSettings::inlinePlotFormat()] == QLatin1String("eps")); 0501 int plotType = eps ? (int)Cantor::EpsResult::Type : (int)Cantor::ImageResult::Type; 0502 QVERIFY(e->result()->type() == plotType); 0503 0504 QCOMPARE(1, model->rowCount()); 0505 QCOMPARE(model->index(0,0).data().toString(), QLatin1String("x")); 0506 } 0507 0508 void TestOctave::testVariableCleanupAfterRestart() 0509 { 0510 Cantor::DefaultVariableModel* model = session()->variableModel(); 0511 QVERIFY(model != nullptr); 0512 0513 evalExp(QLatin1String("clear();")); 0514 auto* e = evalExp(QLatin1String("a = 15; b = 'S';")); 0515 QVERIFY(e != nullptr); 0516 0517 if(session()->status()==Cantor::Session::Running) 0518 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0519 0520 QCOMPARE(2, static_cast<QAbstractItemModel*>(model)->rowCount()); 0521 0522 session()->logout(); 0523 session()->login(); 0524 0525 QCOMPARE(0, static_cast<QAbstractItemModel*>(model)->rowCount()); 0526 } 0527 0528 void TestOctave::testPlot() 0529 { 0530 auto* e = evalExp(QLatin1String("x=-10:0.1:10; plot(x,sin(x));")); 0531 QVERIFY(e != nullptr); 0532 0533 if(session()->status() == Cantor::Session::Running) 0534 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0535 0536 QVERIFY(e->result() != nullptr); 0537 QCOMPARE(e->result()->type(), (int)Cantor::ImageResult::Type ); 0538 QVERIFY(!e->result()->data().isNull()); 0539 QVERIFY(e->errorMessage().isNull()); 0540 } 0541 0542 void TestOctave::testCantorPlot2d() 0543 { 0544 auto* e = evalExp( QLatin1String("cantor_plot2d('sin(x)', 'x', -10,10);") ); 0545 QVERIFY(e != nullptr); 0546 0547 if(session()->status() == Cantor::Session::Running) 0548 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0549 0550 QVERIFY(e->result() != nullptr); 0551 QCOMPARE(e->result()->type(), (int)Cantor::ImageResult::Type ); 0552 QVERIFY(!e->result()->data().isNull()); 0553 QVERIFY(e->errorMessage().isNull()); 0554 } 0555 0556 void TestOctave::testCantorPlot3d() 0557 { 0558 auto* e = evalExp( QLatin1String("cantor_plot3d('cos(x)*sin(y)', 'x', -10,10, 'y', -10,10);") ); 0559 QVERIFY(e != nullptr); 0560 0561 if(session()->status() == Cantor::Session::Running) 0562 waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); 0563 0564 QVERIFY(e->result() != nullptr); 0565 QCOMPARE(e->result()->type(), (int)Cantor::ImageResult::Type ); 0566 QVERIFY(!e->result()->data().isNull()); 0567 QVERIFY(e->errorMessage().isNull()); 0568 } 0569 0570 void TestOctave::testInvalidSyntax() 0571 { 0572 auto* e = evalExp( QLatin1String("2+2*+.") ); 0573 0574 QVERIFY( e != nullptr ); 0575 QCOMPARE( e->status(), Cantor::Expression::Error ); 0576 } 0577 0578 void TestOctave::testHelpRequest() 0579 { 0580 auto* e = evalExp(QLatin1String("help printf")); 0581 0582 QVERIFY(e != nullptr); 0583 QCOMPARE(e->status(), Cantor::Expression::Status::Done); 0584 QVERIFY(e->result() != nullptr); 0585 QCOMPARE(e->result()->type(), (int)Cantor::HelpResult::Type); 0586 QString text = QString::fromLatin1("Print optional arguments under the control of the template").toHtmlEscaped(); 0587 text.replace(QLatin1Char(' '), QLatin1String(" ")); 0588 QVERIFY(e->result()->toHtml().contains(text)); 0589 } 0590 0591 void TestOctave::testSyntaxHelp() 0592 { 0593 Cantor::SyntaxHelpObject* help = session()->syntaxHelpFor(QLatin1String("abs")); 0594 help->fetchSyntaxHelp(); 0595 waitForSignal(help, SIGNAL(done())); 0596 0597 QString text = QString::fromLatin1("Compute the magnitude").toHtmlEscaped(); 0598 text.replace(QLatin1Char(' '), QLatin1String(" ")); 0599 QVERIFY(help->toHtml().contains(text)); 0600 } 0601 0602 void TestOctave::testLoginLogout() 0603 { 0604 // Logout from session twice and all must works fine 0605 session()->logout(); 0606 session()->logout(); 0607 0608 // Login in session twice and all must works fine 0609 session()->login(); 0610 session()->login(); 0611 } 0612 0613 void TestOctave::testRestartWhileRunning() 0614 { 0615 auto* e1=session()->evaluateExpression(QLatin1String("sleep(5)")); 0616 0617 session()->logout(); 0618 QCOMPARE(e1->status(), Cantor::Expression::Interrupted); 0619 session()->login(); 0620 0621 auto* e2=evalExp( QLatin1String("2+2") ); 0622 0623 QVERIFY(e2 != nullptr); 0624 QVERIFY(e2->result() != nullptr); 0625 0626 QCOMPARE(cleanOutput(e2->result()->data().toString() ), QLatin1String("ans = 4")); 0627 } 0628 0629 QTEST_MAIN( TestOctave ) 0630