📄 test_regression.cpp
字号:
{ "b", 0, 0 }, { "base <base_dir>", "Directory containing tests, basedir and output directories.", 0}, { "d", 0, 0 }, { "debug", "Do not supress debug output", 0}, { "g", 0, 0 } , { "genoutput", "Regenerate baseline (instead of checking)", 0 } , { "s", 0, 0 } , { "show", "Show the window while running tests", 0 } , { "t", 0, 0 } , { "test <filename>", "Only run a single test. Multiple options allowed.", 0 } , { "js", "Only run .js tests", 0 }, { "html", "Only run .html tests", 0}, { "noxvfb", "Do not use Xvfb", 0}, { "o", 0, 0 }, { "output <directory>", "Put output in <directory> instead of <base_dir>/output", 0 } , { "+[base_dir]", "Directory containing tests,basedir and output directories. Only regarded if -b is not specified.", 0 } , { "+[testcases]", "Relative path to testcase, or directory of testcases to be run (equivalent to -t).", 0 } , KCmdLineLastOption};int main(int argc, char *argv[]){ // forget about any settings passwd* pw = getpwuid( getuid() ); if (!pw) { fprintf(stderr, "dang, I don't even know who I am.\n"); exit(1); } QString kh("/var/tmp/%1_non_existant"); kh = kh.arg( pw->pw_name ); setenv( "KDEHOME", kh.latin1(), 1 ); setenv( "LC_ALL", "C", 1 ); setenv( "LANG", "C", 1 ); signal( SIGALRM, signal_handler ); KCmdLineArgs::init(argc, argv, "testregression", "TestRegression", "Regression tester for khtml", "1.0"); KCmdLineArgs::addCmdLineOptions(options); KCmdLineArgs *args = KCmdLineArgs::parsedArgs( ); QCString baseDir = args->getOption("base"); if ( args->count() < 1 && baseDir.isEmpty() ) { KCmdLineArgs::usage(); ::exit( 1 ); } int testcase_index = 0; if (baseDir.isEmpty()) baseDir = args->arg(testcase_index++); QFileInfo bdInfo(baseDir); baseDir = QFile::encodeName(bdInfo.absFilePath()); const char *subdirs[] = {"tests", "baseline", "output", "resources"}; for ( int i = 0; i < 3; i++ ) { QFileInfo sourceDir(QFile::encodeName( baseDir ) + "/" + subdirs[i]); if ( !sourceDir.exists() || !sourceDir.isDir() ) { fprintf(stderr,"ERROR: Source directory \"%s/%s\": no such directory.\n", (const char *)baseDir, subdirs[i]); exit(1); } } if ( ::access( "/usr/X11R6/bin/Xvfb", X_OK ) ) { fprintf( stderr, "ERROR: We need /usr/X11R6/bin/Xvfb to be installed for reliable results\n" ); exit( 1 ); } if (args->isSet("xvfb")) { xvfb = fork(); if ( !xvfb ) { char buffer[1000]; sprintf( buffer, "%s/resources,/usr/X11R6/lib/X11/fonts/75dpi:unscaled,/usr/X11R6/lib/X11/fonts/misc:unscaled,/usr/X11R6/lib/X11/fonts/Type1", (const char *)baseDir ); execl( "/usr/X11R6/bin/Xvfb", "/usr/X11R6/bin/Xvfb", "-once", "-dpi", "100", "-screen", "0", "1024x768x16", "-ac", "-fp", buffer, ":47", (char*)NULL ); } setenv( "DISPLAY", ":47", 1 ); } KApplication a; a.disableAutoDcopRegistration(); a.setStyle( "windows" ); KSimpleConfig sc1( "cryptodefaults" ); sc1.setGroup( "Warnings" ); sc1.writeEntry( "OnUnencrypted", false ); a.config()->setGroup( "Notification Messages" ); a.config()->writeEntry( "kjscupguard_alarmhandler", true ); a.config()->setGroup("HTML Settings"); a.config()->writeEntry("ReportJSErrors", false); KConfig cfg( "khtmlrc" ); cfg.setGroup("HTML Settings"); cfg.writeEntry( "StandardFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT ); cfg.writeEntry( "FixedFont", HTML_DEFAULT_VIEW_FIXED_FONT ); cfg.writeEntry( "SerifFont", HTML_DEFAULT_VIEW_SERIF_FONT ); cfg.writeEntry( "SansSerifFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT ); cfg.writeEntry( "CursiveFont", HTML_DEFAULT_VIEW_CURSIVE_FONT ); cfg.writeEntry( "FantasyFont", HTML_DEFAULT_VIEW_FANTASY_FONT ); cfg.writeEntry( "MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE ); cfg.writeEntry( "MediumFontSize", 10 ); cfg.writeEntry( "Fonts", QStringList() ); cfg.writeEntry( "DefaultEncoding", "" ); cfg.setGroup("Java/JavaScript Settings"); cfg.writeEntry( "WindowOpenPolicy", KHTMLSettings::KJSWindowOpenAllow); cfg.sync(); int rv = 1; if ( !args->isSet( "debug" ) ) { KSimpleConfig dc( "kdebugrc" ); static int areas[] = { 1000, 6000, 6005, 6010, 6020, 6030, 6031, 6035, 6036, 6040, 6041, 6045, 6050, 6060, 6061, 7000, 7006, 170, 171, 7101, 7002, 7019, 7027, 7014, 7011, 6070, 6080, 6090, 0}; for ( int i = 0; areas[i]; ++i ) { dc.setGroup( QString::number( areas[i] ) ); dc.writeEntry( "InfoOutput", 4 ); } dc.sync(); kdClearDebugConfig(); } // create widgets KHTMLFactory *fac = new KHTMLFactory(); KMainWindow *toplevel = new KMainWindow(); KHTMLPart *part = new KHTMLPart( toplevel, 0, toplevel, 0, KHTMLPart::BrowserViewGUI ); toplevel->setCentralWidget( part->widget() ); part->setJScriptEnabled(true); part->executeScript(DOM::Node(), ""); // force the part to create an interpreter// part->setJavaEnabled(true); if (args->isSet("show")) visual = true; a.setTopWidget(part->widget()); a.setMainWidget( toplevel ); if ( visual ) toplevel->show(); // we're not interested toplevel->statusBar()->hide(); if (!getenv("KDE_DEBUG")) { // set ulimits rlimit vmem_limit = { 256*1024*1024, RLIM_INFINITY }; // 256Mb Memory should suffice setrlimit(RLIMIT_AS, &vmem_limit); rlimit stack_limit = { 8*1024*1024, RLIM_INFINITY }; // 8Mb Memory should suffice setrlimit(RLIMIT_STACK, &stack_limit); } // run the tests RegressionTest *regressionTest = new RegressionTest(part, baseDir, args->getOption("output"), args->isSet("genoutput"), !args->isSet( "html" ), !args->isSet( "js" )); QObject::connect(part->browserExtension(), SIGNAL(openURLRequest(const KURL &, const KParts::URLArgs &)), regressionTest, SLOT(slotOpenURL(const KURL&, const KParts::URLArgs &))); QObject::connect(part->browserExtension(), SIGNAL(resizeTopLevelWidget( int, int )), regressionTest, SLOT(resizeTopLevelWidget( int, int ))); bool result = false; QCStringList tests = args->getOptionList("test"); // merge testcases specified on command line for (; testcase_index < args->count(); testcase_index++) tests << args->arg(testcase_index); if (tests.count() > 0) for (QValueListConstIterator<QCString> it = tests.begin(); it != tests.end(); ++it) { result = regressionTest->runTests(*it,true); if (!result) break; } else result = regressionTest->runTests(); if (result) { if (args->isSet("genoutput")) { printf("\nOutput generation completed.\n"); } else { printf("\nTests completed.\n"); printf("Total: %d\n", regressionTest->m_passes_work+ regressionTest->m_passes_fail+ regressionTest->m_failures_work+ regressionTest->m_failures_fail+ regressionTest->m_errors); printf("Passes: %d",regressionTest->m_passes_work); if ( regressionTest->m_passes_fail ) printf( " (%d unexpected passes)\n", regressionTest->m_passes_fail ); else printf( "\n" ); printf("Failures: %d",regressionTest->m_failures_work); if ( regressionTest->m_failures_fail ) printf( " (%d expected failures)\n", regressionTest->m_failures_fail ); else printf( "\n" ); if ( regressionTest->m_errors ) printf("Errors: %d\n",regressionTest->m_errors); QFile list( regressionTest->m_outputDir + "/links.html" ); list.open( IO_WriteOnly|IO_Append ); QString link, cl; link = QString( "<hr>%1 failures. (%2 expected failures)" ) .arg(regressionTest->m_failures_work ) .arg( regressionTest->m_failures_fail ); list.writeBlock( link.latin1(), link.length() ); list.close(); } } // Only return a 0 exit code if all tests were successful if (regressionTest->m_failures_work == 0 && regressionTest->m_errors == 0) rv = 0; // cleanup delete regressionTest; delete part; delete toplevel; delete fac; khtml::Cache::clear(); khtml::CSSStyleSelector::clear(); khtml::RenderStyle::cleanup(); kill( xvfb, SIGINT ); return rv;}// -------------------------------------------------------------------------RegressionTest *RegressionTest::curr = 0;RegressionTest::RegressionTest(KHTMLPart *part, const QString &baseDir, const QString &outputDir, bool _genOutput, bool runJS, bool runHTML) : QObject(part){ m_part = part; m_baseDir = baseDir; m_baseDir = m_baseDir.replace( "//", "/" ); if ( m_baseDir.endsWith( "/" ) ) m_baseDir = m_baseDir.left( m_baseDir.length() - 1 ); if (outputDir.isEmpty()) m_outputDir = m_baseDir + "/output"; else { createMissingDirs(outputDir + "/"); m_outputDir = outputDir; } m_genOutput = _genOutput; m_runJS = runJS; m_runHTML = runHTML; m_passes_work = m_passes_fail = 0; m_failures_work = m_failures_fail = 0; m_errors = 0; ::unlink( QFile::encodeName( m_outputDir + "/links.html" ) ); QFile f( m_outputDir + "/empty.html" ); QString s; f.open( IO_WriteOnly | IO_Truncate ); s = "<html><body>Follow the white rabbit"; f.writeBlock( s.latin1(), s.length() ); f.close(); f.setName( m_outputDir + "/index.html" ); f.open( IO_WriteOnly | IO_Truncate ); s = "<html><frameset cols=150,*><frame src=links.html><frame name=content src=empty.html>"; f.writeBlock( s.latin1(), s.length() ); f.close(); m_paintBuffer = 0; curr = this;}#include <qobjectlist.h>static QStringList readListFile( const QString &filename ){ // Read ignore file for this directory QString ignoreFilename = filename; QFileInfo ignoreInfo(ignoreFilename); QStringList ignoreFiles; if (ignoreInfo.exists()) { QFile ignoreFile(ignoreFilename); if (!ignoreFile.open(IO_ReadOnly)) { fprintf(stderr,"Can't open %s\n",ignoreFilename.latin1()); exit(1); } QTextStream ignoreStream(&ignoreFile); QString line; while (!(line = ignoreStream.readLine()).isNull()) ignoreFiles.append(line); ignoreFile.close(); } return ignoreFiles;}RegressionTest::~RegressionTest(){ delete m_paintBuffer;}bool RegressionTest::runTests(QString relPath, bool mustExist, int known_failure){ m_currentOutput = QString::null; if (!QFile(m_baseDir + "/tests/"+relPath).exists()) { fprintf(stderr,"%s: No such file or directory\n",relPath.latin1()); return false; } QString fullPath = m_baseDir + "/tests/"+relPath; QFileInfo info(fullPath); if (!info.exists() && mustExist) { fprintf(stderr,"%s: No such file or directory\n",relPath.latin1()); return false; } if (!info.isReadable() && mustExist) { fprintf(stderr,"%s: Access denied\n",relPath.latin1()); return false; } if (info.isDir()) { QStringList ignoreFiles = readListFile( m_baseDir + "/tests/"+relPath+"/ignore" ); QStringList failureFiles = readListFile( m_baseDir + "/tests/"+relPath+"/KNOWN_FAILURES" ); // Run each test in this directory, recusively QDir sourceDir(m_baseDir + "/tests/"+relPath); for (uint fileno = 0; fileno < sourceDir.count(); fileno++) { QString filename = sourceDir[fileno]; QString relFilename = relPath.isEmpty() ? filename : relPath+"/"+filename; if (filename == "." || filename == ".." || ignoreFiles.contains(filename) ) continue; int failure_type = NoFailure; if ( failureFiles.contains( filename ) ) failure_type |= AllFailure; if ( failureFiles.contains ( filename + "-render" ) ) failure_type |= RenderFailure; if ( failureFiles.contains ( filename + "-dump.png" ) ) failure_type |= PaintFailure; if ( failureFiles.contains ( filename + "-dom" ) ) failure_type |= DomFailure; runTests(relFilename, false, failure_type ); } } else if (info.isFile()) { alarm( 400 ); khtml::Cache::init(); QString relativeDir = QFileInfo(relPath).dirPath(); QString filename = info.fileName(); m_currentBase = m_baseDir + "/tests/"+relativeDir; m_currentCategory = relativeDir; m_currentTest = filename; m_known_failures = known_failure; if ( filename.endsWith(".html") || filename.endsWith( ".htm" ) || filename.endsWith( ".xhtml" ) || filename.endsWith( ".xml" ) ) { if ( relPath.startsWith( "domts/" ) && !m_runJS ) return true; if ( relPath.startsWith( "ecma/" ) && !m_runJS ) return true; if ( m_runHTML ) testStaticFile(relPath); } else if (filename.endsWith(".js")) { if ( m_runJS ) testJSFile(relPath); } else if (mustExist) { fprintf(stderr,"%s: Not a valid test file (must be .htm(l) or .js)\n",relPath.latin1()); return false; } } else if (mustExist) { fprintf(stderr,"%s: Not a regular file\n",relPath.latin1()); return false; } return true;}void RegressionTest::getPartDOMOutput( QTextStream &outputStream, KHTMLPart* part, uint indent ){ Node node = part->document(); while (!node.isNull()) { // process for (uint i = 0; i < indent; i++) outputStream << " "; outputStream << node.nodeName().string(); switch (node.nodeType()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -