git-svn-id: https://svn.microneil.com/svn/CodeDweller-Tests/trunk@24 b3372362-9eaa-4a85-aa2b-6faa1ab7c995master
@@ -1,59 +1,141 @@ | |||
progName=serviceProgram | |||
debugFileName=$progName"Debug.log" | |||
if [ "$(uname --operating-system)" == "Msys" ] | |||
then | |||
CFLAGS='-I.. -Wall -std=c++11 -DWIN32 -pthread -DDEBUG_LOG_FILE="/c/serviceDebug.log"' | |||
CFLAGS='-I.. -Wall -std=c++11 -DWIN32 -pthread -DDEBUG_LOG_FILE="' | |||
CFLAGS=$CFLAGS$(pwd)/$debugFileName\" | |||
else | |||
CFLAGS='-I.. -Wall -std=c++0x -g -O0 -pthread' | |||
CFLAGS='-I.. -Wall -std=c++11 -g -O0 -pthread -DDEBUG_LOG_FILE="' | |||
CFLAGS=$CFLAGS$(pwd)/$debugFileName\" | |||
CFLAGS='-I.. -Wall -std=c++11 -g -O0 -pthread' | |||
fi | |||
progName=serviceProgram | |||
g++ $CFLAGS $progName.cpp ../CodeDweller/service.cpp -o $progName | |||
if [ $? -ne 0 ] | |||
then | |||
exit -1 | |||
fi | |||
# Run test. | |||
logFileName=$progName.log | |||
rm -f $debugFileName | |||
rm -f $logFileName | |||
# Function to run a test. | |||
# | |||
# Usage: | |||
# | |||
# run_test <message> | |||
# | |||
run_test() { | |||
if [ "$(uname --operating-system)" == "Msys" ] | |||
then | |||
sc create "Test Service" binPath= "$(pwd)/$progName.exe" | |||
message=$1 | |||
sc start "Test Service" "$(pwd)/$logFileName" | |||
sleep 1 | |||
logFile=$progName$message.log | |||
sc pause "Test Service" "$(pwd)/$logFileName" | |||
sleep 2 | |||
rm -f $logFile | |||
sc continue "Test Service" "$(pwd)/$logFileName" | |||
sleep 2 | |||
if [ "$(uname --operating-system)" == "Msys" ] | |||
then | |||
sc stop "Test Service" | |||
sleep 1 | |||
sc create "Test Service" binPath= "$(pwd)/$progName.exe" | |||
sc delete "Test Service" | |||
else | |||
./$progName $(pwd)/$logFileName | |||
sc start "Test Service" "$(pwd)/$logFile" | |||
sleep 1 | |||
PID=$(ps axl | grep -i $progName |grep -v grep | cut -d ' ' -f 4) | |||
sleep 1 | |||
sc pause "Test Service" "$(pwd)/$logFile" | |||
sleep 2 | |||
kill -TSTP $PID | |||
sleep 2 | |||
sc continue "Test Service" "$(pwd)/$logFile" | |||
sleep 2 | |||
kill -CONT $PID | |||
sleep 2 | |||
sc stop "Test Service" | |||
sleep 1 | |||
kill -TERM $PID | |||
sleep 1 | |||
fi | |||
sc delete "Test Service" | |||
else | |||
name=$(pwd)/$progName | |||
killall --exact --signal KILL --quiet $name | |||
sleep 1 | |||
$name $(pwd)/$logFile $message | |||
PID=$(pidof $name) | |||
sleep 1 | |||
kill -TSTP $PID | |||
if [ $message != "Pause" ] | |||
then | |||
# In the Pause test, the service should have exited. | |||
sleep 2 | |||
kill -CONT $PID | |||
if diff --strip-trailing-cr expected_$logFileName $logFileName > /dev/null 2>&1 | |||
if [ $message != "Resume" ] | |||
then | |||
# In the Resume test, the service should have exited. | |||
sleep 2 | |||
kill -TERM $PID | |||
fi | |||
fi | |||
# Wait for process to exit. | |||
exited=no | |||
for i in $(seq 10) | |||
do | |||
if pidof $name > /dev/null 2>&1 | |||
then | |||
sleep 1 | |||
else | |||
exited=yes | |||
break | |||
fi | |||
done | |||
if [ $exited == "no" ] | |||
then | |||
echo CodeDweller::Service $message: fail--$progName did not exit | |||
return 1 | |||
fi | |||
fi | |||
if diff --strip-trailing-cr expected_$logFile $logFile > /dev/null 2>&1 | |||
then | |||
echo CodeDweller::Service $message: ok | |||
else | |||
echo CodeDweller::Service $message: fail | |||
return 1 | |||
fi | |||
return 0 | |||
} | |||
stat=0 | |||
# Normal test. | |||
run_test Nominal | |||
nominal_status=$? | |||
# Pause timeout. | |||
run_test Pause | |||
pause_status=$? | |||
# Resume timeout. | |||
run_test Resume | |||
resume_status=$? | |||
# Stop timeout. | |||
run_test Stop | |||
stop_status=$? | |||
if [ $nominal_status == "0" -a \ | |||
$pause_status == "0" -a \ | |||
$resume_status == "0" -a \ | |||
$stop_status == "0" ] | |||
then | |||
echo CodeDweller::Service: ok | |||
else | |||
echo CodeDweller::Service: fail | |||
exit 0 | |||
fi | |||
exit 1 | |||
@@ -0,0 +1 @@ | |||
Sleeping 2 s... |
@@ -0,0 +1,17 @@ | |||
Sleeping 2 s...done. | |||
receivedPause(): 1 | |||
receivedResume(): 0 | |||
receivedStop(): 0 | |||
Clearing all flags. | |||
receivedPause(): 0 | |||
receivedResume(): 0 | |||
receivedStop(): 0 | |||
pauseCbck.pauseFlag: 1 | |||
pauseCbck1.pauseFlag: 1 | |||
resumeCbck.resumeFlag: 0 | |||
resumeCbck1.resumeFlag: 0 | |||
stopCbck.stopFlag: 0 | |||
stopCbck1.stopFlag: 0 | |||
notStopCbck.stopFlag: 0 | |||
Sleeping 2 s... |
@@ -0,0 +1,33 @@ | |||
Sleeping 2 s...done. | |||
receivedPause(): 1 | |||
receivedResume(): 0 | |||
receivedStop(): 0 | |||
Clearing all flags. | |||
receivedPause(): 0 | |||
receivedResume(): 0 | |||
receivedStop(): 0 | |||
pauseCbck.pauseFlag: 1 | |||
pauseCbck1.pauseFlag: 1 | |||
resumeCbck.resumeFlag: 0 | |||
resumeCbck1.resumeFlag: 0 | |||
stopCbck.stopFlag: 0 | |||
stopCbck1.stopFlag: 0 | |||
notStopCbck.stopFlag: 0 | |||
Sleeping 2 s...done. | |||
receivedPause(): 0 | |||
receivedResume(): 1 | |||
receivedStop(): 0 | |||
Clearing all flags. | |||
receivedPause(): 0 | |||
receivedResume(): 0 | |||
receivedStop(): 0 | |||
pauseCbck.pauseFlag: 0 | |||
pauseCbck1.pauseFlag: 0 | |||
resumeCbck.resumeFlag: 1 | |||
resumeCbck1.resumeFlag: 1 | |||
stopCbck.stopFlag: 0 | |||
stopCbck1.stopFlag: 0 | |||
notStopCbck.stopFlag: 0 | |||
Sleeping 2 s... |
@@ -4,18 +4,27 @@ | |||
// | |||
// Usage: | |||
// | |||
// serviceProgram <logFileName> | |||
// serviceProgram <logFileName> <message> | |||
// | |||
// where <logFileName> is the name of a file to write to. | |||
// where <logFileName> is the name of a file to write to, and | |||
// <message> is the message callback timeout to test. <message> can | |||
// be Pause, Resume, or Stop. If <message> is anything else, then | |||
// <message> is ignored. | |||
// | |||
// This program: | |||
// | |||
// 1) Registers callbacks for various messages. | |||
// 1) Sets the callback timeout to 500 ms. | |||
// | |||
// 2) While the stop flag is false, outputs the status of all flags | |||
// 2) Registers callbacks for various messages. Each callback | |||
// normaly sleeps for 400 ms, which is less than the timeout. | |||
// However, if <message> is present, the callback for the specified | |||
// message sleeps for 600 ms. This should cause the service to | |||
// exit. | |||
// | |||
// 3) While the stop flag is false, outputs the status of all flags | |||
// to the log file every 2 seconds, and clears all flags. | |||
// | |||
// 3) After Stop is received, output the status of all flags, and | |||
// 4) After Stop is received, output the status of all flags, and | |||
// exit. | |||
// | |||
// Copyright (C) 2014 MicroNeil Research Corporation. | |||
@@ -38,6 +47,23 @@ | |||
// Place, Suite 330, Boston, MA 02111-1307 USA | |||
//============================================================================== | |||
///////////////////////////////////////////////////////////////////////////// | |||
// Configuration //////////////////////////////////////////////////////////// | |||
///////////////////////////////////////////////////////////////////////////// | |||
// Callback timeout time. | |||
const int timeoutTime_ms = 500; | |||
// How long the callback takes to not exceed the timeout. | |||
const int shortSleepTime_ms = 400; | |||
// How long the callback takes to exceed the timeout. | |||
const int longSleepTime_ms = 600; | |||
///////////////////////////////////////////////////////////////////////////// | |||
// End of configuration ///////////////////////////////////////////////////// | |||
///////////////////////////////////////////////////////////////////////////// | |||
#include <cstdlib> | |||
#include <fstream> | |||
#include <thread> | |||
@@ -51,9 +77,19 @@ public: | |||
PauseCallback() : pauseFlag(false) {} | |||
// Total sleep time for all Pause callbacks should be less than 1000 | |||
// ms. Reason: The while loop below sleeps for two seconds, and the | |||
// buildAndRun script sends the message one second into the sleep. | |||
// The callbacks must be completed before the main loop checks the | |||
// pauseFlag value. | |||
// | |||
// This applies to ResumeCallback and StopCallback. | |||
int sleepTime_ms = shortSleepTime_ms; | |||
bool pauseFlag; | |||
void operator()() { | |||
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime_ms)); | |||
pauseFlag = true; | |||
} | |||
@@ -69,9 +105,12 @@ public: | |||
ResumeCallback() : resumeFlag(false) {} | |||
int sleepTime_ms = shortSleepTime_ms; | |||
bool resumeFlag; | |||
void operator()() { | |||
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime_ms)); | |||
resumeFlag = true; | |||
} | |||
@@ -87,9 +126,12 @@ public: | |||
StopCallback() : stopFlag(false) {} | |||
int sleepTime_ms = shortSleepTime_ms; | |||
bool stopFlag; | |||
void operator()() { | |||
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime_ms)); | |||
stopFlag = true; | |||
} | |||
@@ -101,15 +143,32 @@ StopCallback notStopCbck; | |||
int CodeDweller::Service::run() { | |||
// Set the callback timeout to the default. | |||
CodeDweller::Service::setCallbackTimeout_ms(timeoutTime_ms); | |||
// Get the log file name. | |||
auto arguments = CodeDweller::Service::arguments(); | |||
if (arguments.size() != 2) { | |||
if (arguments.size() == 3) { | |||
// Increase the time it takes for a callback to execute. | |||
if (arguments[2] == "Pause") { | |||
pauseCbck.sleepTime_ms = longSleepTime_ms; | |||
pauseCbck1.sleepTime_ms = longSleepTime_ms; | |||
} else if (arguments[2] == "Resume") { | |||
resumeCbck.sleepTime_ms = longSleepTime_ms; | |||
resumeCbck1.sleepTime_ms = longSleepTime_ms; | |||
} else if (arguments[2] == "Stop") { | |||
stopCbck.sleepTime_ms = longSleepTime_ms; | |||
stopCbck1.sleepTime_ms = longSleepTime_ms; | |||
} | |||
} | |||
if ( (arguments.size() != 2) && (arguments.size() != 3) ) { | |||
return(EXIT_FAILURE); | |||
} | |||
// Get log file. | |||
std::ofstream logStream(arguments[1]); | |||
std::ofstream logStream(arguments[1], std::fstream::app); | |||
// Register the callbacks. | |||
CodeDweller::Service::onPauseCall(pauseCbck); |