Wei Cheng Pan avatar Wei Cheng Pan committed a7b527b

Add check point oracle.

Comments (0)

Files changed (10)

Krapture/server/src/Sikuli/SikuliClient.cpp

 			auto args = data.value( "args" ).toList();
 			emit this->inputRequired( id, object, method, args );
 		} else if( result == "check" ) {
-			// TODO implement check
+			auto id = data.value( "id" ).toInt();
+			auto label = data.value( "label" ).toString();
+			auto value = data.value( "value" ).toString();
+			emit this->checkRequired( id, label, value );
 		} else {
 			assert( !"invalid value" );
 		}
 	this->connect( this->p_.get(), SIGNAL( captured( const QString & ) ), SIGNAL( captured( const QString & ) ) );
 	this->connect( this->p_.get(), SIGNAL( error( const QString & ) ), SIGNAL( error( const QString & ) ) );
 	this->connect( this->p_.get(), SIGNAL( executed( bool, const QString & ) ), SIGNAL( executed( bool, const QString & ) ) );
+	this->connect( this->p_.get(), SIGNAL( checkRequired( int, const QString &, const QString & ) ), SIGNAL( checkRequired( int, const QString &, const QString & ) ) );
 	this->connect( this->p_.get(), SIGNAL( inputRequired( int, const QString &, const QString &, const QVariantList & ) ), SIGNAL( inputRequired( int, const QString &, const QString &, const QVariantList & ) ) );
 	this->connect( this->p_.get(), SIGNAL( log( const QString & ) ), SIGNAL( log( const QString & ) ) );
 	this->connect( this->p_.get(), SIGNAL( ready() ), SIGNAL( ready() ) );

Krapture/server/src/Sikuli/SikuliClient.hpp

 	void captured( const QString & path );
 	void error( const QString & message );
 	void executed( bool success, const QString & response );
+	void checkRequired( int id, const QString & label, const QString & value );
 	void inputRequired( int id, const QString & object, const QString & method, const QVariantList & args );
 	void log( const QString & message );
 	void ready();

Krapture/server/src/Sikuli/SikuliClient_p.hpp

 	void captured( const QString & );
 	void error( const QString & );
 	void executed( bool, const QString & );
+	void checkRequired( int id, const QString & label, const QString & value );
 	void inputRequired( int id, const QString & object, const QString & method, const QVariantList & args );
 	void log( const QString & );
 	void ready();

Krapture/server/src/TestUnit/TestUnit.cpp

 socket( socket ),
 server( server ),
 commands(),
-lastTimestamp( -1LL ) {
+lastTimestamp( -1LL ),
+sutCheckPoints(),
+oracleCheckPoints() {
 	// input handler
 	this->commands.insert( std::make_pair( "<Input>", [this]( const QVariant & data )->void {
 		auto kwargs = data.toMap();
 		auto label = kwargs.value( "label" ).toString();
 		auto value = kwargs.value( "value" ).toString();
 
-		emit this->checkReceived( this->id, label, value );
+		if( this->server->isRecording() ) {
+			emit this->checkReceived( this->id, label, value );
+		} else {
+			// TODO thread lock?
+			this->sutCheckPoints.push_back( value );
+		}
 	} ) );
 
 	this->connect( socket, SIGNAL( readyRead() ), SLOT( onReadyRead() ) );
 
 	auto it = this->commands.find( packet.first );
 	if( it == this->commands.end() ) {
-		// TODO throw error
+		// TODO report error
 		return;
 	}
 	it->second( packet.second );
 TestUnit::TestUnit( int id, SimpleSocket * socket, TestUnitServer * server, QObject * parent ): QObject( parent ), p_( new Private( id, socket, server ) ) {
 }
 
+bool TestUnit::check() const {
+	return this->p_->oracleCheckPoints == this->p_->sutCheckPoints;
+}
+
+void TestUnit::recordOracle( const QString & label, const QString & value ) {
+	this->p_->oracleCheckPoints.push_back( value );
+}
+
 void TestUnit::sendInput( const QString & object, const QString & method, const QVariantList & args ) {
 	QVariantMap kwargs;
 	kwargs.insert( "object", object );

Krapture/server/src/TestUnit/TestUnit.hpp

 public:
 	TestUnit( int id, SimpleSocket * socket, TestUnitServer * server, QObject * parent );
 
+	bool check() const;
+	void recordOracle( const QString & label, const QString & value );
 	void sendInput( const QString & object, const QString & method, const QVariantList & args );
 
 private:

Krapture/server/src/TestUnit/TestUnitServer.cpp

 TestUnitServer::TestUnitServer( QObject * parent ): QObject( parent ), p_( new Private( this ) ) {
 }
 
+bool TestUnitServer::check() const {
+	return std::all_of( this->p_->clients.begin(), this->p_->clients.end(), []( TestUnit * tu )->bool {
+		return tu->check();
+	} );
+}
+
 bool TestUnitServer::isRecording() const {
 	return this->p_->recording;
 }
 	return this->p_->server->listen( name );
 }
 
+void TestUnitServer::recordOracle( int id, const QString & label, const QString & value ) {
+	auto testUnit = this->p_->clients.at( id );
+	testUnit->recordOracle( label, value );
+}
+
 void TestUnitServer::sendInput( int id, const QString & object, const QString & method, const QVariantList & args ) {
 	auto testUnit = this->p_->clients.at( id );
 	testUnit->sendInput( object, method, args );

Krapture/server/src/TestUnit/TestUnitServer.hpp

 public:
 	explicit TestUnitServer( QObject * parent );
 	
+	bool check() const;
 	bool isRecording() const;
 	bool listen( const QString & name );
+	void recordOracle( int id, const QString & label, const QString & value );
 	void sendInput( int id, const QString & object, const QString & method, const QVariantList & args );
 	void startRecording();
 	void stopRecording();

Krapture/server/src/TestUnit/TestUnit_p.hpp

 
 #include <functional>
 #include <map>
+#include <vector>
 
 #include "xTitan/Network/SimpleSocket.hpp"
 #include "TestUnitServer.hpp"
 	TestUnitServer * server;
 	std::map< QString, Command > commands;
 	qint64 lastTimestamp;
+	std::vector< QString > sutCheckPoints;
+	std::vector< QString > oracleCheckPoints;
 };
 
 }

Krapture/server/src/Widget/MainWindow.cpp

 	this->connect( this->client.get(), SIGNAL( executed( bool, const QString & ) ), SLOT( onSikuliClientExecuted( bool, const QString & ) ) );
 	this->connect( this->client.get(), SIGNAL( taskCompleted( const QString &, bool, const QString & ) ), SLOT( onSikuliClientTaskCompleted( const QString &, bool, const QString & ) ) );
 	this->connect( this->client.get(), SIGNAL( bundlesExecuted() ), SLOT( onSikuliClientBundlesExecuted() ) );
+	this->connect( this->client.get(), SIGNAL( checkRequired( int, const QString &, const QString & ) ), SLOT( onSikuliClientCheck( int, const QString &, const QString & ) ) );
 	this->connect( this->client.get(), SIGNAL( inputRequired( int, const QString &, const QString &, const QVariantList & ) ), SLOT( onSikuliClientInput( int, const QString &, const QString &, const QVariantList & ) ) );
 
 	this->connect( this->buttonTimer, SIGNAL( timeout() ), SLOT( onButtonTimeout() ) );
 
 	QString name( ( this->testcase && !this->testcase->getName().isEmpty() ) ? this->testcase->getName() : QObject::tr( "untitled" ) );
 	if( success ) {
-		this->ui.textBrowser->append( QObject::tr( "[%1][SUCCEED]" ).arg( name ) );
+		// tell all test units to check check points
+		if( this->tuServer->check() ) {
+			this->ui.textBrowser->append( QObject::tr( "[%1][SUCCEED]" ).arg( name ) );
+		} else {
+			this->ui.textBrowser->append( QObject::tr( "[%1][FAILED] check points missmatched" ).arg( name ) );
+		}
 	} else {
 		this->ui.textBrowser->append( QObject::tr( "[%1][FAILED] %2" ).arg( name ).arg( response ) );
 	}
 	this->ui.textEdit->insertSpyInput( id, delay, object, method, args );
 }
 
+void MainWindow::Private::onSikuliClientCheck( int id, const QString & label, const QString & value ) {
+	this->tuServer->recordOracle( id, label, value );
+}
+
 void MainWindow::Private::onSikuliClientInput( int id, const QString & object, const QString & method, const QVariantList & args ) {
 	this->tuServer->sendInput( id, object, method, args );
 }

Krapture/server/src/Widget/MainWindow_p.hpp

 	void onSikuliClientExecuted( bool, const QString & );
 	void onSikuliClientTaskCompleted( const QString &, bool, const QString & );
 	void onSikuliClientBundlesExecuted();
+	void onSikuliClientCheck( int id, const QString & label, const QString & value );
 	void onSikuliClientInput( int id, const QString & object, const QString & method, const QVariantList & args );
 	void onSpyInputClicked();
 	void onTUServerCheck( int id, const QString & label, const QString & value );
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.