capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

async-win32-test.c++ (4844B)


      1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
      2 // Licensed under the MIT License:
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a copy
      5 // of this software and associated documentation files (the "Software"), to deal
      6 // in the Software without restriction, including without limitation the rights
      7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 // copies of the Software, and to permit persons to whom the Software is
      9 // furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20 // THE SOFTWARE.
     21 
     22 #if _WIN32
     23 
     24 #include "async-win32.h"
     25 #include "thread.h"
     26 #include "test.h"
     27 #include "mutex.h"
     28 
     29 namespace kj {
     30 namespace {
     31 
     32 KJ_TEST("Win32IocpEventPort I/O operations") {
     33   Win32IocpEventPort port;
     34   EventLoop loop(port);
     35   WaitScope waitScope(loop);
     36 
     37   auto pipeName = kj::str("\\\\.\\Pipe\\kj-async-win32-test.", GetCurrentProcessId());
     38 
     39   HANDLE readEnd_, writeEnd_;
     40   KJ_WIN32(readEnd_ = CreateNamedPipeA(pipeName.cStr(),
     41       PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
     42       PIPE_TYPE_BYTE | PIPE_WAIT,
     43       1, 0, 0, 0, NULL));
     44   AutoCloseHandle readEnd(readEnd_);
     45 
     46   KJ_WIN32(writeEnd_ = CreateFileA(pipeName.cStr(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
     47                                    FILE_ATTRIBUTE_NORMAL, NULL));
     48   AutoCloseHandle writeEnd(writeEnd_);
     49 
     50   auto observer = port.observeIo(readEnd);
     51   auto op = observer->newOperation(0);
     52 
     53   byte buffer[256];
     54 
     55   KJ_ASSERT(!ReadFile(readEnd, buffer, sizeof(buffer), NULL, op->getOverlapped()));
     56   DWORD error = GetLastError();
     57   if (error != ERROR_IO_PENDING) {
     58     KJ_FAIL_WIN32("ReadFile()", error);
     59   }
     60 
     61   bool done = false;
     62   auto promise = op->onComplete().then([&](Win32EventPort::IoResult result) {
     63     done = true;
     64     return result;
     65   }).eagerlyEvaluate(nullptr);
     66 
     67   KJ_EXPECT(!done);
     68 
     69   evalLater([]() {}).wait(waitScope);
     70   evalLater([]() {}).wait(waitScope);
     71   evalLater([]() {}).wait(waitScope);
     72   evalLater([]() {}).wait(waitScope);
     73   evalLater([]() {}).wait(waitScope);
     74 
     75   KJ_EXPECT(!done);
     76 
     77   DWORD bytesWritten;
     78   KJ_WIN32(WriteFile(writeEnd, "foo", 3, &bytesWritten, NULL));
     79   KJ_EXPECT(bytesWritten == 3);
     80 
     81   auto result = promise.wait(waitScope);
     82   KJ_EXPECT(result.errorCode == ERROR_SUCCESS);
     83   KJ_EXPECT(result.bytesTransferred == 3);
     84 
     85   KJ_EXPECT(kj::str(kj::arrayPtr(buffer, 3).asChars()) == "foo");
     86 }
     87 
     88 KJ_TEST("Win32IocpEventPort::wake()") {
     89   Win32IocpEventPort port;
     90 
     91   Thread thread([&]() {
     92     Sleep(10);
     93     port.wake();
     94   });
     95 
     96   KJ_EXPECT(port.wait());
     97 }
     98 
     99 KJ_TEST("Win32IocpEventPort::wake() on poll()") {
    100   Win32IocpEventPort port;
    101   volatile bool woken = false;
    102 
    103   Thread thread([&]() {
    104     Sleep(10);
    105     port.wake();
    106     woken = true;
    107   });
    108 
    109   KJ_EXPECT(!port.poll());
    110   while (!woken) Sleep(10);
    111   KJ_EXPECT(port.poll());
    112 }
    113 
    114 KJ_TEST("Win32IocpEventPort timer") {
    115   Win32IocpEventPort port;
    116   EventLoop loop(port);
    117   WaitScope waitScope(loop);
    118 
    119   auto start = port.getTimer().now();
    120 
    121   bool done = false;
    122   auto promise = port.getTimer().afterDelay(10 * MILLISECONDS).then([&]() {
    123     done = true;
    124   }).eagerlyEvaluate(nullptr);
    125 
    126   KJ_EXPECT(!done);
    127 
    128   evalLater([]() {}).wait(waitScope);
    129   evalLater([]() {}).wait(waitScope);
    130   evalLater([]() {}).wait(waitScope);
    131   evalLater([]() {}).wait(waitScope);
    132   evalLater([]() {}).wait(waitScope);
    133 
    134   KJ_EXPECT(!done);
    135 
    136   promise.wait(waitScope);
    137   KJ_EXPECT(done);
    138   KJ_EXPECT(port.getTimer().now() - start >= 10 * MILLISECONDS);
    139 }
    140 
    141 VOID CALLBACK testApcProc(ULONG_PTR dwParam) {
    142   reinterpret_cast<kj::PromiseFulfiller<void>*>(dwParam)->fulfill();
    143 }
    144 
    145 KJ_TEST("Win32IocpEventPort APC") {
    146   if (GetProcAddress(GetModuleHandle("ntdll.dll"), "wine_get_version") != nullptr) {
    147     // TODO(cleanup): Periodically check if Wine supports this yet.
    148     KJ_LOG(WARNING, "detected that we're running under wine and this test won't work; skipping");
    149     return;
    150   }
    151 
    152   Win32IocpEventPort port;
    153   EventLoop loop(port);
    154   WaitScope waitScope(loop);
    155 
    156   port.allowApc();
    157 
    158   auto paf = kj::newPromiseAndFulfiller<void>();
    159 
    160   KJ_WIN32(QueueUserAPC(&testApcProc, GetCurrentThread(),
    161       reinterpret_cast<ULONG_PTR>(paf.fulfiller.get())));
    162 
    163   paf.promise.wait(waitScope);
    164 }
    165 
    166 }  // namespace
    167 }  // namespace kj
    168 
    169 #endif  // _WIN32