blob: 30735d44536334bfbc0e007b67ae95cf41216da3 [file] [log] [blame]
// Copyright 2023 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "persistent_service_test_lib.h"
#include <inttypes.h>
#include "ipc_utils.h"
#include "persistent_service.h"
#include "util.h"
#define DEBUG 0
// Common macros used to print a prefix then an message to stderr.
#define STDERR_PRINTF(prefix, ...) \
do { \
fputs(prefix, stderr); \
fprintf(stderr, __VA_ARGS__); \
fputs("\n", stderr); \
} while (0)
#if DEBUG
#define SERVER_LOG(...) STDERR_PRINTF("TEST_SERVER: ", __VA_ARGS__)
#define CLIENT_LOG(...) STDERR_PRINTF("TEST_CLIENT: ", __VA_ARGS__)
#else
#define SERVER_LOG(...) (void)0
#define CLIENT_LOG(...) (void)0
#endif
#define SERVER_ERR(...) STDERR_PRINTF("TEST_SERVER: ERROR: ", __VA_ARGS__)
#define SERVER_WARN(...) STDERR_PRINTF("TEST_SERVER: WARNING: ", __VA_ARGS__)
#define CLIENT_ERR(...) STDERR_PRINTF("TEST_CLIENT: ERROR: ", __VA_ARGS__)
#define CLIENT_WARN(...) STDERR_PRINTF("TEST_CLIENT: WARNING: ", __VA_ARGS__)
namespace {
std::vector<std::string> GetServerArgs(const std::string* version) {
std::vector<std::string> result;
std::string program =
GetCurrentExecutableDir() + "/persistent_service_test_helper";
#ifdef _WIN32
program.append(".exe");
#endif
result.push_back(std::move(program));
if (version)
result.push_back(*version);
return result;
}
// This is necessary because RemoteWrite("ping", ...) will send a 5-byte
// character sequence (including the terminating zero), instead of a
// string size + its content.
bool SendString(const char* str, IpcHandle& con, std::string* err) {
return RemoteWrite(std::string(str), con, err);
}
} // namespace
namespace persistent_service_test {
const char kServiceName[] = "persistent-server-test";
const char kDefaultVersion[] = "default-version";
PersistentService::Config GetServerConfig() {
PersistentService::Config config(GetServerArgs(nullptr));
return config.SetVersionInfo(kDefaultVersion);
}
void SetServiceConfigVersion(PersistentService::Config& config,
const std::string& version) {
config.SetVersionInfo(version);
config.command.push_back(StringFormat("-v%s", version.c_str()));
}
void SetServiceConfigTimeoutMs(PersistentService::Config& config,
int64_t connection_timeout_ms) {
config.command.push_back(StringFormat("-t%" PRId64, connection_timeout_ms));
}
PersistentService::Server::VersionCheckHandler GetVersionCheckHandler(
const std::string& server_version_info) {
return [server_version_info](
const std::string& client_version_info) -> std::string {
if (client_version_info != server_version_info) {
return StringFormat("Version mismatch, expected [%s] got [%s]",
server_version_info.c_str(),
client_version_info.c_str());
}
return {};
};
}
bool RequestHandler(IpcHandle connection) {
std::string error;
std::string request;
bool is_first = true;
while (true) {
SERVER_LOG("Waiting for request");
if (!RemoteRead(request, connection, &error)) {
if (!is_first) {
SERVER_LOG("Client connection closed");
return true;
}
SERVER_ERR("Could not read request: %s\n", error.c_str());
return false;
}
SERVER_LOG("Received request [%.*s]", (int)request.size(), request.c_str());
is_first = false;
if (request == "kill-server") {
SERVER_LOG("TEST_SERVER: kill-server command received, exiting");
return false;
}
if (request == "ping") {
SERVER_LOG("TEST_SERVER: ping request received, sending reply");
if (!SendString("pong", connection, &error)) {
SERVER_ERR("Could not send reply: %s\n", error.c_str());
return false;
}
SERVER_LOG("pong sent");
continue;
}
SERVER_ERR("Unknown request [%s]\n", request.c_str());
return false;
}
}
bool RunTest(IpcHandle& client, bool kill_server, std::string* err) {
if (!SendString("ping", client, err)) {
CLIENT_ERR("Could not send test request: %s\n", err->c_str());
return false;
}
std::string reply;
if (!RemoteRead(reply, client, err)) {
CLIENT_ERR("Could not receive test reply: %s\n", err->c_str());
return false;
}
bool success = (reply == "pong");
if (!success) {
CLIENT_ERR("Invalid reply [%s] expected [pong]\n", reply.c_str());
// Do not return here to ensure the server is killed.
}
if (kill_server) {
if (!SendString("kill-server", client, err)) {
CLIENT_ERR("Could not kill server: %s\n", err->c_str());
}
PersistentService::Client persistent(kServiceName);
if (!persistent.WaitForServerShutdown()) {
CLIENT_WARN("Could not wait for server shutdown\n");
}
}
return success;
}
} // namespace persistent_service_test