Alternate e697dbe9c5997e35395fe158628dd8c5209481da
for Visual Studio 2022 and Windows 11.
読み取り中…
検索中…
一致する文字列を見つけられません
NamedPipeTest.cpp
[詳解]
1
5
6#include "pch.h"
7#include "NamedPipe.h"
8#include "Thread.h"
9#include "Array.hpp"
10#include "Utility.h"
11
12using namespace Microsoft::VisualStudio::CppUnitTestFramework;
13
14#define PIPE_NAME _T ("TEST_PIPE")
15const int __ciBufferSize = 120;
16
17namespace WindowsLibraryTest
18{
19 TEST_CLASS (NamedPipeTest)
20 {
21 public:
22 TEST_CLASS_INITIALIZE (ClassInitialize)
23 {
24 Logger::WriteMessage ("NamedPipeTest class initialize.\n");
25 }
26
27 TEST_CLASS_CLEANUP (ClassCleanup)
28 {
29 Logger::WriteMessage ("NamedPipeTest class cleanup.\n");
30 }
31
32 TEST_METHOD_INITIALIZE (MethodInitialize)
33 {
34 Logger::WriteMessage ("NamedPipeTest method initialize.\n");
35 }
36
37 TEST_METHOD_CLEANUP (MethodCleanup)
38 {
39 Logger::WriteMessage ("NamedPipeTest method cleanup.\n");
40 }
41
42 TEST_METHOD (NamedPipeStreamTest1)
43 {
44 auto serverFunc = [](LPVOID lpvParam)->DWORD
45 {
46 alt::NamedPipe pipe;
47 BOOL ret;
48 TCHAR tszBuff[__ciBufferSize];
49 DWORD dwRet;
50
51 ret = pipe.Create (PIPE_NAME, TRUE);
52 Assert::IsTrue (ret, _T ("S)NamedPipe::Create() failed.\n"));
53
54 ret = pipe.Connect ();
55 Assert::IsTrue (ret, _T ("S)NamedPipe::Connect() failed.\n"));
56
57 while (true)
58 {
59 dwRet = pipe.PeekRemain ();
60 if (dwRet < 0)
61 {
62 Assert::Fail (_T ("S)NamedPipe::PeekRemain() failed.\n"));
63 }
64
65 if (dwRet == 0)
66 {
67 Logger::WriteMessage ("S)メッセージが到着していません。\n");
68 Sleep (1000);
69 }
70 else break;
71 }
72 Assert::AreEqual<DWORD> (6 * sizeof (TCHAR), dwRet, _T ("S)NamedPipe::PeekRemain() invalid size.\n"));
73
74 ZeroMemory (tszBuff, sizeof (tszBuff));
75 dwRet = pipe.PeekData (tszBuff, __ciBufferSize);
76 tszBuff[__ciBufferSize - 1] = NULL;
77 Assert::IsTrue (ret, _T ("S)NamedPipe::PeekData() failed.\n"));
78 Assert::AreNotEqual<DWORD> (0, dwRet, _T ("S)NamedPipe::PeekData() invalid size.\n"));
79 Assert::AreEqual<int> (0, lstrcmp (_T ("12345"), tszBuff), _T ("S)受信(Peek)内容が想定外です。"));
80
81 ZeroMemory (tszBuff, sizeof (tszBuff));
82 dwRet = pipe.Read (tszBuff, __ciBufferSize);
83 Assert::AreEqual<DWORD> (6 * sizeof (TCHAR), dwRet, _T("NamedPipe::Read() failed.\n"));
84 Assert::AreEqual<int> (0, lstrcmp (_T ("12345"), tszBuff), _T ("S)受信(Read)内容が想定外です。"));
85
86 ret = pipe.Close ();
87 Assert::IsTrue (ret, _T ("S)NamedPipe::Close() failed.\n"));
88
89 return 0;
90 };
91
92 auto clientFunc = [](LPVOID lpvParam)->DWORD
93 {
94 alt::NamedPipe pipe;
95 BOOL ret;
96 TCHAR tszBuf[__ciBufferSize];
97 DWORD dwRet;
98
99 ret = pipe.Wait (PIPE_NAME);
100 Assert::IsTrue (ret, _T ("C)NamedPipe::Wait() failed.\n"));
101
102 ret = pipe.Open (PIPE_NAME);
103 Assert::IsTrue (ret, _T ("C)NamedPipe::Open() failed.\n"));
104
105 wsprintf (tszBuf, _T ("%s"), _T ("12345"));
106 dwRet = pipe.Write (tszBuf, 6 * sizeof (TCHAR));
107 Assert::AreEqual<DWORD> (6 * sizeof (TCHAR), dwRet, _T ("C)NamedPipe::Write() failed.\n"));
108
109 ret = pipe.Close ();
110 Assert::IsTrue (ret, _T ("C)NamedPipe::Close() failed.\n"));
111
112 return 0;
113 };
114
115 alt::Thread* serverThread = new alt::Thread ();
116 serverThread->Create (serverFunc);
117
118 Sleep (1000);
119
120 alt::Thread* clientThread = new alt::Thread ();
121 clientThread->Create (clientFunc);
122
123 clientThread->Wait ();
124 serverThread->Wait ();
125
126 delete clientThread;
127 delete serverThread;
128 }
129
130 class ServerPipe : public alt::skeleton::ICallback
131 {
132 public:
133 ServerPipe (int instanceNo) { _instanceNo = instanceNo; };
134
135 BOOL Create ()
136 {
137 BOOL ret = _pipe.Create (PIPE_NAME, TRUE);
138 Assert::IsTrue (ret, _T ("S)NamedPipe::Create() failed.\n"));
139
140 return ret;
141 };
142
143 BOOL Connect ()
144 {
145 BOOL ret = _pipe.Connect ();
146 Assert::IsTrue (ret, _T ("S)NamedPipe::Connect() failed.\n"));
147
148 return ret;
149 };
150
151 BOOL Disconnect ()
152 {
153 BOOL ret = _pipe.Disconnect ();
154 Assert::IsTrue (ret, _T ("S)NamedPipe::Disconnect() failed.\n"));
155
156 return ret;
157 };
158
159 BOOL MessagePeek (LPTSTR lptszBuff, DWORD dwSize)
160 {
161 DWORD dwCheck;
162
163 while (true)
164 {
165 dwCheck = _pipe.PeekRemain ();
166 if (dwCheck == 0) Sleep (1000);
167 else if (dwSize > 0) break;
168 else Assert::Fail (_T ("S)NamedPipe::PeekRemain() failed.\n"));
169 }
170
171 dwCheck = _pipe.PeekData (lptszBuff, dwSize);
172 Assert::AreNotEqual<DWORD> (0, dwCheck, _T ("S)NamedPipe::Peek() return 0.\n"));
173
174 return (dwCheck > 0);
175 };
176
177 BOOL Close ()
178 {
179 BOOL ret = _pipe.Close ();
180 Assert::IsTrue (ret, _T ("S)NamedPipe::Close() failed.\n"));
181
182 return ret;
183 };
184
185 private:
186 ServerPipe () { _instanceNo = -1; };
187
188 DWORD Invoke (LPVOID lpvParam)
189 {
190 BYTE byBuffer[__ciBufferSize];
191 alt::TString message;
192
193 for (;;)
194 {
195 ZeroMemory (byBuffer, __ciBufferSize);
196 DWORD dwSize = _pipe.Read (byBuffer, __ciBufferSize);
197 if (dwSize == (DWORD)-1)
198 {
199 message.Format (_T (" S%d)Maybe disconnect.\n"), _instanceNo);
200 Logger::WriteMessage (message.Ctr ());
201 break;
202 }
203 else
204 {
205 byBuffer[dwSize] = '\0';
207 TCHAR tszBuf[__ciBufferSize];
208 wsprintf (tszBuf, _T (" S%d)Received:%s %s\n"), _instanceNo, message.Ctr (), (LPCTSTR)byBuffer);
209 Logger::WriteMessage (tszBuf);
210 }
211 Sleep (0);
212
213 message = _T ("NEXT");
214 _pipe.Write (message.Ctr (), message.Byte ());
215 Sleep (0);
216 }
217
218 this->Disconnect ();
219 this->Close ();
220
221 return 0;
222 };
223
224 private:
225 int _instanceNo;
226 alt::NamedPipe _pipe;
227 };
228
229 class ClientPipe : public alt::skeleton::ICallback
230 {
231 public:
232 ClientPipe (int instanceNo) { _instanceNo = instanceNo; };
233
234 BOOL Wait ()
235 {
236 BOOL ret = _pipe.Wait (PIPE_NAME, 3000);
237 Assert::IsTrue (ret, _T ("C)NamedPipe::Wait() failed.\n"));
238
239 return ret;
240 };
241
242 BOOL Open ()
243 {
244 BOOL ret = _pipe.Open (_T ("TEST_PIPE"));
245 Assert::IsTrue (ret, _T ("C)NamedPipe::Open() failed.\n"));
246
247 return ret;
248 };
249
250 BOOL Close ()
251 {
252 BOOL ret = _pipe.Close ();
253 Assert::IsTrue (ret, _T ("C)NamedPipe::Close() failed.\n"));
254
255 return ret;
256 };
257
258 private:
259 ClientPipe () { _instanceNo = -1; };
260
261 DWORD Read (LPVOID lpvBuf, DWORD dwSize)
262 {
263 return _pipe.Read (lpvBuf, dwSize);
264 };
265
266 DWORD Write (LPVOID lpvBuf, DWORD dwSize)
267 {
268 return _pipe.Write (lpvBuf, dwSize);
269 };
270
271 DWORD Invoke (LPVOID lpvParam)
272 {
273 TCHAR tszBuff[__ciBufferSize];
274 alt::TString message;
275
276 for (int i = 0; i < 10; i++)
277 {
279 wsprintf (tszBuff, _T ("C%d)%03d %s"), _instanceNo, i, message.Ctr ());
280 DWORD dwWrite = this->Write (tszBuff, lstrlen (tszBuff) * sizeof (TCHAR));
281 Sleep (0);
282
283 ZeroMemory (tszBuff, sizeof (tszBuff));
284 DWORD dwRead = this->Read (tszBuff, __ciBufferSize);
285 tszBuff[dwRead/2] = NULL;
286 message.Format (_T (" C%d)Received %s.\n"), _instanceNo, tszBuff);
287 Logger::WriteMessage (message.Ctr());
288 Sleep (500);
289 }
290
291 this->Close ();
292
293 return 0;
294 };
295
296 private:
297 int _instanceNo;
298 alt::NamedPipe _pipe;
299 };
300
301 TEST_METHOD (NamedPipeStreamTest2)
302 {
303 auto serverFunc = [](LPVOID lpvParam)->DWORD
304 {
307 TCHAR tszBuff[10] = { 0 };
308
309 for (int i = 1; i <= 10; i++)
310 {
311 ServerPipe* pServerPipe = new ServerPipe (i);
312 pServerPipe->Create ();
313 pServerPipe->Connect ();
314 pipes.Add (*pServerPipe);
315
316 pServerPipe->MessagePeek (tszBuff, sizeof (tszBuff));
317 if (!_memicmp ("EXIT", tszBuff, 4))
318 {
319 Logger::WriteMessage (_T ("S)Loop escaped.\n"));
320 break;
321 }
322
323 alt::Thread* pThread = new alt::Thread (pServerPipe);
324 pThread->Create ();
325 container.Add (*pThread);
326 }
327
328 return 0;
329 };
330
331 auto clientFunc = [](LPVOID lpvParam)->DWORD
332 {
333 int clientNo = *((int*)(lpvParam));
334 ClientPipe clientPipe (clientNo);
335 clientPipe.Wait ();
336 clientPipe.Open ();
337
338 alt::Thread thread (&clientPipe);
339 thread.Create ();
340 thread.Wait ();
341
342 return 0;
343 };
344
345 alt::Thread* serverThread = new alt::Thread ();
346 serverThread->Create (serverFunc);
347
348 Sleep (3000);
349
350 alt::Thread* clientThread1 = new alt::Thread ();
351 int client1 = 1;
352
353 alt::Thread* clientThread2 = new alt::Thread ();
354 int client2 = 2;
355
356 alt::Thread* clientThread3 = new alt::Thread ();
357 int client3 = 3;
358
359 clientThread1->Create (clientFunc, &client1);
360 Sleep (1000);
361 clientThread2->Create (clientFunc, &client2);
362 Sleep (1000);
363 clientThread3->Create (clientFunc, &client3);
364
365 clientThread1->Wait ();
366 clientThread2->Wait ();
367 clientThread3->Wait ();
368
369 delete clientThread1;
370 delete clientThread2;
371 delete clientThread3;
372
373 alt::NamedPipe terminator;
374 terminator.Wait (PIPE_NAME);
375 terminator.Open (PIPE_NAME);
376 terminator.Write ("EXIT", 4);
377 Logger::WriteMessage ("'EXIT' send to server pipe.\n");
378
379 serverThread->Wait (3000);
380 delete serverThread;
381 }
382 };
383}
可変配列に関するクラス
名前付きパイプに関するWindowsAPIを集約したクラス
#define PIPE_NAME
const int __ciBufferSize
スレッドに関するWindowsAPIを集約したクラス
汎用的に使えるユーティリティクラス
プリコンパイル済みヘッダー ファイルです。
BOOL APIENTRY Close()
使用しなくなったハンドルはこれでクローズします。
名前付きパイプに関するWindowsAPIを集約したクラス
Definition: NamedPipe.h:18
BOOL APIENTRY Open(LPCTSTR lpctszName)
パイプをオープンします。
Definition: NamedPipe.cpp:57
BOOL APIENTRY Connect() const
サーバー側でクライアント接続を待機します。
Definition: NamedPipe.cpp:47
BOOL APIENTRY Wait(LPCTSTR lpctszName, DWORD dwTimeout=NMPWAIT_USE_DEFAULT_WAIT) const
クライアント側でサーバー接続を待機します。
Definition: NamedPipe.cpp:75
DWORD APIENTRY PeekRemain() const
バッファ内に残っているメッセージサイズを取得します。
Definition: NamedPipe.cpp:95
BOOL APIENTRY Create(LPCTSTR lpctszName, BOOL bStreamMode)
パイプを作成します。
Definition: NamedPipe.cpp:12
DWORD APIENTRY PeekData(LPVOID lpvData, DWORD dwSize) const
メッセージ内容を取り出さずに読み取ります。
Definition: NamedPipe.cpp:84
DWORD APIENTRY Read(LPVOID lpvBuffer, DWORD dwSize) const
HANDLEを使ってデータを読み込みます。
DWORD APIENTRY Write(LPCVOID lpcvBuffer, DWORD dwSize) const
HANDLEを使ってデータを書き込みます。
文字列に関するWindowsAPIを集約したクラス
Definition: TString.h:17
TString &APIENTRY Format(LPCTSTR format,...)
フォーマットに従ってパラメータを文字列化します。
Definition: TString.cpp:333
INT APIENTRY Byte() const
内部で確保している文字列(バイト数)を取得します。
Definition: TString.cpp:44
LPCTSTR APIENTRY Ctr() const
内部で確保している文字列ポインタを取得します。
Definition: TString.h:46
スレッドに関するWindowsAPIを集約したクラス
Definition: Thread.h:43
BOOL APIENTRY Create(PTHREAD_START_ROUTINE function=NULL, LPVOID lpvParam=NULL, DWORD dwCreationFlag=0)
スレッドを作成します。
Definition: Thread.cpp:24
static SYSTEMTIME APIENTRY GetLocalTime()
ローカル時間の取得
Definition: Utility.cpp:46
static TString APIENTRY GetFormatTime(const SYSTEMTIME &systemTime)
SYSTEMTIME構造体の値を文字列化
Definition: Utility.cpp:55
DWORD APIENTRY Wait(DWORD dwWaitTime=INFINITE) const
シグナル状態になるとブロックを解除します。
サイズ可変の配列を具現したクラス
Definition: Array.hpp:20
VOID APIENTRY Add(T &item)
Array<T>へ値を追加
Definition: Array.hpp:83
Threadクラスのスレッド実行関数を設定します。
TEST_CLASS(ArrayTest)
Definition: ArrayTest.cpp:19