📄 test_regression.cpp
字号:
cl += "<span id='b5' class='button' onclick='showDom();m(5);'>D-DIFF</span> \n"; // The test file always exists - except for checkOutput called from *.js files if ( QFile::exists( m_baseDir + "/tests/"+ test ) ) cl += QString( "<a class=button href=\"%1\">HTML</a> " ) .arg( relpath+"/tests/"+test ); cl += QString( "<hr>" "<img style='border: solid 5px gray' src=\"%1\" id='image'>" ) .arg( relpath+"/baseline/"+test+"-dump.png" ); cl += "<div id='render' class='diff'>" + renderDiff + "</div>"; cl += "<div id='dom' class='diff'>" + domDiff + "</div>"; cl += "</body></html>"; compare.writeBlock( cl.latin1(), cl.length() ); compare.close();}void RegressionTest::testStaticFile(const QString & filename){ qApp->mainWidget()->resize( 800, 600); // restore size // Set arguments KParts::URLArgs args; if (filename.endsWith(".html") || filename.endsWith(".htm")) args.serviceType = "text/html"; else if (filename.endsWith(".xhtml")) args.serviceType = "application/xhtml+xml"; else if (filename.endsWith(".xml")) args.serviceType = "text/xml"; m_part->browserExtension()->setURLArgs(args); // load page KURL url; url.setProtocol("file"); url.setPath(QFileInfo(m_baseDir + "/tests/"+filename).absFilePath()); PartMonitor pm(m_part); m_part->openURL(url); pm.waitForCompletion(); m_part->closeURL(); if ( filename.startsWith( "domts/" ) ) { QString functionname; KJS::Completion comp = m_part->jScriptInterpreter()->evaluate("exposeTestFunctionNames();"); /* * Error handling */ KJS::ExecState *exec = m_part->jScriptInterpreter()->globalExec(); if ( comp.complType() == ReturnValue || comp.complType() == Normal ) { if (comp.value().isValid() && comp.value().isA(ObjectType) && (Object::dynamicCast(comp.value()).className() == "Array" ) ) { Object argArrayObj = Object::dynamicCast(comp.value()); unsigned int length = argArrayObj. get(exec,lengthPropertyName). toUInt32(exec); if ( length == 1 ) functionname = argArrayObj.get(exec, 0).toString(exec).qstring(); } } if ( functionname.isNull() ) { kdDebug() << "DOM " << filename << " doesn't expose 1 function name - ignoring" << endl; return; } KJS::Completion comp2 = m_part->jScriptInterpreter()->evaluate("setUpPage(); " + functionname + "();" ); bool success = ( comp2.complType() == ReturnValue || comp2.complType() == Normal ); QString description = "DOMTS"; if ( comp2.complType() == Throw ) { KJS::Value val = comp2.value(); KJS::Object obj = Object::dynamicCast(val); if ( obj.isValid() && obj.hasProperty( exec, "jsUnitMessage" ) ) description = obj.get( exec, "jsUnitMessage" ).toString( exec ).qstring(); else description = comp2.value().toString( exec ).qstring(); } reportResult( success, description ); if (!success && !m_known_failures) doFailureReport( filename, JSFailure ); return; } int back_known_failures = m_known_failures; if ( m_genOutput ) { if ( m_known_failures & DomFailure) m_known_failures = AllFailure; reportResult( checkOutput(filename+"-dom"), "DOM" ); if ( m_known_failures & RenderFailure ) m_known_failures = AllFailure; reportResult( checkOutput(filename+"-render"), "RENDER" ); if ( m_known_failures & PaintFailure ) m_known_failures = AllFailure; renderToImage().save(m_baseDir + "/baseline/" + filename + "-dump.png","PNG", 60); printf("Generated %s\n", QString( m_baseDir + "/baseline/" + filename + "-dump.png" ).latin1() ); reportResult( true, "PAINT" ); } else { int failures = NoFailure; // compare with output file if ( m_known_failures & DomFailure) m_known_failures = AllFailure; if ( !reportResult( checkOutput(filename+"-dom"), "DOM" ) ) failures |= DomFailure; if ( m_known_failures & RenderFailure ) m_known_failures = AllFailure; if ( !reportResult( checkOutput(filename+"-render"), "RENDER" ) ) failures |= RenderFailure; if ( m_known_failures & PaintFailure ) m_known_failures = AllFailure; CheckResult dumped = checkPaintdump(filename); reportResult( dumped, "PAINT"); if (dumped == Failure) failures |= PaintFailure; doFailureReport(filename, failures ); } m_known_failures = back_known_failures;}void RegressionTest::evalJS( ScriptInterpreter &interp, const QString &filename, bool report_result ){ QString fullSourceName = filename; QFile sourceFile(fullSourceName); if (!sourceFile.open(IO_ReadOnly)) { fprintf(stderr,"Error reading file %s\n",fullSourceName.latin1()); exit(1); } QTextStream stream ( &sourceFile ); stream.setEncoding( QTextStream::UnicodeUTF8 ); QString code = stream.read(); sourceFile.close(); saw_failure = false; ignore_errors = false; Completion c = interp.evaluate(UString( code ) ); if ( report_result && !ignore_errors) { bool expected_failure = filename.endsWith( "-n.js" ); if (c.complType() == Throw) { QString errmsg = c.value().toString(interp.globalExec()).qstring(); if ( !expected_failure ) { printf( "ERROR: %s (%s)\n",filename.latin1(), errmsg.latin1()); m_errors++; } else { reportResult( true, QString( "Expected Failure: %1" ).arg( errmsg ) ); } } else if ( saw_failure ) { if ( !expected_failure ) doFailureReport( m_currentCategory + "/" + m_currentTest, JSFailure ); reportResult( expected_failure, "saw 'failed!'" ); } else { reportResult( !expected_failure, "passed" ); } }}class GlobalImp : public ObjectImp {public: virtual UString className() const { return "global"; }};void RegressionTest::testJSFile(const QString & filename ){ qApp->mainWidget()->resize( 800, 600); // restore size // create interpreter // note: this is different from the interpreter used by the part, // it contains regression test-specific objects & functions Object global(new GlobalImp()); khtml::ChildFrame frame; frame.m_part = m_part; ScriptInterpreter interp(global,&frame); ExecState *exec = interp.globalExec(); global.put(exec, "part", Object(new KHTMLPartObject(exec,m_part))); global.put(exec, "regtest", Object(new RegTestObject(exec,this))); global.put(exec, "debug", Object(new RegTestFunction(exec,this,RegTestFunction::Print,1) ) ); global.put(exec, "print", Object(new RegTestFunction(exec,this,RegTestFunction::Print,1) ) ); QStringList dirs = QStringList::split( '/', filename ); // NOTE: the basename is of little interest here, but the last basedir change // isn't taken in account QString basedir = m_baseDir + "/tests/"; for ( QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it ) { if ( ! ::access( QFile::encodeName( basedir + "shell.js" ), R_OK ) ) evalJS( interp, basedir + "shell.js", false ); basedir += *it + "/"; } evalJS( interp, m_baseDir + "/tests/"+ filename, true );}RegressionTest::CheckResult RegressionTest::checkPaintdump(const QString &filename){ QString againstFilename( filename + "-dump.png" ); QString absFilename = QFileInfo(m_baseDir + "/baseline/" + againstFilename).absFilePath(); if ( svnIgnored( absFilename ) ) { m_known_failures = NoFailure; return Ignored; } CheckResult result = Failure; QImage baseline; baseline.load( absFilename, "PNG"); QImage output = renderToImage(); if ( !imageEqual( baseline, output ) ) { QString outputFilename = m_outputDir + "/" + againstFilename; createMissingDirs(outputFilename ); output.save(outputFilename, "PNG", 60); } else { ::unlink( QFile::encodeName( m_outputDir + "/" + againstFilename ) ); result = Success; } return result;}RegressionTest::CheckResult RegressionTest::checkOutput(const QString &againstFilename){ QString absFilename = QFileInfo(m_baseDir + "/baseline/" + againstFilename).absFilePath(); if ( svnIgnored( absFilename ) ) { m_known_failures = NoFailure; return Ignored; } bool domOut = againstFilename.endsWith( "-dom" ); QString data = getPartOutput( domOut ? DOMTree : RenderTree ); data.remove( char( 13 ) ); CheckResult result = Success; // compare result to existing file QString outputFilename = QFileInfo(m_outputDir + "/" + againstFilename).absFilePath(); bool kf = false; if ( m_known_failures & AllFailure ) kf = true; else if ( domOut && ( m_known_failures & DomFailure ) ) kf = true; else if ( !domOut && ( m_known_failures & RenderFailure ) ) kf = true; if ( kf ) outputFilename += "-KF"; if ( m_genOutput ) outputFilename = absFilename; QFile file(absFilename); if (file.open(IO_ReadOnly)) { QTextStream stream ( &file ); stream.setEncoding( QTextStream::UnicodeUTF8 ); QString fileData = stream.read(); result = ( fileData == data ) ? Success : Failure; if ( !m_genOutput && result == Success ) { ::unlink( QFile::encodeName( outputFilename ) ); return Success; } } // generate result file createMissingDirs( outputFilename ); QFile file2(outputFilename); if (!file2.open(IO_WriteOnly)) { fprintf(stderr,"Error writing to file %s\n",outputFilename.latin1()); exit(1); } QTextStream stream2(&file2); stream2.setEncoding( QTextStream::UnicodeUTF8 ); stream2 << data; if ( m_genOutput ) printf("Generated %s\n", outputFilename.latin1()); return result;}bool RegressionTest::reportResult(CheckResult result, const QString & description){ if ( result == Ignored ) { //printf("IGNORED: "); //printDescription( description ); return true; // no error } else return reportResult( result == Success, description );}bool RegressionTest::reportResult(bool passed, const QString & description){ if (m_genOutput) return true; if (passed) { if ( m_known_failures & AllFailure ) { printf("PASS (unexpected!): "); m_passes_fail++; } else { printf("PASS: "); m_passes_work++; } } else { if ( m_known_failures & AllFailure ) { printf("FAIL (known): "); m_failures_fail++; passed = true; // we knew about it } else { printf("FAIL: "); m_failures_work++; } } printDescription( description ); return passed;}void RegressionTest::printDescription(const QString& description){ if (!m_currentCategory.isEmpty()) printf("%s/", m_currentCategory.latin1()); printf("%s", m_currentTest.latin1()); if (!description.isEmpty()) { QString desc = description; desc.replace( '\n', ' ' ); printf(" [%s]", desc.latin1()); } printf("\n"); fflush(stdout);}void RegressionTest::createMissingDirs(const QString & filename){ QFileInfo dif(filename); QFileInfo dirInfo( dif.dirPath() ); if (dirInfo.exists()) return; QStringList pathComponents; QFileInfo parentDir = dirInfo; pathComponents.prepend(parentDir.absFilePath()); while (!parentDir.exists()) { QString parentPath = parentDir.absFilePath(); int slashPos = parentPath.findRev('/'); if (slashPos < 0) break; parentPath = parentPath.left(slashPos); pathComponents.prepend(parentPath); parentDir = QFileInfo(parentPath); } for (uint pathno = 1; pathno < pathComponents.count(); pathno++) { if (!QFileInfo(pathComponents[pathno]).exists() && !QDir(pathComponents[pathno-1]).mkdir(pathComponents[pathno])) { fprintf(stderr,"Error creating directory %s\n",pathComponents[pathno].latin1()); exit(1); } }}void RegressionTest::slotOpenURL(const KURL &url, const KParts::URLArgs &args){ m_part->browserExtension()->setURLArgs( args ); PartMonitor pm(m_part); m_part->openURL(url); pm.waitForCompletion();}bool RegressionTest::svnIgnored( const QString &filename ){ QFileInfo fi( filename ); QString ignoreFilename = fi.dirPath() + "/svnignore"; QFile ignoreFile(ignoreFilename); if (!ignoreFile.open(IO_ReadOnly)) return false; QTextStream ignoreStream(&ignoreFile); QString line; while (!(line = ignoreStream.readLine()).isNull()) { if ( line == fi.fileName() ) return true; } ignoreFile.close(); return false;}void RegressionTest::resizeTopLevelWidget( int w, int h ){ qApp->mainWidget()->resize( w, h ); // Since we're not visible, this doesn't have an immediate effect, QWidget posts the event QApplication::sendPostedEvents( 0, QEvent::Resize );}#include "test_regression.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -