Fixed a race condition on RPC worker thread creation, and a typo.
[wine] / dlls / kernel / tests / pipe.c
1 /*
2  * Unit tests for named pipe functions in Wine
3  *
4  * Copyright (c) 2002 Dan Kegel
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <time.h>
24
25 #ifndef STANDALONE
26 #include "wine/test.h"
27 #else
28 #include <assert.h>
29 #define START_TEST(name) main(int argc, char **argv)
30 #define ok(condition, msg) assert(condition)
31 #define todo_wine
32 #endif
33
34 #include <wtypes.h>
35 #include <windef.h>
36 #include <winbase.h>
37 #include <winerror.h>
38
39 #define PIPENAME "\\\\.\\PiPe\\tests_" __FILE__
40
41 void test_CreateNamedPipeA(void)
42 {
43     HANDLE hnp;
44     HANDLE hFile;
45     const char obuf[] = "Bit Bucket";
46     char ibuf[32];
47     DWORD written;
48     DWORD gelesen;
49
50     /* Bad parameter checks */
51     hnp = CreateNamedPipeA("not a named pipe", 
52         PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_WAIT, 
53         /* nMaxInstances */ 1,
54         /* nOutBufSize */ 1024,
55         /* nInBufSize */ 1024,
56         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
57         /* lpSecurityAttrib */ NULL);
58
59     if (hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
60         /* Is this the right way to notify user of skipped tests? */
61         ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, 
62             "CreateNamedPipe not supported on this platform, skipping tests.");
63         return;
64     }
65     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
66         "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe");
67
68     hnp = CreateNamedPipeA(NULL, 
69         PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_WAIT, 
70         1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
71     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
72         "CreateNamedPipe should fail if name is NULL");
73
74     hFile = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, 
75         NULL, OPEN_EXISTING, 0, 0);
76     ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND, "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND");
77
78     /* Functional checks */
79
80     hnp = CreateNamedPipeA(PIPENAME,
81         PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_WAIT, 
82         /* nMaxInstances */ 1,
83         /* nOutBufSize */ 1024,
84         /* nInBufSize */ 1024,
85         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
86         /* lpSecurityAttrib */ NULL);
87     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
88
89     hFile = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, 
90             NULL, OPEN_EXISTING, 0, 0);
91     todo_wine
92     {
93         ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed");
94     }
95
96     /* don't try to do i/o if one side couldn't be opened, as it hangs */
97     if (hFile != INVALID_HANDLE_VALUE) {
98         HANDLE hFile2;
99
100         /* Make sure we can read and write a few bytes in both directions*/
101         memset(ibuf, 0, sizeof(ibuf));
102         ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile");
103         ok(written == sizeof(obuf), "write file len");
104         ok(ReadFile(hFile, ibuf, sizeof(obuf), &gelesen, NULL), "ReadFile");
105         ok(gelesen == sizeof(obuf), "read file len");
106         ok(memcmp(obuf, ibuf, written) == 0, "content check");
107
108         memset(ibuf, 0, sizeof(ibuf));
109         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile");
110         ok(written == sizeof(obuf), "write file len");
111         ok(ReadFile(hnp, ibuf, sizeof(obuf), &gelesen, NULL), "ReadFile");
112         ok(gelesen == sizeof(obuf), "read file len");
113         ok(memcmp(obuf, ibuf, written) == 0, "content check");
114
115         /* Picky conformance tests */
116
117         /* Verify that you can't connect to pipe again
118          * until server calls DisconnectNamedPipe+ConnectNamedPipe
119          * or creates a new pipe
120          * case 1: other client not yet closed
121          */
122         hFile2 = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, 
123             NULL, OPEN_EXISTING, 0, 0);
124         ok(hFile2 == INVALID_HANDLE_VALUE, "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail");
125         ok(GetLastError() == ERROR_PIPE_BUSY, "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY");
126
127         ok(CloseHandle(hFile), "CloseHandle");
128
129         /* case 2: other client already closed */
130         hFile = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, 
131             NULL, OPEN_EXISTING, 0, 0);
132         ok(hFile == INVALID_HANDLE_VALUE, "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail");
133         ok(GetLastError() == ERROR_PIPE_BUSY, "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY");
134
135         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe");
136
137         /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
138         hFile = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, 
139             NULL, OPEN_EXISTING, 0, 0);
140         ok(hFile == INVALID_HANDLE_VALUE, "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail");
141         ok(GetLastError() == ERROR_PIPE_BUSY, "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY");
142
143         /* to be complete, we'd call ConnectNamedPipe here and loop,
144          * but by default that's blocking, so we'd either have
145          * to turn on the uncommon nonblocking mode, or
146          * use another thread.
147          */
148     }
149
150     ok(CloseHandle(hnp), "CloseHandle");
151 }
152
153 START_TEST(pipe)
154 {
155     test_CreateNamedPipeA();
156 }