services: Added tests for service thread termination without setting service state to stopped.

oldstable
Piotr Caban 2012-10-22 15:00:47 +02:00 committed by Alexandre Julliard
parent 522bc15b45
commit afc4284d05
1 changed files with 188 additions and 31 deletions

View File

@ -123,12 +123,12 @@ static void WINAPI service_main(DWORD argc, char **argv)
service_ok(res, "SetServiceStatus(SERVICE_STOPPED) failed: %u", GetLastError());
}
static void service_process(void)
static void service_process(void (WINAPI *p_service_main)(DWORD, char **))
{
BOOL res;
static const SERVICE_TABLE_ENTRYA servtbl[] = {
{service_name, service_main},
SERVICE_TABLE_ENTRYA servtbl[] = {
{service_name, p_service_main},
{NULL, NULL}
};
@ -150,7 +150,66 @@ static void service_process(void)
res = StartServiceCtrlDispatcherA(servtbl);
service_ok(res, "StartServiceCtrlDispatcher failed: %u\n", GetLastError());
/* Let service thread terminate */
Sleep(50);
CloseHandle(service_stop_event);
CloseHandle(pipe_handle);
}
static DWORD WINAPI no_stop_handler(DWORD ctrl, DWORD event_type, void *event_data, void *context)
{
SERVICE_STATUS status;
status.dwServiceType = SERVICE_WIN32;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
status.dwWin32ExitCode = 0;
status.dwServiceSpecificExitCode = 0;
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
switch(ctrl)
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
service_event("STOP");
status.dwCurrentState = SERVICE_STOPPED;
status.dwControlsAccepted = 0;
SetServiceStatus(service_handle, &status);
SetEvent(service_stop_event);
return NO_ERROR;
default:
status.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus( service_handle, &status );
return NO_ERROR;
}
}
static void WINAPI no_stop_main(DWORD argc, char **argv)
{
SERVICE_STATUS status;
BOOL res;
service_ok(argc == 1, "argc = %d", argc);
if(argc)
service_ok(!strcmp(argv[0], service_name), "argv[0] = %s, expected %s", argv[0], service_name);
service_handle = pRegisterServiceCtrlHandlerExA(service_name, no_stop_handler, NULL);
service_ok(service_handle != NULL, "RegisterServiceCtrlHandlerEx failed: %u\n", GetLastError());
if(!service_handle)
return;
status.dwServiceType = SERVICE_WIN32;
status.dwCurrentState = SERVICE_RUNNING;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
status.dwWin32ExitCode = 0;
status.dwServiceSpecificExitCode = 0;
status.dwCheckPoint = 0;
status.dwWaitHint = 10000;
res = SetServiceStatus(service_handle, &status);
service_ok(res, "SetServiceStatus(SERVICE_RUNNING) failed: %u", GetLastError());
service_event("RUNNING");
}
/* Test process global variables */
@ -160,7 +219,7 @@ static char current_event[32];
static HANDLE event_handle = INVALID_HANDLE_VALUE;
static CRITICAL_SECTION event_cs;
static SC_HANDLE register_service(void)
static SC_HANDLE register_service(const char *test_name)
{
char service_cmd[MAX_PATH+150], *ptr;
SC_HANDLE service;
@ -175,6 +234,8 @@ static SC_HANDLE register_service(void)
strcpy(ptr, " service ");
ptr += strlen(ptr);
sprintf(ptr, "%s ", test_name);
ptr += strlen(ptr);
strcpy(ptr, service_name);
trace("service_cmd \"%s\"\n", service_cmd);
@ -233,7 +294,7 @@ static DWORD WINAPI pipe_thread(void *arg)
trace("service trace: %s\n", ptr+6);
}else if(!strncmp(ptr, "OK:", 3)) {
ok(1, "service: %s\n", ptr+3);
}else if(!strncmp(ptr, "FAIL:", 3)) {
}else if(!strncmp(ptr, "FAIL:", 5)) {
ok(0, "service: %s\n", ptr+5);
}else if(!strncmp(ptr, "EVENT:", 6)) {
trace("service event: %s\n", ptr+6);
@ -253,13 +314,121 @@ static DWORD WINAPI pipe_thread(void *arg)
return 0;
}
static void test_process(void)
static void test_service(void)
{
SC_HANDLE service_handle;
SC_HANDLE service_handle = register_service("simple_service");
SERVICE_STATUS status;
HANDLE thread;
BOOL res;
if(!service_handle)
return;
trace("starting...\n");
res = StartServiceA(service_handle, 0, NULL);
ok(res, "StartService failed: %u\n", GetLastError());
if(!res) {
DeleteService(service_handle);
return;
}
expect_event("RUNNING");
res = QueryServiceStatus(service_handle, &status);
ok(res, "QueryServiceStatus failed: %d\n", GetLastError());
todo_wine ok(status.dwServiceType == SERVICE_WIN32_OWN_PROCESS, "status.dwServiceType = %x\n", status.dwServiceType);
ok(status.dwCurrentState == SERVICE_RUNNING, "status.dwCurrentState = %x\n", status.dwCurrentState);
ok(status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN),
"status.dwControlsAccepted = %x\n", status.dwControlsAccepted);
ok(status.dwWin32ExitCode == 0, "status.dwExitCode = %d\n", status.dwWin32ExitCode);
ok(status.dwServiceSpecificExitCode == 0, "status.dwServiceSpecificExitCode = %d\n",
status.dwServiceSpecificExitCode);
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
todo_wine ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
res = ControlService(service_handle, SERVICE_CONTROL_STOP, &status);
ok(res, "ControlService failed: %u\n", GetLastError());
expect_event("STOP");
res = DeleteService(service_handle);
ok(res, "DeleteService failed: %u\n", GetLastError());
CloseServiceHandle(service_handle);
}
static inline void test_no_stop(void)
{
SC_HANDLE service_handle = register_service("no_stop");
SERVICE_STATUS status;
BOOL res;
if(!service_handle)
return;
trace("starting...\n");
res = StartServiceA(service_handle, 0, NULL);
ok(res, "StartService failed: %u\n", GetLastError());
if(!res) {
DeleteService(service_handle);
return;
}
expect_event("RUNNING");
/* Let service thread terminate */
Sleep(1000);
res = QueryServiceStatus(service_handle, &status);
ok(res, "QueryServiceStatus failed: %d\n", GetLastError());
todo_wine ok(status.dwServiceType == SERVICE_WIN32_OWN_PROCESS, "status.dwServiceType = %x\n", status.dwServiceType);
ok(status.dwCurrentState == SERVICE_RUNNING, "status.dwCurrentState = %x\n", status.dwCurrentState);
ok(status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN),
"status.dwControlsAccepted = %x\n", status.dwControlsAccepted);
ok(status.dwWin32ExitCode == 0, "status.dwExitCode = %d\n", status.dwWin32ExitCode);
ok(status.dwServiceSpecificExitCode == 0, "status.dwServiceSpecificExitCode = %d\n",
status.dwServiceSpecificExitCode);
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
todo_wine ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
res = ControlService(service_handle, SERVICE_CONTROL_STOP, &status);
ok(res, "ControlService failed: %u\n", GetLastError());
expect_event("STOP");
res = QueryServiceStatus(service_handle, &status);
ok(res, "QueryServiceStatus failed: %d\n", GetLastError());
todo_wine ok(status.dwServiceType == SERVICE_WIN32_OWN_PROCESS, "status.dwServiceType = %x\n", status.dwServiceType);
ok(status.dwCurrentState==SERVICE_STOPPED || status.dwCurrentState==SERVICE_STOP_PENDING,
"status.dwCurrentState = %x\n", status.dwCurrentState);
ok(status.dwControlsAccepted == 0, "status.dwControlsAccepted = %x\n", status.dwControlsAccepted);
ok(status.dwWin32ExitCode == 0, "status.dwExitCode = %d\n", status.dwWin32ExitCode);
ok(status.dwServiceSpecificExitCode == 0, "status.dwServiceSpecificExitCode = %d\n",
status.dwServiceSpecificExitCode);
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
res = DeleteService(service_handle);
ok(res, "DeleteService failed: %u\n", GetLastError());
res = QueryServiceStatus(service_handle, &status);
ok(res, "QueryServiceStatus failed: %d\n", GetLastError());
todo_wine ok(status.dwServiceType == SERVICE_WIN32_OWN_PROCESS, "status.dwServiceType = %x\n", status.dwServiceType);
ok(status.dwCurrentState==SERVICE_STOPPED || status.dwCurrentState==SERVICE_STOP_PENDING,
"status.dwCurrentState = %x\n", status.dwCurrentState);
ok(status.dwControlsAccepted == 0, "status.dwControlsAccepted = %x\n", status.dwControlsAccepted);
ok(status.dwWin32ExitCode == 0, "status.dwExitCode = %d\n", status.dwWin32ExitCode);
ok(status.dwServiceSpecificExitCode == 0, "status.dwServiceSpecificExitCode = %d\n",
status.dwServiceSpecificExitCode);
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
CloseServiceHandle(service_handle);
res = QueryServiceStatus(service_handle, &status);
ok(!res, "QueryServiceStatus should have failed\n");
ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError = %d\n", GetLastError());
}
static void test_runner(void (*p_run_test)(void))
{
HANDLE thread;
sprintf(service_name, "WineTestService%d", GetTickCount());
trace("service_name: %s\n", service_name);
sprintf(named_pipe_name, "\\\\.\\pipe\\%s_pipe", service_name);
@ -281,25 +450,11 @@ static void test_process(void)
if(!thread)
return;
service_handle = register_service();
if(!service_handle)
return;
p_run_test();
trace("starting...\n");
res = StartServiceA(service_handle, 0, NULL);
ok(res, "StartService failed: %u\n", GetLastError());
if(!res)
return;
expect_event("RUNNING");
res = ControlService(service_handle, SERVICE_CONTROL_STOP, &status);
ok(res, "ControlService failed: %u\n", GetLastError());
expect_event("STOP");
res = DeleteService(service_handle);
ok(res, "DeleteService failed: %u\n", GetLastError());
CloseServiceHandle(service_handle);
WaitForSingleObject(thread, INFINITE);
CloseHandle(event_handle);
CloseHandle(pipe_handle);
}
START_TEST(service)
@ -319,15 +474,17 @@ START_TEST(service)
ok(scm_handle != NULL, "OpenSCManager failed: %u\n", GetLastError());
if(argc < 3) {
test_process();
test_runner(test_service);
test_runner(test_no_stop);
}else {
strcpy(service_name, argv[2]);
strcpy(service_name, argv[3]);
sprintf(named_pipe_name, "\\\\.\\pipe\\%s_pipe", service_name);
service_process();
if(!strcmp(argv[2], "simple_service"))
service_process(service_main);
else if(!strcmp(argv[2], "no_stop"))
service_process(no_stop_main);
}
CloseHandle(event_handle);
CloseHandle(pipe_handle);
CloseServiceHandle(scm_handle);
}