Skip to content

Commit

Permalink
C++ client: process the envp argument to main instead of calling gete…
Browse files Browse the repository at this point in the history
…nv() (deephaven#5393)

* C++ client: process the envp argument to main instead of calling getenv()

* Respond to review feedback
  • Loading branch information
kosak authored Apr 22, 2024
1 parent 2858f51 commit 87217e7
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,35 @@
#include "deephaven/dhcore/utility/utility.h"

namespace deephaven::client::tests {
/**
* Stores a static global map of environment variable key/value pairs.
* Initialized from the 'envp' variable passed in to main.
*/
class GlobalEnvironmentForTests {
public:
/**
* Initialize the environment_ map from the envp array passed into main().
* @param envp The envp parameter that was passed by the OS into 'main'.
*/
static void Init(char **envp);

/**
* Look up 'key' in the environment_ map. Returns the associated value if found;
* otherwise returns the value contained in 'defaultValue'.
*
* @param key The key
* @param default_value The value to return if the key is not found.
* @return The associated value if found, otherwise the value contained in 'defaultValue'.
*/
static std::string_view GetEnv(std::string_view key, std::string_view default_value);

// This is a pointer, so we don't have to worry about global construction/destruction.
// At global teardown time we will just leak memory.
// Also, std::less<> gets us the transparent comparator, so we can do lookups
// directly with string_view.
static std::map<std::string, std::string, std::less<>> *environment_;
};

class ColumnNamesForTests {
public:
ColumnNamesForTests();
Expand Down
11 changes: 10 additions & 1 deletion cpp-client/deephaven/tests/src/main.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
/*
* Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
*/
#define CATCH_CONFIG_MAIN
#define CATCH_CONFIG_RUNNER
#include "deephaven/third_party/catch.hpp"
#include "deephaven/tests/test_util.h"

using deephaven::client::tests::GlobalEnvironmentForTests;

int main(int argc, char *argv[], char **envp) {
// Process envp so we don't have to call getenv(), which Windows complains about.
GlobalEnvironmentForTests::Init(envp);
return Catch::Session().run(argc, argv);
}
42 changes: 37 additions & 5 deletions cpp-client/deephaven/tests/src/test_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,40 @@ using deephaven::client::utility::TableMaker;
using deephaven::client::utility::ValueOrThrow;

namespace deephaven::client::tests {
std::map<std::string, std::string, std::less<>> *GlobalEnvironmentForTests::environment_ = nullptr;

void GlobalEnvironmentForTests::Init(char **envp) {
if (environment_ != nullptr) {
throw std::runtime_error(DEEPHAVEN_LOCATION_STR("It's an error to call Init() twice"));
}
environment_ = new std::map<std::string, std::string, std::less<>>();

for (char **current = envp; *current != nullptr; ++current) {
std::string_view sv(*current);

// Find the equal sign and split the strings into keys and values.
auto pos = sv.find('=');
if (pos == std::string_view::npos) {
continue;
}
auto key = sv.substr(0, pos);
auto value = sv.substr(pos + 1);
environment_->try_emplace(std::string(key), value);
}
}

std::string_view GlobalEnvironmentForTests::GetEnv(std::string_view key,
std::string_view default_value) {
if (environment_ == nullptr) {
return default_value;
}
auto ip = environment_->find(key);
if (ip == environment_->end()) {
return default_value;
}
return ip->second;
}

ColumnNamesForTests::ColumnNamesForTests() : importDate_("ImportDate"), ticker_("Ticker"),
open_("Open"), close_("Close"), volume_("Volume") {}
ColumnNamesForTests::ColumnNamesForTests(ColumnNamesForTests &&other) noexcept = default;
Expand Down Expand Up @@ -116,11 +150,9 @@ TableMakerForTests TableMakerForTests::Create() {
}

Client TableMakerForTests::CreateClient(const ClientOptions &options) {
const char *hostptr = std::getenv("DH_HOST");
const char *portptr = std::getenv("DH_PORT");
std::string host = (hostptr == nullptr) ? "localhost" : hostptr;
std::string port = (portptr == nullptr) ? "10000" : portptr;
std::string connection_string(host + ":" + port);
auto host = GlobalEnvironmentForTests::GetEnv("DH_HOST", "localhost");
auto port = GlobalEnvironmentForTests::GetEnv("DH_PORT", "10000");
auto connection_string = fmt::format("{}:{}", host, port);
fmt::print(std::cerr, "Connecting to {}\n", connection_string);
auto client = Client::Connect(connection_string, options);
return client;
Expand Down

0 comments on commit 87217e7

Please sign in to comment.