blob: c007aa1f94a8b6bb7b40818d5b43ca9d66f68e33 [file] [log] [blame]
// Copyright 2016 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "named_pipe_client_win.h"
#include <string>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "named_pipe_server_win.h"
#include "named_pipe_win.h"
#include "worker_thread_manager.h"
namespace devtools_goma {
namespace {
const int kNamedPipeWaitTimeoutMs = 13000;
} // anonymous namespace
class NamedPipeClientTest : public ::testing::Test {
public:
class MockHandler : public NamedPipeServer::Handler {
public:
MockHandler() : wait_sec_(0) {}
~MockHandler() override {}
void HandleIncoming(NamedPipeServer::Request* req) override {
LOG(INFO) << "Handle incoming: msg=" << req->request_message();
EXPECT_EQ(expect_request_, req->request_message());
absl::SleepFor(absl::Seconds(wait_sec_));
LOG(INFO) << "reply response: msg=" << reply_;
req->SendReply(reply_);
}
void Transaction(const std::string& expect_req,
const std::string& reply) {
expect_request_ = expect_req;
reply_ = reply;
}
void SetWaitSec(int wait_sec) {
wait_sec_ = wait_sec;
}
private:
std::string expect_request_;
std::string reply_;
int wait_sec_;
};
};
TEST(NamedPipeClientTest, Simple) {
WorkerThreadManager wm;
wm.Start(1);
std::unique_ptr<NamedPipeClientTest::MockHandler> handler(
new NamedPipeClientTest::MockHandler);
static const char kReq[] = "POST /e HTTP/1.1\r\n";
static const char kResp[] = "HTTP/1.1 200 OK\r\n";
handler->Transaction(kReq, kResp);
LOG(INFO) << "pipe server starts";
NamedPipeServer server(&wm, handler.get());
static const char kName[] = "named-pipe-client-win-unittest";
server.Start(kName);
LOG(INFO) << "pipe clients starts";
NamedPipeFactory factory(kName, kNamedPipeWaitTimeoutMs);
ScopedNamedPipe pipe = factory.New();
if (!pipe.valid()) {
LOG_SYSRESULT(GetLastError());
}
ASSERT_TRUE(pipe.valid());
LOG(INFO) << "send message " << kReq;
ssize_t num_written = pipe.WriteWithTimeout(kReq, strlen(kReq), 5);
EXPECT_EQ(strlen(kReq), num_written);
LOG(INFO) << "wait for response...";
std::string buf;
buf.resize(1024);
ssize_t num_read = pipe.ReadWithTimeout(&buf[0], buf.size(), 5);
EXPECT_EQ(strlen(kResp), num_read);
buf.resize(num_read);
LOG(INFO) << "response=" << buf;
EXPECT_EQ(kResp, buf);
LOG(INFO) << "pipe server stopping...";
server.Stop();
wm.Finish();
}
TEST(NamedPipeClientTest, LargeResponse) {
WorkerThreadManager wm;
wm.Start(1);
std::unique_ptr<NamedPipeClientTest::MockHandler> handler(
new NamedPipeClientTest::MockHandler);
static const char kReq[] = "POST /e HTTP/1.1\r\n";
std::string resp = "HTTP/1.1 200 OK\r\n";
const int kBufsize = 1024;
// response is more than kBufsize
// but less than kOutputBufSize in named_pipe_server_win.cc (64 * 1024).
resp.resize(2 * 1024 + 512);
handler->Transaction(kReq, resp);
LOG(INFO) << "pipe server starts";
NamedPipeServer server(&wm, handler.get());
static const char kName[] = "named-pipe-client-win-unittest";
server.Start(kName);
LOG(INFO) << "pipe clients starts";
NamedPipeFactory factory(kName, kNamedPipeWaitTimeoutMs);
ScopedNamedPipe pipe = factory.New();
if (!pipe.valid()) {
LOG_SYSRESULT(GetLastError());
}
ASSERT_TRUE(pipe.valid());
LOG(INFO) << "send message " << kReq;
ssize_t num_written = pipe.WriteWithTimeout(kReq, strlen(kReq), 5);
EXPECT_EQ(strlen(kReq), num_written);
LOG(INFO) << "wait for response...";
std::string received;
for (;;) {
LOG(INFO) << "received=" << received.size()
<< " try read=" << kBufsize;
std::string buf;
buf.resize(kBufsize);
ssize_t num_read = pipe.ReadWithTimeout(&buf[0], buf.size(), 5);
if (num_read == 0) {
break;
}
EXPECT_GT(num_read, 0)
<< "received=" << received.size()
<< " err=" << num_read;
EXPECT_LE(num_read, kBufsize)
<< "received=" << received.size()
<< " read=" << num_read;
buf.resize(num_read);
received += buf;
if (received.size() == resp.size()) {
break;
}
}
EXPECT_EQ(resp, received);
LOG(INFO) << "pipe server stopping...";
server.Stop();
wm.Finish();
}
TEST(NamedPipeClientTest, LargeResponseThanOutputBuffer) {
WorkerThreadManager wm;
wm.Start(1);
std::unique_ptr<NamedPipeClientTest::MockHandler> handler(
new NamedPipeClientTest::MockHandler);
static const char kReq[] = "POST /e HTTP/1.1\r\n";
std::string resp = "HTTP/1.1 200 OK\r\n";
// response is more than kOutputBufSize
// in named_pipe_server_win.cc (128 * 1024).
const int kRespBufsize = 130 * 1024;
resp.resize(kRespBufsize);
handler->Transaction(kReq, resp);
LOG(INFO) << "pipe server starts";
NamedPipeServer server(&wm, handler.get());
static const char kName[] = "named-pipe-client-win-unittest";
server.Start(kName);
LOG(INFO) << "pipe clients starts";
NamedPipeFactory factory(kName, kNamedPipeWaitTimeoutMs);
ScopedNamedPipe pipe = factory.New();
if (!pipe.valid()) {
LOG_SYSRESULT(GetLastError());
}
ASSERT_TRUE(pipe.valid());
LOG(INFO) << "send message " << kReq;
ssize_t num_written = pipe.WriteWithTimeout(kReq, strlen(kReq), 5);
EXPECT_EQ(strlen(kReq), num_written);
LOG(INFO) << "wait for response...";
std::string received;
size_t bufsize = 1024;
for (;;) {
std::string buf;
if (!received.empty()) {
bufsize = kRespBufsize - received.size();
}
buf.resize(bufsize);
LOG(INFO) << "received=" << received.size()
<< " try read=" << bufsize;
ssize_t num_read = pipe.ReadWithTimeout(&buf[0], buf.size(), 5);
if (num_read == 0) {
break;
}
EXPECT_GT(num_read, 0)
<< "received=" << received.size()
<< " err=" << num_read;
EXPECT_LE(num_read, bufsize)
<< "received=" << received.size()
<< " read=" << num_read;
buf.resize(num_read);
received += buf;
if (received.size() == resp.size()) {
break;
}
}
EXPECT_EQ(resp, received);
LOG(INFO) << "pipe server stopping...";
server.Stop();
wm.Finish();
}
TEST(NamedPipeClientTest, Timeout) {
WorkerThreadManager wm;
wm.Start(1);
std::unique_ptr<NamedPipeClientTest::MockHandler> handler(
new NamedPipeClientTest::MockHandler);
static const char kReq[] = "POST /e HTTP/1.1\r\n";
static const char kResp[] = "HTTP/1.1 200 OK\r\n";
handler->Transaction(kReq, kResp);
handler->SetWaitSec(5);
LOG(INFO) << "pipe server starts";
NamedPipeServer server(&wm, handler.get());
static const char kName[] = "named-pipe-client-win-unittest";
server.Start(kName);
LOG(INFO) << "pipe clients starts";
NamedPipeFactory factory(kName, kNamedPipeWaitTimeoutMs);
ScopedNamedPipe pipe = factory.New();
if (!pipe.valid()) {
LOG_SYSRESULT(GetLastError());
}
ASSERT_TRUE(pipe.valid());
LOG(INFO) << "send message " << kReq;
ssize_t num_written = pipe.WriteWithTimeout(kReq, strlen(kReq), 5);
EXPECT_EQ(strlen(kReq), num_written);
LOG(INFO) << "wait for response...";
std::string received;
const int kBufsize = 1024;
for (;;) {
std::string buf;
buf.resize(kBufsize);
LOG(INFO) << "received=" << received.size()
<< " try read=" << buf.size();
ssize_t num_read = pipe.ReadWithTimeout(&buf[0], buf.size(), 1);
if (num_read == 0) {
break;
}
if (num_read == ERR_TIMEOUT) {
LOG(INFO) << "error timeout";
absl::SleepFor(absl::Seconds(2));
continue;
}
EXPECT_GT(num_read, 0)
<< "received=" << received.size()
<< " err=" << num_read;
EXPECT_LE(num_read, buf.size())
<< "received=" << received.size()
<< " read=" << num_read;
buf.resize(num_read);
LOG(INFO) << "receive: " << buf;
received += buf;
if (received.size() == strlen(kResp)) {
break;
}
}
EXPECT_EQ(kResp, received);
LOG(INFO) << "pipe server stopping...";
server.Stop();
wm.Finish();
}
} // namespace devtools_goma