• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kate
 

kate

  • kate
  • part
test_regression.cpp
1
26#include <stdlib.h>
27#include <sys/time.h>
28#include <sys/resource.h>
29#include <sys/types.h>
30#include <unistd.h>
31#include <pwd.h>
32#include <signal.h>
33
34#include <tdeapplication.h>
35#include <tdestandarddirs.h>
36#include <tqimage.h>
37#include <tqfile.h>
38#include "test_regression.h"
39#include <unistd.h>
40#include <stdio.h>
41
42#include <tdeaction.h>
43#include <tdecmdlineargs.h>
44#include "katefactory.h"
45#include <tdeio/job.h>
46#include <tdemainwindow.h>
47#include <ksimpleconfig.h>
48#include <tdeglobalsettings.h>
49
50#include <tqcolor.h>
51#include <tqcursor.h>
52#include <tqdir.h>
53#include <tqevent.h>
54#include <tqobject.h>
55#include <tqpushbutton.h>
56#include <tqscrollview.h>
57#include <tqstring.h>
58#include <tqregexp.h>
59#include <tqtextstream.h>
60#include <tqvaluelist.h>
61#include <tqwidget.h>
62#include <tqfileinfo.h>
63#include <tqtimer.h>
64#include <kstatusbar.h>
65#include <tqfileinfo.h>
66
67#include "katedocument.h"
68#include "kateview.h"
69#include <tdeparts/browserextension.h>
70#include "katejscript.h"
71#include "katedocumenthelpers.h"
72#include "kateconfig.h"
73#include "../interfaces/katecmd.h"
74
75using namespace KJS;
76
77#define BASE_DIR_CONFIG "/.testkateregression-3.5"
78
79//BEGIN TestJScriptEnv
80
81TestJScriptEnv::TestJScriptEnv(KateDocument *part) {
82 ExecState *exec = m_interpreter->globalExec();
83
84 KJS::ObjectImp *wd = wrapDocument(m_interpreter->globalExec(), part);
85 KateView *v = static_cast<KateView *>(part->widget());
86 KJS::ObjectImp *wv = new KateViewObject(exec, v, wrapView(m_interpreter->globalExec(), v));
87
88 *m_view = KJS::Object(wv);
89 *m_document = KJS::Object(wd);
90 m_output = new OutputObject(exec, part, v);
91 m_output->ref();
92
93 // recreate properties
94 m_interpreter->globalObject().put(exec, "document", *m_document);
95 m_interpreter->globalObject().put(exec, "view", *m_view);
96 // create new properties
97 m_interpreter->globalObject().put(exec, "output", KJS::Object(m_output));
98 // add convenience shortcuts
99 m_interpreter->globalObject().put(exec, "d", *m_document);
100 m_interpreter->globalObject().put(exec, "v", *m_view);
101 m_interpreter->globalObject().put(exec, "out", KJS::Object(m_output));
102 m_interpreter->globalObject().put(exec, "o", KJS::Object(m_output));
103}
104
105TestJScriptEnv::~TestJScriptEnv() {
106 m_output->deref();
107}
108
109//END TestJScriptEnv
110
111//BEGIN KateViewObject
112
113KateViewObject::KateViewObject(ExecState *exec, KateView *v, ObjectImp *fallback)
114 : view(v), fallback(fallback)
115{
116// put a function
117#define PUT_FUNC(name, enumval) \
118 putDirect(#name, new KateViewFunction(exec,v,KateViewFunction::enumval,1), DontEnum)
119 fallback->ref();
120
121 PUT_FUNC(keyReturn, KeyReturn);
122 PUT_FUNC(enter, KeyReturn);
123 PUT_FUNC(type, Type);
124 PUT_FUNC(keyDelete, KeyDelete);
125 PUT_FUNC(deleteWordRight, DeleteWordRight);
126 PUT_FUNC(transpose, Transpose);
127 PUT_FUNC(cursorLeft, CursorLeft);
128 PUT_FUNC(cursorPrev, CursorLeft);
129 PUT_FUNC(left, CursorLeft);
130 PUT_FUNC(prev, CursorLeft);
131 PUT_FUNC(shiftCursorLeft, ShiftCursorLeft);
132 PUT_FUNC(shiftCursorPrev, ShiftCursorLeft);
133 PUT_FUNC(shiftLeft, ShiftCursorLeft);
134 PUT_FUNC(shiftPrev, ShiftCursorLeft);
135 PUT_FUNC(cursorRight, CursorRight);
136 PUT_FUNC(cursorNext, CursorRight);
137 PUT_FUNC(right, CursorRight);
138 PUT_FUNC(next, CursorRight);
139 PUT_FUNC(shiftCursorRight, ShiftCursorRight);
140 PUT_FUNC(shiftCursorNext, ShiftCursorRight);
141 PUT_FUNC(shiftRight, ShiftCursorRight);
142 PUT_FUNC(shiftNext, ShiftCursorRight);
143 PUT_FUNC(wordLeft, WordLeft);
144 PUT_FUNC(wordPrev, WordLeft);
145 PUT_FUNC(shiftWordLeft, ShiftWordLeft);
146 PUT_FUNC(shiftWordPrev, ShiftWordLeft);
147 PUT_FUNC(wordRight, WordRight);
148 PUT_FUNC(wordNext, WordRight);
149 PUT_FUNC(shiftWordRight, ShiftWordRight);
150 PUT_FUNC(shiftWordNext, ShiftWordRight);
151 PUT_FUNC(home, Home);
152 PUT_FUNC(shiftHome, ShiftHome);
153 PUT_FUNC(end, End);
154 PUT_FUNC(shiftEnd, ShiftEnd);
155 PUT_FUNC(up, Up);
156 PUT_FUNC(shiftUp, ShiftUp);
157 PUT_FUNC(down, Down);
158 PUT_FUNC(shiftDown, ShiftDown);
159 PUT_FUNC(scrollUp, ScrollUp);
160 PUT_FUNC(scrollDown, ScrollDown);
161 PUT_FUNC(topOfView, TopOfView);
162 PUT_FUNC(shiftTopOfView, ShiftTopOfView);
163 PUT_FUNC(bottomOfView, BottomOfView);
164 PUT_FUNC(shiftBottomOfView, ShiftBottomOfView);
165 PUT_FUNC(pageUp, PageUp);
166 PUT_FUNC(shiftPageUp, ShiftPageUp);
167 PUT_FUNC(pageDown, PageDown);
168 PUT_FUNC(shiftPageDown, ShiftPageDown);
169 PUT_FUNC(top, Top);
170 PUT_FUNC(shiftTop, ShiftTop);
171 PUT_FUNC(bottom, Bottom);
172 PUT_FUNC(shiftBottom, ShiftBottom);
173 PUT_FUNC(toMatchingBracket, ToMatchingBracket);
174 PUT_FUNC(shiftToMatchingBracket, ShiftToMatchingBracket);
175#undef PUT_FUNC
176}
177
178KateViewObject::~KateViewObject()
179{
180 fallback->deref();
181}
182
183const ClassInfo *KateViewObject::classInfo() const {
184 // evil hack II: disguise as fallback, otherwise we can't fall back
185 return fallback->classInfo();
186}
187
188Value KateViewObject::get(ExecState *exec, const Identifier &propertyName) const
189{
190 ValueImp *val = getDirect(propertyName);
191 if (val)
192 return Value(val);
193
194 return fallback->get(exec, propertyName);
195}
196
197//END KateViewObject
198
199//BEGIN KateViewFunction
200
201KateViewFunction::KateViewFunction(ExecState */*exec*/, KateView *v, int _id, int length)
202{
203 m_view = v;
204 id = _id;
205 putDirect("length",length);
206}
207
208bool KateViewFunction::implementsCall() const
209{
210 return true;
211}
212
213Value KateViewFunction::call(ExecState *exec, Object &/*thisObj*/, const List &args)
214{
215 // calls a function repeatedly as specified by its first parameter (once
216 // if not specified).
217#define REP_CALL(enumval, func) \
218 case enumval: {\
219 int cnt = 1;\
220 if (args.size() > 0) cnt = args[0].toInt32(exec);\
221 while (cnt-- > 0) { m_view->func(); }\
222 return Undefined();\
223 }
224 switch (id) {
225 REP_CALL(KeyReturn, keyReturn);
226 REP_CALL(KeyDelete, keyDelete);
227 REP_CALL(DeleteWordRight, deleteWordRight);
228 REP_CALL(Transpose, transpose);
229 REP_CALL(CursorLeft, cursorLeft);
230 REP_CALL(ShiftCursorLeft, shiftCursorLeft);
231 REP_CALL(CursorRight, cursorRight);
232 REP_CALL(ShiftCursorRight, shiftCursorRight);
233 REP_CALL(WordLeft, wordLeft);
234 REP_CALL(ShiftWordLeft, shiftWordLeft);
235 REP_CALL(WordRight, wordRight);
236 REP_CALL(ShiftWordRight, shiftWordRight);
237 REP_CALL(Home, home);
238 REP_CALL(ShiftHome, shiftHome);
239 REP_CALL(End, end);
240 REP_CALL(ShiftEnd, shiftEnd);
241 REP_CALL(Up, up);
242 REP_CALL(ShiftUp, shiftUp);
243 REP_CALL(Down, down);
244 REP_CALL(ShiftDown, shiftDown);
245 REP_CALL(ScrollUp, scrollUp);
246 REP_CALL(ScrollDown, scrollDown);
247 REP_CALL(TopOfView, topOfView);
248 REP_CALL(ShiftTopOfView, shiftTopOfView);
249 REP_CALL(BottomOfView, bottomOfView);
250 REP_CALL(ShiftBottomOfView, shiftBottomOfView);
251 REP_CALL(PageUp, pageUp);
252 REP_CALL(ShiftPageUp, shiftPageUp);
253 REP_CALL(PageDown, pageDown);
254 REP_CALL(ShiftPageDown, shiftPageDown);
255 REP_CALL(Top, top);
256 REP_CALL(ShiftTop, shiftTop);
257 REP_CALL(Bottom, bottom);
258 REP_CALL(ShiftBottom, shiftBottom);
259 REP_CALL(ToMatchingBracket, toMatchingBracket);
260 REP_CALL(ShiftToMatchingBracket, shiftToMatchingBracket);
261 case Type: {
262 UString str = args[0].toString(exec);
263 TQString res = str.qstring();
264 return Boolean(m_view->doc()->typeChars(m_view, res));
265 }
266 }
267
268 return Undefined();
269#undef REP_CALL
270}
271
272//END KateViewFunction
273
274//BEGIN OutputObject
275
276OutputObject::OutputObject(KJS::ExecState *exec, KateDocument *d, KateView *v) : doc(d), view(v), changed(0), outstr(0) {
277 putDirect("write", new OutputFunction(exec,this,OutputFunction::Write,-1), DontEnum);
278 putDirect("print", new OutputFunction(exec,this,OutputFunction::Write,-1), DontEnum);
279 putDirect("writeln", new OutputFunction(exec,this,OutputFunction::Writeln,-1), DontEnum);
280 putDirect("println", new OutputFunction(exec,this,OutputFunction::Writeln,-1), DontEnum);
281 putDirect("writeLn", new OutputFunction(exec,this,OutputFunction::Writeln,-1), DontEnum);
282 putDirect("printLn", new OutputFunction(exec,this,OutputFunction::Writeln,-1), DontEnum);
283
284 putDirect("writeCursorPosition", new OutputFunction(exec,this,OutputFunction::WriteCursorPosition,-1), DontEnum);
285 putDirect("cursorPosition", new OutputFunction(exec,this,OutputFunction::WriteCursorPosition,-1), DontEnum);
286 putDirect("pos", new OutputFunction(exec,this,OutputFunction::WriteCursorPosition,-1), DontEnum);
287 putDirect("writeCursorPositionln", new OutputFunction(exec,this,OutputFunction::WriteCursorPositionln,-1), DontEnum);
288 putDirect("cursorPositionln", new OutputFunction(exec,this,OutputFunction::WriteCursorPositionln,-1), DontEnum);
289 putDirect("posln", new OutputFunction(exec,this,OutputFunction::WriteCursorPositionln,-1), DontEnum);
290
291}
292
293OutputObject::~OutputObject() {
294}
295
296KJS::UString OutputObject::className() const {
297 return UString("OutputObject");
298}
299
300//END OutputObject
301
302//BEGIN OutputFunction
303
304OutputFunction::OutputFunction(KJS::ExecState *exec, OutputObject *output, int _id, int length)
305 : o(output)
306{
307 id = _id;
308 if (length >= 0)
309 putDirect("length",length);
310}
311
312bool OutputFunction::implementsCall() const
313{
314 return true;
315}
316
317KJS::Value OutputFunction::call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args)
318{
319 if (!*o->changed) *o->outstr = TQString();
320
321 switch (id) {
322 case Write:
323 case Writeln: {
324 // Gather all parameters and concatenate to string
325 TQString res;
326 for (int i = 0; i < args.size(); i++) {
327 res += args[i].toString(exec).qstring();
328 }
329
330 if (id == Writeln)
331 res += "\n";
332
333 *o->outstr += res;
334 break;
335 }
336 case WriteCursorPositionln:
337 case WriteCursorPosition: {
338 // Gather all parameters and concatenate to string
339 TQString res;
340 for (int i = 0; i < args.size(); i++) {
341 res += args[i].toString(exec).qstring();
342 }
343
344 // Append cursor position
345 uint l, c;
346 o->view->cursorPosition(&l, &c);
347 res += "(" + TQString::number(l) + "," + TQString::number(c) + ")";
348
349 if (id == WriteCursorPositionln)
350 res += "\n";
351
352 *o->outstr += res;
353 break;
354 }
355 }
356
357 *o->changed = true;
358 return Undefined();
359}
360
361//END OutputFunction
362
363// -------------------------------------------------------------------------
364
365const char failureSnapshotPrefix[] = "testkateregressionrc-FS.";
366
367static TQString findMostRecentFailureSnapshot() {
368 TQDir dir(tdeApp->dirs()->saveLocation("config"),
369 TQString(failureSnapshotPrefix)+"*",
370 TQDir::Time, TQDir::Files);
371 return dir[0].mid(sizeof failureSnapshotPrefix - 1);
372}
373
374static TDECmdLineOptions options[] =
375{
376 { "b", 0, 0 },
377 { "base <base_dir>", "Directory containing tests, basedir and output directories.", 0},
378 { "cmp-failures <snapshot>", "Compare failures of this testrun against snapshot <snapshot>. Defaults to the most recently captured failure snapshot or none if none exists.", 0 },
379 { "d", 0, 0 },
380 { "debug", "Do not supress debug output", 0},
381 { "g", 0, 0 } ,
382 { "genoutput", "Regenerate baseline (instead of checking)", 0 } ,
383 { "keep-output", "Keep output files even on success", 0 },
384 { "save-failures <snapshot>", "Save failures of this testrun as failure snapshot <snapshot>", 0 },
385 { "s", 0, 0 } ,
386 { "show", "Show the window while running tests", 0 } ,
387 { "t", 0, 0 } ,
388 { "test <filename>", "Only run a single test. Multiple options allowed.", 0 } ,
389 { "o", 0, 0 },
390 { "output <directory>", "Put output in <directory> instead of <base_dir>/output", 0 } ,
391 { "+[base_dir]", "Directory containing tests,basedir and output directories. Only regarded if -b is not specified.", 0 } ,
392 { "+[testcases]", "Relative path to testcase, or directory of testcases to be run (equivalent to -t).", 0 } ,
393 TDECmdLineLastOption
394};
395
396int main(int argc, char *argv[])
397{
398 // forget about any settings
399 passwd* pw = getpwuid( getuid() );
400 if (!pw) {
401 fprintf(stderr, "dang, I don't even know who I am.\n");
402 exit(1);
403 }
404
405 TQString kh("/var/tmp/%1_kate_non_existent");
406 kh = kh.arg( pw->pw_name );
407 setenv( "TDEHOME", kh.latin1(), 1 );
408 setenv( "LC_ALL", "C", 1 );
409 setenv( "LANG", "C", 1 );
410
411// signal( SIGALRM, signal_handler );
412
413 TDECmdLineArgs::init(argc, argv, "testregression", "TestRegression",
414 "Regression tester for kate", "1.0");
415 TDECmdLineArgs::addCmdLineOptions(options);
416
417 TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs( );
418
419 TQCString baseDir = args->getOption("base");
420 TQCString baseDirConfigFile(::getenv("HOME") + TQCString(BASE_DIR_CONFIG));
421 {
422 TQFile baseDirConfig(baseDirConfigFile);
423 if (baseDirConfig.open(IO_ReadOnly)) {
424 TQTextStream bds(&baseDirConfig);
425 baseDir = bds.readLine().latin1();
426 }
427 }
428
429 if ( args->count() < 1 && baseDir.isEmpty() ) {
430 printf("For regression testing, make sure to have checked out the kate regression\n"
431 "testsuite from svn:\n"
432 "\tsvn co \"https://<user>@svn.kde.org:/home/kde/trunk/tests/katetests/regression\"\n"
433 "Remember the root path into which you checked out the testsuite.\n"
434 "\n");
435 printf("%s needs the root path of the kate regression\n"
436 "testsuite to function properly\n"
437 "By default, the root path is looked up in the file\n"
438 "\t%s\n"
439 "If it doesn't exist yet, create it by invoking\n"
440 "\techo \"<root-path>\" > %s\n"
441 "You may override the location by specifying the root explicitly on the\n"
442 "command line with option -b\n"
443 "", TDECmdLineArgs::appName(),
444 (const char *)baseDirConfigFile,
445 (const char *)baseDirConfigFile);
446 ::exit( 1 );
447 }
448
449 int testcase_index = 0;
450 if (baseDir.isEmpty()) baseDir = args->arg(testcase_index++);
451
452 TQFileInfo bdInfo(baseDir);
453 baseDir = TQFile::encodeName(bdInfo.absFilePath());
454
455 const char *subdirs[] = {"tests", "baseline", "output", "resources"};
456 for ( int i = 0; i < 2; i++ ) {
457 TQFileInfo sourceDir(TQFile::encodeName( baseDir ) + "/" + subdirs[i]);
458 if ( !sourceDir.exists() || !sourceDir.isDir() ) {
459 fprintf(stderr,"ERROR: Source directory \"%s/%s\": no such directory.\n", (const char *)baseDir, subdirs[i]);
460 exit(1);
461 }
462 }
463
464 TDEApplication a;
465 a.disableAutoDcopRegistration();
466 a.setStyle("windows");
467 KSimpleConfig cfg( "testkateregressionrc" );
468 cfg.setGroup("Kate Document Defaults");
469 cfg.writeEntry("Basic Config Flags",
470 KateDocumentConfig::cfBackspaceIndents
471// | KateDocumentConfig::cfWordWrap
472// | KateDocumentConfig::cfRemoveSpaces
473 | KateDocumentConfig::cfWrapCursor
474// | KateDocumentConfig::cfAutoBrackets
475// | KateDocumentConfig::cfTabIndentsMode
476// | KateDocumentConfig::cfOvr
477 | KateDocumentConfig::cfKeepIndentProfile
478 | KateDocumentConfig::cfKeepExtraSpaces
479 | KateDocumentConfig::cfTabIndents
480 | KateDocumentConfig::cfShowTabs
481 | KateDocumentConfig::cfSpaceIndent
482 | KateDocumentConfig::cfSmartHome
483 | KateDocumentConfig::cfTabInsertsTab
484// | KateDocumentConfig::cfReplaceTabsDyn
485// | KateDocumentConfig::cfRemoveTrailingDyn
486 | KateDocumentConfig::cfDoxygenAutoTyping
487// | KateDocumentConfig::cfMixedIndent
488 | KateDocumentConfig::cfIndentPastedText
489 );
490 cfg.sync();
491
492 int rv = 1;
493
494 {
495 KSimpleConfig dc( "kdebugrc" );
496 // FIXME adapt to kate
497 static int areas[] = { 1000, 13000, 13001, 13002, 13010,
498 13020, 13025, 13030, 13033, 13035,
499 13040, 13050, 13051, 7000, 7006, 170,
500 171, 7101, 7002, 7019, 7027, 7014,
501 7001, 7011, 6070, 6080, 6090, 0};
502 int channel = args->isSet( "debug" ) ? 2 : 4;
503 for ( int i = 0; areas[i]; ++i ) {
504 dc.setGroup( TQString::number( areas[i] ) );
505 dc.writeEntry( "InfoOutput", channel );
506 }
507 dc.sync();
508
509 kdClearDebugConfig();
510 }
511
512 // create widgets
513 KateFactory *fac = KateFactory::self();
514 TDEMainWindow *toplevel = new TDEMainWindow();
515 KateDocument *part = new KateDocument(/*bSingleViewMode*/true,
516 /*bBrowserView*/false,
517 /*bReadOnly*/false,
518 /*parentWidget*/toplevel,
519 /*widgetName*/"testkate");
520 part->readConfig(&cfg);
521
522 toplevel->setCentralWidget( part->widget() );
523
524 Q_ASSERT(part->config()->configFlags() & KateDocumentConfig::cfDoxygenAutoTyping);
525
526 bool visual = false;
527 if (args->isSet("show"))
528 visual = true;
529
530 a.setTopWidget(part->widget());
531 a.setMainWidget( toplevel );
532 if ( visual )
533 toplevel->show();
534
535 // we're not interested
536 toplevel->statusBar()->hide();
537
538 if (!getenv("TDE_DEBUG")) {
539 // set ulimits
540 rlimit vmem_limit = { 256*1024*1024, RLIM_INFINITY }; // 256Mb Memory should suffice
541 setrlimit(RLIMIT_AS, &vmem_limit);
542 rlimit stack_limit = { 8*1024*1024, RLIM_INFINITY }; // 8Mb Memory should suffice
543 setrlimit(RLIMIT_STACK, &stack_limit);
544 }
545
546 // run the tests
547 RegressionTest *regressionTest = new RegressionTest(part,
548 &cfg,
549 baseDir,
550 args->getOption("output"),
551 args->isSet("genoutput"));
552 TQObject::connect(part->browserExtension(), TQ_SIGNAL(openURLRequest(const KURL &, const KParts::URLArgs &)),
553 regressionTest, TQ_SLOT(slotOpenURL(const KURL&, const KParts::URLArgs &)));
554 TQObject::connect(part->browserExtension(), TQ_SIGNAL(resizeTopLevelWidget( int, int )),
555 regressionTest, TQ_SLOT(resizeTopLevelWidget( int, int )));
556
557 regressionTest->m_keepOutput = args->isSet("keep-output");
558 regressionTest->m_showGui = args->isSet("show");
559
560 {
561 TQString failureSnapshot = args->getOption("cmp-failures");
562 if (failureSnapshot.isEmpty())
563 failureSnapshot = findMostRecentFailureSnapshot();
564 if (!failureSnapshot.isEmpty())
565 regressionTest->setFailureSnapshotConfig(
566 new KSimpleConfig(failureSnapshotPrefix + failureSnapshot, true),
567 failureSnapshot);
568 }
569
570 if (args->isSet("save-failures")) {
571 TQString failureSaver = args->getOption("save-failures");
572 regressionTest->setFailureSnapshotSaver(
573 new KSimpleConfig(failureSnapshotPrefix + failureSaver, false),
574 failureSaver);
575 }
576
577 bool result = false;
578 QCStringList tests = args->getOptionList("test");
579 // merge testcases specified on command line
580 for (; testcase_index < args->count(); testcase_index++)
581 tests << args->arg(testcase_index);
582 if (tests.count() > 0)
583 for (TQValueListConstIterator<TQCString> it = tests.begin(); it != tests.end(); ++it) {
584 result = regressionTest->runTests(*it,true);
585 if (!result) break;
586 }
587 else
588 result = regressionTest->runTests();
589
590 if (result) {
591 if (args->isSet("genoutput")) {
592 printf("\nOutput generation completed.\n");
593 }
594 else {
595 printf("\nTests completed.\n");
596 printf("Total: %d\n",
597 regressionTest->m_passes_work+
598 regressionTest->m_passes_fail+
599 regressionTest->m_failures_work+
600 regressionTest->m_failures_fail+
601 regressionTest->m_errors);
602 printf("Passes: %d",regressionTest->m_passes_work);
603 if ( regressionTest->m_passes_fail )
604 printf( " (%d unexpected passes)", regressionTest->m_passes_fail );
605 if (regressionTest->m_passes_new)
606 printf(" (%d new since %s)", regressionTest->m_passes_new, regressionTest->m_failureComp->group().latin1());
607 printf( "\n" );
608 printf("Failures: %d",regressionTest->m_failures_work);
609 if ( regressionTest->m_failures_fail )
610 printf( " (%d expected failures)", regressionTest->m_failures_fail );
611 if ( regressionTest->m_failures_new )
612 printf(" (%d new since %s)", regressionTest->m_failures_new, regressionTest->m_failureComp->group().latin1());
613 printf( "\n" );
614 if ( regressionTest->m_errors )
615 printf("Errors: %d\n",regressionTest->m_errors);
616
617 TQFile list( regressionTest->m_outputDir + "/links.html" );
618 list.open( IO_WriteOnly|IO_Append );
619 TQString link, cl;
620 link = TQString( "<hr>%1 failures. (%2 expected failures)" )
621 .arg(regressionTest->m_failures_work )
622 .arg( regressionTest->m_failures_fail );
623 if (regressionTest->m_failures_new)
624 link += TQString(" <span style=\"color:red;font-weight:bold\">(%1 new failures since %2)</span>")
625 .arg(regressionTest->m_failures_new)
626 .arg(regressionTest->m_failureComp->group());
627 if (regressionTest->m_passes_new)
628 link += TQString(" <p style=\"color:green;font-weight:bold\">%1 new passes since %2</p>")
629 .arg(regressionTest->m_passes_new)
630 .arg(regressionTest->m_failureComp->group());
631 list.writeBlock( link.latin1(), link.length() );
632 list.close();
633 }
634 }
635
636 // Only return a 0 exit code if all tests were successful
637 if (regressionTest->m_failures_work == 0 && regressionTest->m_errors == 0)
638 rv = 0;
639
640 // cleanup
641 delete regressionTest;
642 delete part;
643 delete toplevel;
644// delete fac;
645
646 return rv;
647}
648
649// -------------------------------------------------------------------------
650
651RegressionTest *RegressionTest::curr = 0;
652
653RegressionTest::RegressionTest(KateDocument *part, TDEConfig *baseConfig,
654 const TQString &baseDir,
655 const TQString &outputDir, bool _genOutput)
656 : TQObject(part)
657{
658 m_part = part;
659 m_view = static_cast<KateView *>(m_part->widget());
660 m_baseConfig = baseConfig;
661 m_baseDir = baseDir;
662 m_baseDir = m_baseDir.replace( "//", "/" );
663 if ( m_baseDir.endsWith( "/" ) )
664 m_baseDir = m_baseDir.left( m_baseDir.length() - 1 );
665 if (outputDir.isEmpty())
666 m_outputDir = m_baseDir + "/output";
667 else
668 m_outputDir = outputDir;
669 createMissingDirs(m_outputDir + "/");
670 m_keepOutput = false;
671 m_genOutput = _genOutput;
672 m_failureComp = 0;
673 m_failureSave = 0;
674 m_showGui = false;
675 m_passes_work = m_passes_fail = m_passes_new = 0;
676 m_failures_work = m_failures_fail = m_failures_new = 0;
677 m_errors = 0;
678
679 ::unlink( TQFile::encodeName( m_outputDir + "/links.html" ) );
680 TQFile f( m_outputDir + "/empty.html" );
681 TQString s;
682 f.open( IO_WriteOnly | IO_Truncate );
683 s = "<html><body>Follow the white rabbit";
684 f.writeBlock( s.latin1(), s.length() );
685 f.close();
686 f.setName( m_outputDir + "/index.html" );
687 f.open( IO_WriteOnly | IO_Truncate );
688 s = "<html><frameset cols=150,*><frame src=links.html><frame name=content src=empty.html>";
689 f.writeBlock( s.latin1(), s.length() );
690 f.close();
691
692 curr = this;
693}
694
695#include <tqobjectlist.h>
696
697static TQStringList readListFile( const TQString &filename )
698{
699 // Read ignore file for this directory
700 TQString ignoreFilename = filename;
701 TQFileInfo ignoreInfo(ignoreFilename);
702 TQStringList ignoreFiles;
703 if (ignoreInfo.exists()) {
704 TQFile ignoreFile(ignoreFilename);
705 if (!ignoreFile.open(IO_ReadOnly)) {
706 fprintf(stderr,"Can't open %s\n",ignoreFilename.latin1());
707 exit(1);
708 }
709 TQTextStream ignoreStream(&ignoreFile);
710 TQString line;
711 while (!(line = ignoreStream.readLine()).isNull())
712 ignoreFiles.append(line);
713 ignoreFile.close();
714 }
715 return ignoreFiles;
716}
717
718RegressionTest::~RegressionTest()
719{
720 // Important! Delete comparison config *first* as saver config
721 // might point to the same physical file.
722 delete m_failureComp;
723 delete m_failureSave;
724}
725
726void RegressionTest::setFailureSnapshotConfig(TDEConfig *cfg, const TQString &sname)
727{
728 Q_ASSERT(cfg);
729 m_failureComp = cfg;
730 m_failureComp->setGroup(sname);
731}
732
733void RegressionTest::setFailureSnapshotSaver(TDEConfig *cfg, const TQString &sname)
734{
735 Q_ASSERT(cfg);
736 m_failureSave = cfg;
737 m_failureSave->setGroup(sname);
738}
739
740TQStringList RegressionTest::concatListFiles(const TQString &relPath, const TQString &filename)
741{
742 TQStringList cmds;
743 int pos = relPath.findRev('/');
744 if (pos >= 0)
745 cmds += concatListFiles(relPath.left(pos), filename);
746 cmds += readListFile(m_baseDir + "/tests/" + relPath + "/" + filename);
747 return cmds;
748}
749
750bool RegressionTest::runTests(TQString relPath, bool mustExist, int known_failure)
751{
752 m_currentOutput = TQString::null;
753
754 if (!TQFile(m_baseDir + "/tests/"+relPath).exists()) {
755 fprintf(stderr,"%s: No such file or directory\n",relPath.latin1());
756 return false;
757 }
758
759 TQString fullPath = m_baseDir + "/tests/"+relPath;
760 TQFileInfo info(fullPath);
761
762 if (!info.exists() && mustExist) {
763 fprintf(stderr,"%s: No such file or directory\n",relPath.latin1());
764 return false;
765 }
766
767 if (!info.isReadable() && mustExist) {
768 fprintf(stderr,"%s: Access denied\n",relPath.latin1());
769 return false;
770 }
771
772 if (info.isDir()) {
773 TQStringList ignoreFiles = readListFile( m_baseDir + "/tests/"+relPath+"/ignore" );
774 TQStringList failureFiles = readListFile( m_baseDir + "/tests/"+relPath+"/KNOWN_FAILURES" );
775
776 // Run each test in this directory, recusively
777 TQDir sourceDir(m_baseDir + "/tests/"+relPath);
778 for (uint fileno = 0; fileno < sourceDir.count(); fileno++) {
779 TQString filename = sourceDir[fileno];
780 TQString relFilename = relPath.isEmpty() ? filename : relPath+"/"+filename;
781
782 if (filename.startsWith(".") || ignoreFiles.contains(filename) )
783 continue;
784 int failure_type = NoFailure;
785 if ( failureFiles.contains( filename ) )
786 failure_type |= AllFailure;
787 if ( failureFiles.contains ( filename + "-result" ) )
788 failure_type |= ResultFailure;
789 runTests(relFilename, false, failure_type);
790 }
791 }
792 else if (info.isFile()) {
793
794 TQString relativeDir = TQFileInfo(relPath).dirPath();
795 TQString filename = info.fileName();
796 m_currentBase = m_baseDir + "/tests/"+relativeDir;
797 m_currentCategory = relativeDir;
798 m_currentTest = filename;
799 m_known_failures = known_failure;
800 m_outputCustomised = false;
801 // gather commands
802 // directory-specific commands
803 TQStringList commands = concatListFiles(relPath, ".kateconfig-commands");
804 // testcase-specific commands
805 commands += readListFile(m_currentBase + "/" + filename + "-commands");
806
807 rereadConfig(); // reset options to default
808 if ( filename.endsWith(".txt") ) {
809#if 0
810 if ( relPath.startsWith( "domts/" ) && !m_runJS )
811 return true;
812 if ( relPath.startsWith( "ecma/" ) && !m_runJS )
813 return true;
814#endif
815// if ( m_runHTML )
816 testStaticFile(relPath, commands);
817 }
818 else if (mustExist) {
819 fprintf(stderr,"%s: Not a valid test file (must be .txt)\n",relPath.latin1());
820 return false;
821 }
822 } else if (mustExist) {
823 fprintf(stderr,"%s: Not a regular file\n",relPath.latin1());
824 return false;
825 }
826
827 return true;
828}
829
830void RegressionTest::createLink( const TQString& test, int failures )
831{
832 createMissingDirs( m_outputDir + "/" + test + "-compare.html" );
833
834 TQFile list( m_outputDir + "/links.html" );
835 list.open( IO_WriteOnly|IO_Append );
836 TQString link;
837 link = TQString( "<a href=\"%1\" target=\"content\" title=\"%2\">" )
838 .arg( test + "-compare.html" )
839 .arg( test );
840 link += m_currentTest;
841 link += "</a> ";
842 if (failures & NewFailure)
843 link += "<span style=\"font-weight:bold;color:red\">";
844 link += "[";
845 if ( failures & ResultFailure )
846 link += "R";
847 link += "]";
848 if (failures & NewFailure)
849 link += "</span>";
850 link += "<br>\n";
851 list.writeBlock( link.latin1(), link.length() );
852 list.close();
853}
854
861static TQString makeRelativePath(const TQString &base, const TQString &path)
862{
863 TQString absBase = TQFileInfo(base).absFilePath();
864 TQString absPath = TQFileInfo(path).absFilePath();
865// kdDebug() << "absPath: \"" << absPath << "\"" << endl;
866// kdDebug() << "absBase: \"" << absBase << "\"" << endl;
867
868 // walk up to common ancestor directory
869 int pos = 0;
870 do {
871 pos++;
872 int newpos = absBase.find('/', pos);
873 if (newpos == -1) newpos = absBase.length();
874 TQConstString cmpPathComp(absPath.unicode() + pos, newpos - pos);
875 TQConstString cmpBaseComp(absBase.unicode() + pos, newpos - pos);
876// kdDebug() << "cmpPathComp: \"" << cmpPathComp.string() << "\"" << endl;
877// kdDebug() << "cmpBaseComp: \"" << cmpBaseComp.string() << "\"" << endl;
878// kdDebug() << "pos: " << pos << " newpos: " << newpos << endl;
879 if (cmpPathComp.string() != cmpBaseComp.string()) { pos--; break; }
880 pos = newpos;
881 } while (pos < (int)absBase.length() && pos < (int)absPath.length());
882 int basepos = pos < (int)absBase.length() ? pos + 1 : pos;
883 int pathpos = pos < (int)absPath.length() ? pos + 1 : pos;
884
885// kdDebug() << "basepos " << basepos << " pathpos " << pathpos << endl;
886
887 TQString rel;
888 {
889 TQConstString relBase(absBase.unicode() + basepos, absBase.length() - basepos);
890 TQConstString relPath(absPath.unicode() + pathpos, absPath.length() - pathpos);
891 // generate as many .. as there are path elements in relBase
892 if (relBase.string().length() > 0) {
893 for (int i = relBase.string().contains('/'); i > 0; --i)
894 rel += "../";
895 rel += "..";
896 if (relPath.string().length() > 0) rel += "/";
897 }
898 rel += relPath.string();
899 }
900 return rel;
901}
902
904static void pause(int msec)
905{
906 TQTime t;
907 t.start();
908 do {
909 tdeApp->processEvents();
910 } while (t.elapsed() < msec);
911}
912
913void RegressionTest::doFailureReport( const TQString& test, int failures )
914{
915 if ( failures == NoFailure ) {
916 ::unlink( TQFile::encodeName( m_outputDir + "/" + test + "-compare.html" ) );
917 return;
918 }
919
920 createLink( test, failures );
921
922 TQFile compare( m_outputDir + "/" + test + "-compare.html" );
923
924 TQString testFile = TQFileInfo(test).fileName();
925
926 TQString renderDiff;
927 TQString domDiff;
928
929 TQString relOutputDir = makeRelativePath(m_baseDir, m_outputDir);
930
931 // are blocking reads possible with TDEProcess?
932 char pwd[PATH_MAX];
933 (void) getcwd( pwd, PATH_MAX );
934 chdir( TQFile::encodeName( m_baseDir ) );
935
936 if ( failures & ResultFailure ) {
937 domDiff += "<pre>";
938 FILE *pipe = popen( TQString::fromLatin1( "diff -u baseline/%1-result %3/%2-result" )
939 .arg ( test, test, relOutputDir ).latin1(), "r" );
940 TQTextIStream *is = new TQTextIStream( pipe );
941 for ( int line = 0; line < 100 && !is->eof(); ++line ) {
942 TQString line = is->readLine();
943 line = line.replace( '<', "&lt;" );
944 line = line.replace( '>', "&gt;" );
945 domDiff += line + "\n";
946 }
947 delete is;
948 pclose( pipe );
949 domDiff += "</pre>";
950 }
951
952 chdir( pwd );
953
954 // create a relative path so that it works via web as well. ugly
955 TQString relpath = makeRelativePath(m_outputDir + "/"
956 + TQFileInfo(test).dirPath(), m_baseDir);
957
958 compare.open( IO_WriteOnly|IO_Truncate );
959 TQString cl;
960 cl = TQString( "<html><head><title>%1</title>" ).arg( test );
961 cl += TQString( "<script>\n"
962 "var pics = new Array();\n"
963 "pics[0]=new Image();\n"
964 "pics[0].src = '%1';\n"
965 "pics[1]=new Image();\n"
966 "pics[1].src = '%2';\n"
967 "var doflicker = 1;\n"
968 "var t = 1;\n"
969 "var lastb=0;\n" )
970 .arg( relpath+"/baseline/"+test+"-dump.png" )
971 .arg( testFile+"-dump.png" );
972 cl += TQString( "function toggleVisible(visible) {\n"
973 " document.getElementById('render').style.visibility= visible == 'render' ? 'visible' : 'hidden';\n"
974 " document.getElementById('image').style.visibility= visible == 'image' ? 'visible' : 'hidden';\n"
975 " document.getElementById('dom').style.visibility= visible == 'dom' ? 'visible' : 'hidden';\n"
976 "}\n"
977 "function show() { document.getElementById('image').src = pics[t].src; "
978 "document.getElementById('image').style.borderColor = t && !doflicker ? 'red' : 'gray';\n"
979 "toggleVisible('image');\n"
980 "}" );
981 cl += TQString ( "function runSlideShow(){\n"
982 " document.getElementById('image').src = pics[t].src;\n"
983 " if (doflicker)\n"
984 " t = 1 - t;\n"
985 " setTimeout('runSlideShow()', 200);\n"
986 "}\n"
987 "function m(b) { if (b == lastb) return; document.getElementById('b'+b).className='buttondown';\n"
988 " var e = document.getElementById('b'+lastb);\n"
989 " if(e) e.className='button';\n"
990 " lastb = b;\n"
991 "}\n"
992 "function showRender() { doflicker=0;toggleVisible('render')\n"
993 "}\n"
994 "function showDom() { doflicker=0;toggleVisible('dom')\n"
995 "}\n"
996 "</script>\n");
997
998 cl += TQString ("<style>\n"
999 ".buttondown { cursor: pointer; padding: 0px 20px; color: white; background-color: blue; border: inset blue 2px;}\n"
1000 ".button { cursor: pointer; padding: 0px 20px; color: black; background-color: white; border: outset blue 2px;}\n"
1001 ".diff { position: absolute; left: 10px; top: 100px; visibility: hidden; border: 1px black solid; background-color: white; color: black; /* width: 800; height: 600; overflow: scroll; */ }\n"
1002 "</style>\n" );
1003
1004 cl += TQString( "<body onload=\"m(5); toggleVisible('dom');\"" );
1005 cl += TQString(" text=black bgcolor=gray>\n<h1>%3</h1>\n" ).arg( test );
1006 if ( renderDiff.length() )
1007 cl += "<span id='b4' class='button' onclick='showRender();m(4)'>R-DIFF</span>&nbsp;\n";
1008 if ( domDiff.length() )
1009 cl += "<span id='b5' class='button' onclick='showDom();m(5);'>D-DIFF</span>&nbsp;\n";
1010 // The test file always exists - except for checkOutput called from *.js files
1011 if ( TQFile::exists( m_baseDir + "/tests/"+ test ) )
1012 cl += TQString( "<a class=button href=\"%1\">HTML</a>&nbsp;" )
1013 .arg( relpath+"/tests/"+test );
1014
1015 cl += TQString( "<hr>"
1016 "<img style='border: solid 5px gray' src=\"%1\" id='image'>" )
1017 .arg( relpath+"/baseline/"+test+"-dump.png" );
1018
1019 cl += "<div id='render' class='diff'>" + renderDiff + "</div>";
1020 cl += "<div id='dom' class='diff'>" + domDiff + "</div>";
1021
1022 cl += "</body></html>";
1023 compare.writeBlock( cl.latin1(), cl.length() );
1024 compare.close();
1025}
1026
1027void RegressionTest::testStaticFile(const TQString & filename, const TQStringList &commands)
1028{
1029 tqApp->mainWidget()->resize( 800, 600); // restore size
1030
1031 // Set arguments
1032 KParts::URLArgs args;
1033 if (filename.endsWith(".txt")) args.serviceType = "text/plain";
1034 m_part->browserExtension()->setURLArgs(args);
1035 // load page
1036 KURL url;
1037 url.setProtocol("file");
1038 url.setPath(TQFileInfo(m_baseDir + "/tests/"+filename).absFilePath());
1039 m_part->openURL(url);
1040
1041 // inject commands
1042 for (TQStringList::ConstIterator cit = commands.begin(); cit != commands.end(); ++cit) {
1043 TQString str = (*cit).stripWhiteSpace();
1044 if (str.isEmpty() || str.startsWith("#")) continue;
1045 Kate::Command *cmd = KateCmd::self()->queryCommand(str);
1046 if (cmd) {
1047 TQString msg;
1048 if (!cmd->exec(m_view, str, msg))
1049 fprintf(stderr, "ERROR executing command '%s': %s\n", str.latin1(), msg.latin1());
1050 }
1051 }
1052
1053 pause(200);
1054
1055 Q_ASSERT(m_part->config()->configFlags() & KateDocumentConfig::cfDoxygenAutoTyping);
1056
1057 bool script_error = false;
1058 {
1059 // Execute script
1060 TestJScriptEnv jsenv(m_part);
1061 jsenv.output()->setChangedFlag(&m_outputCustomised);
1062 jsenv.output()->setOutputString(&m_outputString);
1063 script_error = evalJS(jsenv.interpreter(), m_baseDir + "/tests/"+TQFileInfo(filename).dirPath()+"/.kateconfig-script", true)
1064 && evalJS(jsenv.interpreter(), m_baseDir + "/tests/"+filename+"-script");
1065 }
1066
1067 int back_known_failures = m_known_failures;
1068
1069 if (!script_error) goto bail_out;
1070
1071 if (m_showGui) tdeApp->processEvents();
1072
1073 if ( m_genOutput ) {
1074 reportResult(checkOutput(filename+"-result"), "result");
1075 } else {
1076 int failures = NoFailure;
1077
1078 // compare with output file
1079 if ( m_known_failures & ResultFailure)
1080 m_known_failures = AllFailure;
1081 bool newfail;
1082 if ( !reportResult( checkOutput(filename+"-result"), "result", &newfail ) )
1083 failures |= ResultFailure;
1084 if (newfail)
1085 failures |= NewFailure;
1086
1087 doFailureReport(filename, failures );
1088 }
1089
1090bail_out:
1091 m_known_failures = back_known_failures;
1092 m_part->setModified(false);
1093 m_part->closeURL();
1094}
1095
1096bool RegressionTest::evalJS(Interpreter &interp, const TQString &filename, bool ignore_nonexistent)
1097{
1098 TQString fullSourceName = filename;
1099 TQFile sourceFile(fullSourceName);
1100
1101 if (!sourceFile.open(IO_ReadOnly)) {
1102 if (!ignore_nonexistent) {
1103 fprintf(stderr,"ERROR reading file %s\n",fullSourceName.latin1());
1104 m_errors++;
1105 }
1106 return ignore_nonexistent;
1107 }
1108
1109 TQTextStream stream ( &sourceFile );
1110 stream.setEncoding( TQTextStream::UnicodeUTF8 );
1111 TQString code = stream.read();
1112 sourceFile.close();
1113
1114 saw_failure = false;
1115 ignore_errors = false;
1116 Completion c = interp.evaluate(UString( code ) );
1117
1118 if ( /*report_result &&*/ !ignore_errors) {
1119 if (c.complType() == Throw) {
1120 TQString errmsg = c.value().toString(interp.globalExec()).qstring();
1121 printf( "ERROR: %s (%s)\n",filename.latin1(), errmsg.latin1());
1122 m_errors++;
1123 return false;
1124 }
1125 }
1126 return true;
1127}
1128
1129class GlobalImp : public ObjectImp {
1130public:
1131 virtual UString className() const { return "global"; }
1132};
1133
1134RegressionTest::CheckResult RegressionTest::checkOutput(const TQString &againstFilename)
1135{
1136 TQString absFilename = TQFileInfo(m_baseDir + "/baseline/" + againstFilename).absFilePath();
1137 if ( svnIgnored( absFilename ) ) {
1138 m_known_failures = NoFailure;
1139 return Ignored;
1140 }
1141
1142 CheckResult result = Success;
1143
1144 // compare result to existing file
1145 TQString outputFilename = TQFileInfo(m_outputDir + "/" + againstFilename).absFilePath();
1146 bool kf = false;
1147 if ( m_known_failures & AllFailure )
1148 kf = true;
1149 if ( kf )
1150 outputFilename += "-KF";
1151
1152 if ( m_genOutput )
1153 outputFilename = absFilename;
1154
1155 // get existing content
1156 TQString data;
1157 if (m_outputCustomised) {
1158 data = m_outputString;
1159 } else {
1160 data = m_part->text();
1161 }
1162
1163 TQFile file(absFilename);
1164 if (file.open(IO_ReadOnly)) {
1165 TQTextStream stream ( &file );
1166 stream.setEncoding( TQTextStream::UnicodeUTF8 );
1167
1168 TQString fileData = stream.read();
1169
1170 result = ( fileData == data ) ? Success : Failure;
1171 if ( !m_genOutput && result == Success && !m_keepOutput ) {
1172 ::unlink( TQFile::encodeName( outputFilename ) );
1173 return Success;
1174 }
1175 } else if (!m_genOutput) {
1176 fprintf(stderr, "Error reading file %s\n", absFilename.latin1());
1177 result = Failure;
1178 }
1179
1180 // generate result file
1181 createMissingDirs( outputFilename );
1182 TQFile file2(outputFilename);
1183 if (!file2.open(IO_WriteOnly)) {
1184 fprintf(stderr,"Error writing to file %s\n",outputFilename.latin1());
1185 exit(1);
1186 }
1187
1188 TQTextStream stream2(&file2);
1189 stream2.setEncoding( TQTextStream::UnicodeUTF8 );
1190 stream2 << data;
1191 if ( m_genOutput )
1192 printf("Generated %s\n", outputFilename.latin1());
1193
1194 return result;
1195}
1196
1197void RegressionTest::rereadConfig()
1198{
1199 m_baseConfig->setGroup("Kate Document Defaults");
1200 m_part->config()->readConfig(m_baseConfig);
1201 m_baseConfig->setGroup("Kate View Defaults");
1202 m_view->config()->readConfig(m_baseConfig);
1203}
1204
1205bool RegressionTest::reportResult(CheckResult result, const TQString & description, bool *newfail)
1206{
1207 if ( result == Ignored ) {
1208 //printf("IGNORED: ");
1209 //printDescription( description );
1210 return true; // no error
1211 } else
1212 return reportResult( result == Success, description, newfail );
1213}
1214
1215bool RegressionTest::reportResult(bool passed, const TQString & description, bool *newfail)
1216{
1217 if (newfail) *newfail = false;
1218
1219 if (m_genOutput)
1220 return true;
1221
1222 TQString filename(m_currentTest + "-" + description);
1223 if (!m_currentCategory.isEmpty())
1224 filename = m_currentCategory + "/" + filename;
1225
1226 const bool oldfailed = m_failureComp && m_failureComp->readNumEntry(filename);
1227 if (passed) {
1228 if ( m_known_failures & AllFailure ) {
1229 printf("PASS (unexpected!)");
1230 m_passes_fail++;
1231 } else {
1232 printf("PASS");
1233 m_passes_work++;
1234 }
1235 if (oldfailed) {
1236 printf(" (new)");
1237 m_passes_new++;
1238 }
1239 if (m_failureSave)
1240 m_failureSave->deleteEntry(filename);
1241 }
1242 else {
1243 if ( m_known_failures & AllFailure ) {
1244 printf("FAIL (known)");
1245 m_failures_fail++;
1246 passed = true; // we knew about it
1247 } else {
1248 printf("FAIL");
1249 m_failures_work++;
1250 }
1251 if (!oldfailed && m_failureComp) {
1252 printf(" (new)");
1253 m_failures_new++;
1254 if (newfail) *newfail = true;
1255 }
1256 if (m_failureSave)
1257 m_failureSave->writeEntry(filename, 1);
1258 }
1259 printf(": ");
1260
1261 printDescription( description );
1262 return passed;
1263}
1264
1265void RegressionTest::printDescription(const TQString& description)
1266{
1267 if (!m_currentCategory.isEmpty())
1268 printf("%s/", m_currentCategory.latin1());
1269
1270 printf("%s", m_currentTest.latin1());
1271
1272 if (!description.isEmpty()) {
1273 TQString desc = description;
1274 desc.replace( '\n', ' ' );
1275 printf(" [%s]", desc.latin1());
1276 }
1277
1278 printf("\n");
1279 fflush(stdout);
1280}
1281
1282void RegressionTest::createMissingDirs(const TQString & filename)
1283{
1284 TQFileInfo dif(filename);
1285 TQFileInfo dirInfo( dif.dirPath() );
1286 if (dirInfo.exists())
1287 return;
1288
1289 TQStringList pathComponents;
1290 TQFileInfo parentDir = dirInfo;
1291 pathComponents.prepend(parentDir.absFilePath());
1292 while (!parentDir.exists()) {
1293 TQString parentPath = parentDir.absFilePath();
1294 int slashPos = parentPath.findRev('/');
1295 if (slashPos < 0)
1296 break;
1297 parentPath = parentPath.left(slashPos);
1298 pathComponents.prepend(parentPath);
1299 parentDir = TQFileInfo(parentPath);
1300 }
1301 for (uint pathno = 1; pathno < pathComponents.count(); pathno++) {
1302 if (!TQFileInfo(pathComponents[pathno]).exists() &&
1303 !TQDir(pathComponents[pathno-1]).mkdir(pathComponents[pathno])) {
1304 fprintf(stderr,"Error creating directory %s\n",pathComponents[pathno].latin1());
1305 exit(1);
1306 }
1307 }
1308}
1309
1310void RegressionTest::slotOpenURL(const KURL &url, const KParts::URLArgs &args)
1311{
1312 m_part->browserExtension()->setURLArgs( args );
1313
1314 m_part->openURL(url);
1315}
1316
1317bool RegressionTest::svnIgnored( const TQString &filename )
1318{
1319 TQFileInfo fi( filename );
1320 TQString ignoreFilename = fi.dirPath() + "/svnignore";
1321 TQFile ignoreFile(ignoreFilename);
1322 if (!ignoreFile.open(IO_ReadOnly))
1323 return false;
1324
1325 TQTextStream ignoreStream(&ignoreFile);
1326 TQString line;
1327 while (!(line = ignoreStream.readLine()).isNull()) {
1328 if ( line == fi.fileName() )
1329 return true;
1330 }
1331 ignoreFile.close();
1332 return false;
1333}
1334
1335void RegressionTest::resizeTopLevelWidget( int w, int h )
1336{
1337 tqApp->mainWidget()->resize( w, h );
1338 // Since we're not visible, this doesn't have an immediate effect, TQWidget posts the event
1339 TQApplication::sendPostedEvents( 0, TQEvent::Resize );
1340}
1341
1342#include "test_regression.moc"
KSimpleConfig
KURL
KURL::setPath
void setPath(const TQString &path)
KURL::setProtocol
void setProtocol(const TQString &_txt)
Kate::Command
Kate Commands.
Definition: document.h:97
Kate::Command::exec
virtual bool exec(View *view, const TQString &cmd, TQString &msg)=0
Execute this command for the given view and cmd string, return a bool about success,...
OutputFunction
Customizing output to result-files.
Definition: test_regression.h:147
OutputObject
Customizing output to result-files.
Definition: test_regression.h:123
TDEApplication
TDEApplication::setTopWidget
void setTopWidget(TQWidget *topWidget)
TDEApplication::disableAutoDcopRegistration
static void disableAutoDcopRegistration()
TDECmdLineArgs
TDECmdLineArgs::isSet
bool isSet(const char *option) const
TDECmdLineArgs::appName
static const char * appName()
TDECmdLineArgs::getOptionList
QCStringList getOptionList(const char *option) const
TDECmdLineArgs::parsedArgs
static TDECmdLineArgs * parsedArgs(const char *id=0)
TDECmdLineArgs::addCmdLineOptions
static void addCmdLineOptions(const TDECmdLineOptions *options, const char *name=0, const char *id=0, const char *afterId=0)
TDECmdLineArgs::getOption
TQCString getOption(const char *option) const
TDECmdLineArgs::init
static void init(int _argc, char **_argv, const char *_appname, const char *programName, const char *_description, const char *_version, bool noTDEApp=false)
TDECmdLineArgs::arg
const char * arg(int n) const
TDECmdLineArgs::count
int count() const
TDEConfigBase::setGroup
void setGroup(const TQString &group)
TDEConfig
TDEMainWindow
TDEMainWindow::statusBar
KStatusBar * statusBar()
TDEMainWindow::show
virtual void show()
kdClearDebugConfig
void kdClearDebugConfig()
KJS
Cool, this is all we need here.
Definition: katejscript.cpp:53
TDEStdAccel::description
TQString description(StdAccel id)
KParts::URLArgs
KParts::URLArgs::serviceType
TQString serviceType
TDECmdLineOptions

kate

Skip menu "kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kate

Skip menu "kate"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kate by doxygen 1.9.4
This website is maintained by Timothy Pearson.