From f52c85dcd7c1a5c1c0578cb57ecf0d53b4a477ab Mon Sep 17 00:00:00 2001
From: Ruud Overeem <overeem@astron.nl>
Date: Thu, 23 Aug 2007 23:16:10 +0000
Subject: [PATCH] BugID: 1000 More complete testset.

---
 MAC/GCF/_PAL/SAL/test/Echo.cc               |   2 +-
 MAC/GCF/_PAL/SAL/test/Makefile.am           |   6 +-
 MAC/GCF/_PAL/SAL/test/PerformanceService.cc |  99 +++++
 MAC/GCF/_PAL/SAL/test/PerformanceService.h  |  66 ++++
 MAC/GCF/_PAL/SAL/test/Ping.cc               |  13 +-
 MAC/GCF/_PAL/SAL/test/tGSAPerformance.cc    | 406 ++++++++++++++++++++
 MAC/GCF/_PAL/SAL/test/tGSAPerformance.h     |  74 ++++
 MAC/GCF/_PAL/SAL/test/tGSAService.cc        |  39 +-
 MAC/GCF/_PAL/SAL/test/tGSAService.h         |   1 +
 9 files changed, 695 insertions(+), 11 deletions(-)
 create mode 100644 MAC/GCF/_PAL/SAL/test/PerformanceService.cc
 create mode 100644 MAC/GCF/_PAL/SAL/test/PerformanceService.h
 create mode 100644 MAC/GCF/_PAL/SAL/test/tGSAPerformance.cc
 create mode 100644 MAC/GCF/_PAL/SAL/test/tGSAPerformance.h

diff --git a/MAC/GCF/_PAL/SAL/test/Echo.cc b/MAC/GCF/_PAL/SAL/test/Echo.cc
index 4e5c701ab8f..bf4a940ede2 100644
--- a/MAC/GCF/_PAL/SAL/test/Echo.cc
+++ b/MAC/GCF/_PAL/SAL/test/Echo.cc
@@ -43,7 +43,7 @@ using namespace TM;
 Echo::Echo(string name) : GCFTask((State)&Echo::initial, name) , _pService(0)
 {
   // register the protocol for debugging purposes
-  registerProtocol(ECHO_PROTOCOL, ECHO_PROTOCOL_signalnames);
+  TM::registerProtocol(ECHO_PROTOCOL, ECHO_PROTOCOL_STRINGS);
 
   // initialize the port
   server.init(*this, "server", GCFPortInterface::SPP, ECHO_PROTOCOL);
diff --git a/MAC/GCF/_PAL/SAL/test/Makefile.am b/MAC/GCF/_PAL/SAL/test/Makefile.am
index 2ca6c528cf9..ac4f7e90416 100644
--- a/MAC/GCF/_PAL/SAL/test/Makefile.am
+++ b/MAC/GCF/_PAL/SAL/test/Makefile.am
@@ -1,6 +1,6 @@
 AM_CPPFLAGS = -I$(top_srcdir)/SAL/src
 
-check_PROGRAMS 		= salEcho salPing tGSAService
+check_PROGRAMS 		= salEcho salPing tGSAService tGSAPerformance
 
 TESTS				= tGSAService #salEcho salPing
 
@@ -16,6 +16,10 @@ tGSAService_SOURCES 		= $(BUILT_SOURCES) tGSAService.cc Service.cc
 tGSAService_LDADD			=  ../src/libsal.la $(LOFAR_DEPEND)
 tGSAService_DEPENDENCIES	= ../src/libsal.la $(LOFAR_DEPEND)
 
+tGSAPerformance_SOURCES 	= $(BUILT_SOURCES) tGSAPerformance.cc PerformanceService.cc
+tGSAPerformance_LDADD		=  ../src/libsal.la $(LOFAR_DEPEND)
+tGSAPerformance_DEPENDENCIES= ../src/libsal.la $(LOFAR_DEPEND)
+
 AUTOGEN = autogen
 SUFFIXES = .ph
 %.ph: %.prot
diff --git a/MAC/GCF/_PAL/SAL/test/PerformanceService.cc b/MAC/GCF/_PAL/SAL/test/PerformanceService.cc
new file mode 100644
index 00000000000..a52cdbcd1d4
--- /dev/null
+++ b/MAC/GCF/_PAL/SAL/test/PerformanceService.cc
@@ -0,0 +1,99 @@
+#include <lofar_config.h>
+#include <GCF/GCF_PVTypes.h>
+#include <GCF/PAL/GCF_PVSSInfo.h>
+#include "PerformanceService.h"
+
+int		gDeleteCounter = 0;
+int		gCreateCounter = 0;
+int		gSetCounter = 0;
+int		gGetCounter = 0;
+int		NR_OF_DPS = 10;
+bool	gValidate = false;
+
+namespace LOFAR {
+  namespace GCF {
+    using namespace Common;
+	namespace PAL {
+   
+TSAResult PerformanceService::dpCreate(const string& propName, 
+                            const string& macType)
+{
+	return GSAService::dpCreate(propName, macType);
+}
+
+TSAResult PerformanceService::dpDelete(const string& propName)
+{
+	return GSAService::dpDelete(propName);
+}
+
+TSAResult PerformanceService::dpeSubscribe(const string& propName)
+{
+	return GSAService::dpeSubscribe(propName);
+}
+
+TSAResult PerformanceService::dpeUnsubscribe(const string& propName)
+{
+	return GSAService::dpeUnsubscribe(propName);
+}
+
+TSAResult PerformanceService::dpeGet(const string& propName)
+{
+	return GSAService::dpeGet(propName);
+}
+
+TSAResult PerformanceService::dpeSet(const string& propName, const GCFPValue& value, double timestamp, bool wantAnswer)
+{
+	return GSAService::dpeSet(propName, value, timestamp, wantAnswer);
+}
+
+bool PerformanceService::dpeExists(const string& propName)
+{
+	return GCFPVSSInfo::propExists(propName);
+}
+
+    
+void PerformanceService::dpCreated(const string& /*propName*/)
+{
+	gCreateCounter--;
+}
+
+void PerformanceService::dpDeleted(const string& /*propName*/)
+{
+	gDeleteCounter--;
+}
+
+void PerformanceService::dpeSubscribed(const string& propName)
+{
+	LOG_DEBUG(formatString("SERVICE:Property '%s' subscribed", propName.c_str()));
+}
+
+void PerformanceService::dpeUnsubscribed(const string& propName)
+{
+	LOG_DEBUG(formatString("SERVICE:Property '%s' unsubscribed", propName.c_str()));
+}
+
+void PerformanceService::dpeValueGet(const string& propName, const GCFPValue& value)
+{
+	if (gValidate) {
+	//	GCFPVInteger	theValue = ((GCFPVInteger *)&value)->getValue();
+	//	if (value < 23 || value > (23 + NR_OF_DPS)) {
+	//		LOG_DEBUG_STR (propName << " returned value " << theValue);
+	//	}
+	}
+	gGetCounter--;
+}
+
+void PerformanceService::dpeValueChanged(const string& propName, const GCFPValue& /*value*/)
+{
+	gSetCounter--;
+//	LOG_DEBUG(formatString("SERVICE:Value of property '%s' changed", propName.c_str()));
+}
+
+void PerformanceService::dpeValueSet(const string& /*propName*/)
+{
+	gSetCounter--;
+}
+
+  } // namespace PAL
+ } // namespace GCF
+} // namespace LOFAR
diff --git a/MAC/GCF/_PAL/SAL/test/PerformanceService.h b/MAC/GCF/_PAL/SAL/test/PerformanceService.h
new file mode 100644
index 00000000000..fe37d3342c4
--- /dev/null
+++ b/MAC/GCF/_PAL/SAL/test/PerformanceService.h
@@ -0,0 +1,66 @@
+//
+//  PerformanceService.h: Concrete GSAService class definition.
+//
+//  Copyright (C) 2003
+//  ASTRON (Netherlands Foundation for Research in Astronomy)
+//  P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+//  $Id$
+//
+
+#include <GSA_Service.h>
+
+extern int	gDeleteCounter;
+extern int	gCreateCounter;
+extern int	gSetCounter;
+extern int	gGetCounter;
+extern int	NR_OF_DPS;
+extern bool	gValidate;
+
+namespace LOFAR {
+ namespace GCF {
+  namespace PAL {
+class PerformanceService : public GSAService
+{
+  public:
+    PerformanceService() {};
+    virtual ~PerformanceService() {};
+
+    virtual TSAResult dpCreate(const string& propName, 
+                               const string& macType);
+    virtual TSAResult dpDelete(const string& propName);
+    virtual TSAResult dpeSubscribe(const string& propName);
+    virtual TSAResult dpeUnsubscribe(const string& propName);
+    virtual TSAResult dpeGet(const string& propName);
+    virtual TSAResult dpeSet(const string& propName, const Common::GCFPValue& value, double timestamp, bool wantAnswer = false);
+    virtual bool dpeExists(const string& propName);
+    
+  protected:
+    virtual void dpCreated(const string& propName);
+    virtual void dpDeleted(const string& propName);
+    virtual void dpeSubscribed(const string& propName);
+    virtual void dpeSubscriptionLost(const string& /*propName*/) {;}
+    virtual void dpeUnsubscribed(const string& propName);
+    virtual void dpeValueGet(const string& propName, const Common::GCFPValue& value);
+    virtual void dpeValueChanged(const string& propName, const Common::GCFPValue& value);
+    virtual void dpeValueSet(const string& propName);
+  
+  private:
+};
+  } // namespace PAL
+ } // namespace GCF
+} // namespace LOFAR
diff --git a/MAC/GCF/_PAL/SAL/test/Ping.cc b/MAC/GCF/_PAL/SAL/test/Ping.cc
index 97b94086cbe..09a53348220 100644
--- a/MAC/GCF/_PAL/SAL/test/Ping.cc
+++ b/MAC/GCF/_PAL/SAL/test/Ping.cc
@@ -1,5 +1,5 @@
 //
-//  Ping.cc: Implementation of the Ping task class.
+// Ping.cc: Implementation of the Ping task class.
 //
 //  Copyright (C) 2003
 //  ASTRON (Netherlands Foundation for Research in Astronomy)
@@ -30,12 +30,9 @@
 using std::cout;
 using std::endl;
 
-namespace LOFAR 
-{
- namespace GCF 
- {
-  namespace PAL
-  {
+namespace LOFAR {
+ namespace GCF {
+  namespace PAL {
 /**
  * Function to calculate the elapsed time between two tiemval's.
  */
@@ -49,7 +46,7 @@ Ping::Ping(string name)
   : GCFTask((State)&Ping::initial, name), ping_timer(-1)
 {
   // register the port for debug tracing
-  registerProtocol(ECHO_PROTOCOL, ECHO_PROTOCOL_signalnames);
+  TM::registerProtocol(ECHO_PROTOCOL, ECHO_PROTOCOL_STRINGS);
 
   /**
    * Initialize the "client" port
diff --git a/MAC/GCF/_PAL/SAL/test/tGSAPerformance.cc b/MAC/GCF/_PAL/SAL/test/tGSAPerformance.cc
new file mode 100644
index 00000000000..07c3a65db45
--- /dev/null
+++ b/MAC/GCF/_PAL/SAL/test/tGSAPerformance.cc
@@ -0,0 +1,406 @@
+//
+//  tGSAPerformance.cc: Test program to test the majority of the GSA Service class.
+//
+//  Copyright (C) 2007
+//  ASTRON (Netherlands Foundation for Research in Astronomy)
+//  P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+//  $Id$
+
+#include <lofar_config.h>
+#include <Common/LofarLogger.h>
+#include <Common/Exception.h>
+#include <Common/Timer.h>
+#include <GCF/GCF_PVTypes.h>
+#include <GCF/PAL/GCF_PVSSInfo.h>
+#include "tGSAPerformance.h"
+
+using std::cout;
+using std::endl;
+
+namespace LOFAR {
+  namespace GCF {
+  using namespace Common;
+  using namespace TM;
+  namespace PAL {
+
+
+tGSAPerformance::tGSAPerformance(const string& name) : 
+	GCFTask((State)&tGSAPerformance::initial, name), 
+	_pService(0),
+	itsTimerPort(0)
+{
+	TM::registerProtocol(F_FSM_PROTOCOL, F_FSM_PROTOCOL_STRINGS);
+	itsTimerPort = new GCFTimerPort(*this, "timerPort");
+}
+
+tGSAPerformance::~tGSAPerformance()
+{
+	cout << "Deleting tGSAPerformance" << endl;
+	if (_pService) {
+		delete _pService;
+	}
+	if (itsTimerPort) {
+		delete itsTimerPort;
+	}
+}
+
+//
+// initial (event, port)
+//
+GCFEvent::TResult tGSAPerformance::initial(GCFEvent& e, GCFPortInterface& /*p*/)
+{
+	LOG_DEBUG_STR("initial:" << eventName(e));
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+
+	switch (e.signal) {
+	case F_ENTRY:
+		break;
+
+	case F_INIT:  {
+		LOG_INFO("Creating a Service Class");
+		_pService = new PerformanceService();
+
+		itsTimerPort->setTimer(1.0);
+	}
+	break;
+
+	case F_TIMER:
+		TRAN(tGSAPerformance::test1cleanup);
+	break;
+
+	default:
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	return status;
+}
+
+//
+// final (event, port)
+//
+GCFEvent::TResult tGSAPerformance::final(GCFEvent& e, GCFPortInterface& /*p*/)
+{
+	LOG_DEBUG_STR("final:" << eventName(e));
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+
+	switch (e.signal) {
+	case F_ENTRY:
+		if (_pService) {
+//			_pService->dpDelete("testInt");
+			itsTimerPort->setTimer(1.0);
+		}
+		break;
+	
+	case F_TIMER:
+		stop();
+		break;
+
+	default:
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	return status;
+}
+
+//
+// test1cleanup (event, port)
+//
+GCFEvent::TResult tGSAPerformance::test1cleanup(GCFEvent& e, GCFPortInterface& p)
+{
+	LOG_DEBUG_STR("test1cleanup:" << eventName(e) << "@" << p.getName());
+
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+
+	switch (e.signal) {
+	case F_ENTRY: {
+		// test PVSSInfo class
+		bool	DBok (GCFPVSSInfo::typeExists("ExampleDP_Int"));
+		LOG_INFO_STR("typeExist(ExampleDP_Int): " << DBok ? "Yes" : "no");
+		ASSERTSTR(DBok, "type ExampleDP_Int does not exist in PVSS");
+
+		LOG_INFO_STR("Cleaning up old datapoints if any");
+		gDeleteCounter = 0;
+		string	DPname;
+		for (int i = 0; i < NR_OF_DPS; i++) {
+			DPname = formatString ("Integer%04d", i);
+			if (GCFPVSSInfo::propExists(DPname)) {
+				_pService->dpDelete(DPname);
+				gDeleteCounter++;
+			}
+		}
+		// wait for gDeleteCounter to become 0 (decreased in PSA)
+		itsTimerPort->setTimer(1.0);
+	}
+	break;
+
+	case F_TIMER:
+		if (gDeleteCounter != 0) {
+			itsTimerPort->setTimer(1.0);
+			LOG_INFO_STR ("Waiting for " << gDeleteCounter << " datapoints to disappear");
+		}
+		else {
+			TRAN(tGSAPerformance::test1create);
+		}
+		break;
+
+	default:
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	return status;
+}
+
+//
+// test1create (event, port)
+//
+GCFEvent::TResult tGSAPerformance::test1create(GCFEvent& e, GCFPortInterface& p)
+{
+	LOG_DEBUG_STR("test1create:" << eventName(e) << "@" << p.getName());
+
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+	TSAResult		  result;
+	static NSTimer		timer("Creating");
+
+	switch (e.signal) {
+	case F_ENTRY: {
+		LOG_INFO_STR("Creating " << NR_OF_DPS << " integer variables");
+		string	DPname;
+		timer.start();
+		for (int i = 0; i < NR_OF_DPS; i++) {
+			DPname = formatString ("Integer%04d", i);
+			result = _pService->dpCreate(DPname, "ExampleDP_Int");
+			ASSERTSTR(result == SA_NO_ERROR, "Creation variable " << i << 
+											" returned result: " << GSAerror(result));
+		}
+		timer.stop();
+		LOG_INFO_STR (timer);
+		timer.start();
+		gCreateCounter = NR_OF_DPS;
+		itsTimerPort->setTimer(0.25);
+	}
+	break;
+
+	case F_TIMER:
+		if (gCreateCounter != 0) {
+			itsTimerPort->setTimer(0.25);
+			LOG_INFO_STR ("Waiting for " << gCreateCounter << " datapoints to be created");
+		}
+		else {
+			timer.stop();
+			LOG_INFO_STR (timer);
+			TRAN(tGSAPerformance::test1setvalue);
+		}
+		break;
+
+	default:
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	return status;
+}
+
+//
+// test1setvalue (event, port)
+//
+GCFEvent::TResult tGSAPerformance::test1setvalue(GCFEvent& e, GCFPortInterface& p)
+{
+	LOG_DEBUG_STR("test1setvalue:" << eventName(e) << "@" << p.getName());
+
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+	TSAResult		  result;
+	static NSTimer			  timer("Setting");
+
+	switch (e.signal) {
+	case F_ENTRY: {
+		LOG_INFO_STR("Setting " << NR_OF_DPS << " integer variables");
+		string	DPname;
+		timer.start();
+		for (int i = 0; i < NR_OF_DPS; i++) {
+			DPname = formatString ("Integer%04d", i);
+			GCFPVInteger	newVal(123-i);
+			result = _pService->dpeSet(DPname, newVal, 0.0, true);
+			ASSERTSTR(result == SA_NO_ERROR, "Setting variable " << i << 
+											" returned result: " << GSAerror(result));
+		}
+		timer.stop();
+		LOG_INFO_STR (timer);
+		timer.start();
+		gSetCounter = NR_OF_DPS;
+		itsTimerPort->setTimer(0.01);
+	}
+	break;
+
+	case F_TIMER:
+		if (gSetCounter != 0) {
+			itsTimerPort->setTimer(0.01);
+			LOG_INFO_STR ("Waiting for " << gSetCounter << " datapoints to be written");
+		}
+		else {
+			timer.stop();
+			LOG_INFO_STR(timer);
+			TRAN(tGSAPerformance::test1getvalue);
+		}
+		break;
+
+	default:
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	return status;
+}
+
+//
+// test1getvalue (event, port)
+//
+GCFEvent::TResult tGSAPerformance::test1getvalue(GCFEvent& e, GCFPortInterface& p)
+{
+	LOG_DEBUG_STR("test1getvalue:" << eventName(e) << "@" << p.getName());
+
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+	TSAResult		  result;
+	static NSTimer		timer("Getting");
+
+	switch (e.signal) {
+	case F_ENTRY: {
+		LOG_INFO_STR("Getting " << NR_OF_DPS << " integer variables");
+		string	DPname;
+		timer.start();
+		for (int i = 0; i < NR_OF_DPS; i++) {
+			DPname = formatString ("Integer%04d", i);
+			result = _pService->dpeGet(DPname);
+			ASSERTSTR(result == SA_NO_ERROR, "Getting variable " << i << 
+											" returned result: " << GSAerror(result));
+		}
+		timer.stop();
+		LOG_INFO_STR (timer);
+		timer.start();
+		gGetCounter = NR_OF_DPS;
+		itsTimerPort->setTimer(0.1);
+	}
+	break;
+
+	case F_TIMER:
+		if (gGetCounter != 0) {
+			itsTimerPort->setTimer(0.1);
+			LOG_INFO_STR ("Waiting for " << gGetCounter << " datapoints to be read");
+		}
+		else {
+			timer.stop();
+			LOG_INFO_STR (timer);
+			TRAN(tGSAPerformance::test1delete);
+		}
+		break;
+
+	default:
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	return status;
+}
+
+//
+// test1delete (event, port)
+//
+GCFEvent::TResult tGSAPerformance::test1delete(GCFEvent& e, GCFPortInterface& p)
+{
+	LOG_DEBUG_STR("test1delete:" << eventName(e) << "@" << p.getName());
+
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+	TSAResult		  result;
+	static NSTimer		timer("Deleting");
+
+	switch (e.signal) {
+	case F_ENTRY: {
+		LOG_INFO_STR("Deleting " << NR_OF_DPS << " integer variables");
+		string	DPname;
+		timer.start();
+		for (int i = 0; i < NR_OF_DPS; i++) {
+			DPname = formatString ("Integer%04d", i);
+			result = _pService->dpDelete(DPname);
+			ASSERTSTR(result == SA_NO_ERROR, "Deleting variable " << i << 
+											" returned result: " << GSAerror(result));
+		}
+		timer.stop();
+		LOG_INFO_STR (timer);
+		timer.start();
+		gDeleteCounter = NR_OF_DPS;
+		itsTimerPort->setTimer(1.0);
+	}
+	break;
+
+	case F_TIMER:
+		if (gDeleteCounter != 0) {
+			itsTimerPort->setTimer(0.25);
+			LOG_INFO_STR ("Waiting for " << gDeleteCounter << " datapoints to be deleted");
+		}
+		else {
+			timer.stop();
+			LOG_INFO_STR (timer);
+			TRAN(tGSAPerformance::final);
+		}
+		break;
+
+	default:
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	return status;
+}
+
+
+
+  } // namespace PAL
+ } // namespace GCF
+} // namespace LOFAR
+
+
+using namespace LOFAR::GCF;
+
+int main(int argc, char* argv[])
+{
+	switch (argc) {
+	case 3:		gValidate = true;
+				// no break!
+	case 2:		NR_OF_DPS = atoi(argv[1]);
+				break;
+	default:	cout << "Syntax: " << argv[0] << " number_of_datapoints [-v]" << endl;
+				cout << "    -v   Validate values after get." << endl;
+				exit(1);
+	}
+
+	if (!NR_OF_DPS) {
+		cout << "number_of_datapoints forced to 10" << endl;
+		NR_OF_DPS = 10;
+	}
+
+	TM::GCFTask::init(argc, argv);
+
+	PAL::tGSAPerformance test_task("SALSpeedTest");  
+	test_task.start(); // make initial transition
+
+	TM::GCFTask::run();
+
+	return 0;
+}
diff --git a/MAC/GCF/_PAL/SAL/test/tGSAPerformance.h b/MAC/GCF/_PAL/SAL/test/tGSAPerformance.h
new file mode 100644
index 00000000000..c03a6636974
--- /dev/null
+++ b/MAC/GCF/_PAL/SAL/test/tGSAPerformance.h
@@ -0,0 +1,74 @@
+//
+//  tGSAPerformance.h: Definition of the tGSAService task class.
+//
+//  Copyright (C) 2003
+//  ASTRON (Netherlands Foundation for Research in Astronomy)
+//  P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+//  $Id$
+//
+
+#ifndef _TGSAPERFORMANCE_H_
+#define _TGSAPERFORMANCE_H_
+
+#include <GCF/TM/GCF_Control.h>
+#include "PerformanceService.h"
+
+namespace LOFAR {
+ namespace GCF {
+  namespace PAL {
+/**
+ * The tGSAPerformance task receives ECHO_PING events from the Ping task and
+ * returns an ECHO_ECHO event for each ECHO_PING event received.
+ */
+class tGSAPerformance : public GCFTask
+{
+ public:
+
+  /**
+   * The constructor for the tGSAPerformance task.
+   * @param name The name of this task. By differentiating in the name, multiple
+   * instances of the same task can be created and addressed.
+   */
+  tGSAPerformance (const string& name);
+
+  virtual ~tGSAPerformance();
+
+  GCFEvent::TResult initial  	 (GCFEvent& e, GCFPortInterface& p);
+  GCFEvent::TResult final    	 (GCFEvent& e, GCFPortInterface& p);
+  GCFEvent::TResult test1cleanup (GCFEvent& e, GCFPortInterface& p);
+  GCFEvent::TResult test1create	 (GCFEvent& e, GCFPortInterface& p);
+  GCFEvent::TResult test1setvalue(GCFEvent& e, GCFPortInterface& p);
+  GCFEvent::TResult test1getvalue(GCFEvent& e, GCFPortInterface& p);
+  GCFEvent::TResult test1delete	 (GCFEvent& e, GCFPortInterface& p);
+
+ private:
+
+  /**
+   * The tGSAPerformance task acts as a server for Ping tasks to use. Event from the Ping
+   * task are received on the server port. And reply events to the Ping task
+   * are sent through the server port.
+   */
+	PerformanceService* 	_pService;
+	GCFTimerPort*			itsTimerPort;
+};
+
+  } // namespace PAL
+ } // namespace GCF
+} // namespace LOFAR
+
+#endif
diff --git a/MAC/GCF/_PAL/SAL/test/tGSAService.cc b/MAC/GCF/_PAL/SAL/test/tGSAService.cc
index 4793b367e9d..3af00736a84 100644
--- a/MAC/GCF/_PAL/SAL/test/tGSAService.cc
+++ b/MAC/GCF/_PAL/SAL/test/tGSAService.cc
@@ -352,7 +352,7 @@ GCFEvent::TResult tGSAService::test7(GCFEvent& e, GCFPortInterface& p)
 
 	switch (e.signal) {
 	case F_ENTRY: {
-		LOG_DEBUG("Reding back the integer variable");
+		LOG_DEBUG("Reading back the integer variable");
         result = _pService->dpeGet("testInt");
 		ASSERTSTR(result == SA_NO_ERROR, "Reading the integer testInt returned result: " << GSAerror(result));
 		itsTimerPort->setTimer(1.0);
@@ -434,6 +434,43 @@ GCFEvent::TResult tGSAService::test9(GCFEvent& e, GCFPortInterface& p)
 	}
 	break;
 
+	case F_TIMER:
+		TRAN(tGSAService::test10);
+		break;
+
+	default:
+		status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	return status;
+}
+
+//
+// test10 (event, port)
+//
+GCFEvent::TResult tGSAService::test10(GCFEvent& e, GCFPortInterface& p)
+{
+	LOG_DEBUG_STR("test10:" << eventName(e) << "@" << p.getName());
+
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+	TSAResult		  result;
+
+	switch (e.signal) {
+	case F_ENTRY: {
+		LOG_DEBUG("Reading back a non existant variable");
+		try {
+			result = _pService->dpeGet("UnknownVariable");
+			ASSERTSTR(result == SA_NO_ERROR, "Reading an unknown variable should return an error!");
+		}
+		catch (Exception& except) {
+			LOG_INFO_STR ("Reading an unknown variable returned result: " 
+							<< GSAerror(result));
+		}
+		itsTimerPort->setTimer(1.0);
+	}
+	break;
+
 	case F_TIMER:
 		TRAN(tGSAService::final);
 		break;
diff --git a/MAC/GCF/_PAL/SAL/test/tGSAService.h b/MAC/GCF/_PAL/SAL/test/tGSAService.h
index 7a58f6019fe..620efdb44b3 100644
--- a/MAC/GCF/_PAL/SAL/test/tGSAService.h
+++ b/MAC/GCF/_PAL/SAL/test/tGSAService.h
@@ -59,6 +59,7 @@ class tGSAService : public GCFTask
   GCFEvent::TResult test7	 (GCFEvent& e, GCFPortInterface& p);
   GCFEvent::TResult test8	 (GCFEvent& e, GCFPortInterface& p);
   GCFEvent::TResult test9	 (GCFEvent& e, GCFPortInterface& p);
+  GCFEvent::TResult test10	 (GCFEvent& e, GCFPortInterface& p);
 
  private:
 
-- 
GitLab