diff options
Diffstat (limited to 'src/zenserver-test/hub-tests.cpp')
| -rw-r--r-- | src/zenserver-test/hub-tests.cpp | 137 |
1 files changed, 134 insertions, 3 deletions
diff --git a/src/zenserver-test/hub-tests.cpp b/src/zenserver-test/hub-tests.cpp index 11531e30f..9c1669256 100644 --- a/src/zenserver-test/hub-tests.cpp +++ b/src/zenserver-test/hub-tests.cpp @@ -19,6 +19,8 @@ # include <zenutil/zenserverprocess.h> # include <zenhttp/httpclient.h> # include <zenutil/consul.h> +# include <zencore/thread.h> +# include <zencore/timer.h> namespace zen::tests::hub { @@ -230,12 +232,33 @@ TEST_CASE("hub.lifecycle.children") } } -TEST_CASE("hub.consul.lifecycle" * doctest::skip()) +static bool +WaitForConsulService(consul::ConsulClient& Client, std::string_view ServiceId, bool ExpectedState, int TimeoutMs) { - zen::consul::ConsulProcess ConsulProc; + Stopwatch Timer; + uint64_t Index = 0; + while (Timer.GetElapsedTimeMs() < static_cast<uint64_t>(TimeoutMs)) + { + uint64_t RemainingMs = static_cast<uint64_t>(TimeoutMs) - Timer.GetElapsedTimeMs(); + int WaitSeconds = std::max(1, static_cast<int>(RemainingMs / 1000)); + if (Client.WatchService(ServiceId, Index, WaitSeconds) == ExpectedState) + { + return true; + } + if (Index == 0) + { + Sleep(100); // error path only: avoid tight loop on persistent connection failure + } + } + return Client.HasService(ServiceId) == ExpectedState; +} + +TEST_CASE("hub.consul.kv") +{ + consul::ConsulProcess ConsulProc; ConsulProc.SpawnConsulAgent(); - zen::consul::ConsulClient Client("http://localhost:8500/"); + consul::ConsulClient Client("http://localhost:8500/"); Client.SetKeyValue("zen/hub/testkey", "testvalue"); std::string RetrievedValue = Client.GetKeyValue("zen/hub/testkey"); @@ -246,6 +269,114 @@ TEST_CASE("hub.consul.lifecycle" * doctest::skip()) ConsulProc.StopConsulAgent(); } +TEST_CASE("hub.consul.hub.registration") +{ + consul::ConsulProcess ConsulProc; + ConsulProc.SpawnConsulAgent(); + + ZenServerInstance Instance(TestEnv, ZenServerInstance::ServerMode::kHubServer); + const uint16_t PortNumber = + Instance.SpawnServerAndWaitUntilReady("--consul-endpoint=http://localhost:8500/ --instance-id=test-instance"); + REQUIRE(PortNumber != 0); + + consul::ConsulClient Client("http://localhost:8500/"); + + REQUIRE(WaitForConsulService(Client, "zen-hub-test-instance", true, 5000)); + + Instance.Shutdown(); + + CHECK(!Client.HasService("zen-hub-test-instance")); + + ConsulProc.StopConsulAgent(); +} + +TEST_CASE("hub.consul.provision.registration") +{ + consul::ConsulProcess ConsulProc; + ConsulProc.SpawnConsulAgent(); + + ZenServerInstance Instance(TestEnv, ZenServerInstance::ServerMode::kHubServer); + const uint16_t PortNumber = + Instance.SpawnServerAndWaitUntilReady("--consul-endpoint=http://localhost:8500/ --instance-id=test-instance"); + REQUIRE(PortNumber != 0); + + consul::ConsulClient Client("http://localhost:8500/"); + + REQUIRE(WaitForConsulService(Client, "zen-hub-test-instance", true, 5000)); + + HttpClient HubClient(Instance.GetBaseUri() + "/hub/"); + + HttpClient::Response Result = HubClient.Post("modules/testmod/provision"); + REQUIRE(Result); + + CHECK(Client.HasService("testmod")); + { + const uint16_t ModulePort = Result.AsObject()["port"].AsUInt16(0); + REQUIRE(ModulePort != 0); + + std::string JsonError; + CbFieldIterator ServicesRoot = LoadCompactBinaryFromJson(Client.GetAgentServicesJson(), JsonError); + REQUIRE(JsonError.empty()); + + CbObjectView ServicesMap; + for (CbFieldView F : ServicesRoot) + { + if (F.IsObject()) + { + ServicesMap = F.AsObjectView(); + } + } + REQUIRE(ServicesMap); + + // Verify fields registered by OnProvisioned + { + CbObjectView ModService = ServicesMap["testmod"].AsObjectView(); + CHECK_EQ(ModService["ID"sv].AsString(), "testmod"sv); + CHECK_EQ(ModService["Service"sv].AsString(), "zen-storage"sv); + CHECK_EQ(ModService["Port"sv].AsDouble(0), double(ModulePort)); + bool FoundModuleTag = false; + bool FoundHubTag = false; + bool FoundVersionTag = false; + for (CbFieldView Tag : ModService["Tags"].AsArrayView()) + { + std::string_view TagStr = Tag.AsString(); + if (TagStr == "module:testmod"sv) + { + FoundModuleTag = true; + } + else if (TagStr == "zen-hub:zen-hub-test-instance"sv) + { + FoundHubTag = true; + } + else if (TagStr.substr(0, 8) == "version:"sv) + { + FoundVersionTag = true; + } + } + CHECK(FoundModuleTag); + CHECK(FoundHubTag); + CHECK(FoundVersionTag); + } + + // Verify fields registered by InitializeConsulRegistration + { + CbObjectView HubService = ServicesMap["zen-hub-test-instance"].AsObjectView(); + CHECK_EQ(HubService["ID"sv].AsString(), "zen-hub-test-instance"sv); + CHECK_EQ(HubService["Service"sv].AsString(), "zen-hub"sv); + CHECK_EQ(HubService["Port"sv].AsDouble(0), double(PortNumber)); + } + } + + Result = HubClient.Post("modules/testmod/deprovision"); + REQUIRE(Result); + + CHECK(!Client.HasService("testmod")); + + Instance.Shutdown(); + + ConsulProc.StopConsulAgent(); +} + TEST_SUITE_END(); } // namespace zen::tests::hub |