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); | |||