https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0c683c264c7c908e4bcc97...
commit 0c683c264c7c908e4bcc971d0a904afb2dad6b41 Author: Serge Gautherie reactos-git_serge_171003@gautherie.fr AuthorDate: Tue Jan 16 05:47:34 2018 +0100 Commit: Ged Murphy gedmurphy@reactos.org CommitDate: Thu May 17 16:17:36 2018 +0100
[KMTEST] Check/Wait for start/stop of services to complete
This is cleaner behavior and lets report failures.
- Create KmtEnsureServiceState(), called at end of KmtStartService() and KmtStopService(). - Create KmtGetServiceStateAsString(), called from KmtEnsureServiceState().
ROSTESTS-263 --- modules/rostests/kmtests/kmtest/service.c | 111 +++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-)
diff --git a/modules/rostests/kmtests/kmtest/service.c b/modules/rostests/kmtests/kmtest/service.c index cc2e91a96e..7427fbfdd3 100644 --- a/modules/rostests/kmtests/kmtest/service.c +++ b/modules/rostests/kmtests/kmtest/service.c @@ -4,6 +4,7 @@ * PURPOSE: Kernel-Mode Test Suite loader service control functions * COPYRIGHT: Copyright 2011-2018 Thomas Faber thomas.faber@reactos.org * Copyright 2017 Ged Murphy gedmurphy@reactos.org + * Copyright 2018 Serge Gautherie reactos-git_serge_171003@gautherie.fr */
#include <kmt_test.h> @@ -11,7 +12,7 @@
#include <assert.h>
-#define SERVICE_ACCESS (SERVICE_START | SERVICE_STOP | DELETE) +#define SERVICE_ACCESS (SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | DELETE)
/* * This is an internal function not meant for use by the kmtests app, @@ -101,6 +102,104 @@ KmtCreateService( ServiceHandle); }
+/** + * @name KmtGetServiceStateAsString + * + * @param ServiceState + * Service state as a number + * + * @return Service state as a string + */ +static +PCSTR +KmtGetServiceStateAsString( + IN DWORD ServiceState) +{ + switch(ServiceState) + { + case SERVICE_STOPPED: + return "STOPPED"; + case SERVICE_START_PENDING: + return "START_PENDING"; + case SERVICE_STOP_PENDING: + return "STOP_PENDING"; + case SERVICE_RUNNING: + return "RUNNING"; + case SERVICE_CONTINUE_PENDING: + return "CONTINUE_PENDING"; + case SERVICE_PAUSE_PENDING: + return "PAUSE_PENDING"; + case SERVICE_PAUSED: + return "PAUSED"; + default: + ok(FALSE, "Unknown service state = %lu\n", ServiceState); + return "(Unknown)"; + } +} + +/** + * @name KmtEnsureServiceState + * + * @param ServiceName + * Name of the service to check, + * or NULL + * @param ServiceHandle + * Handle to the service + * @param ExpectedServiceState + * State which the service should be in + * + * @return Win32 error code + */ +static +DWORD +KmtEnsureServiceState( + IN PCWSTR ServiceName OPTIONAL, + IN SC_HANDLE ServiceHandle, + IN DWORD ExpectedServiceState) +{ + DWORD Error = ERROR_SUCCESS; + SERVICE_STATUS ServiceStatus; + DWORD StartTime = GetTickCount(); + DWORD Timeout = 10 * 1000; + PCWSTR ServiceNameOut = ServiceName ? ServiceName : L"(handle only, no name)"; + + assert(ServiceHandle); + assert(ExpectedServiceState); + + if (!QueryServiceStatus(ServiceHandle, &ServiceStatus)) + error_goto(Error, cleanup); + + while (ServiceStatus.dwCurrentState != ExpectedServiceState) + { + // NB: ServiceStatus.dwWaitHint and ServiceStatus.dwCheckPoint logic could be added, if need be. + + Sleep(1 * 1000); + + if (!QueryServiceStatus(ServiceHandle, &ServiceStatus)) + error_goto(Error, cleanup); + + if (GetTickCount() - StartTime >= Timeout) + break; + } + + if (ServiceStatus.dwCurrentState != ExpectedServiceState) + { + ok(FALSE, "Service = %ls, state = %lu %s (!= %lu %s), waitHint = %lu, checkPoint = %lu\n", + ServiceNameOut, + ServiceStatus.dwCurrentState, KmtGetServiceStateAsString(ServiceStatus.dwCurrentState), + ExpectedServiceState, KmtGetServiceStateAsString(ExpectedServiceState), + ServiceStatus.dwWaitHint, ServiceStatus.dwCheckPoint); + goto cleanup; + } + + trace("Service = %ls, state = %lu %s\n", + ServiceNameOut, + ExpectedServiceState, KmtGetServiceStateAsString(ExpectedServiceState)); + +cleanup: + return Error; +} + /** * @name KmtStartService * @@ -133,6 +232,10 @@ KmtStartService( if (!StartService(*ServiceHandle, 0, NULL)) error_goto(Error, cleanup);
+ Error = KmtEnsureServiceState(ServiceName, *ServiceHandle, SERVICE_RUNNING); + if (Error) + goto cleanup; + cleanup: return Error; } @@ -228,6 +331,10 @@ KmtStopService( if (!ControlService(*ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus)) error_goto(Error, cleanup);
+ Error = KmtEnsureServiceState(ServiceName, *ServiceHandle, SERVICE_STOPPED); + if (Error) + goto cleanup; + cleanup: return Error; } @@ -340,4 +447,4 @@ KmtpCreateService(
cleanup: return Error; -} \ No newline at end of file +}