1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
// Copyright Epic Games, Inc. All Rights Reserved.
#if ZEN_WITH_TESTS && ZEN_WITH_NOMAD
# include "zenserver-test.h"
# include <zencore/filesystem.h>
# include <zencore/logging.h>
# include <zencore/testing.h>
# include <zencore/timer.h>
# include <zenhttp/httpclient.h>
# include <zennomad/nomadclient.h>
# include <zennomad/nomadprocess.h>
# include <zenutil/zenserverprocess.h>
# include <fmt/format.h>
namespace zen::tests::nomad_tests {
using namespace std::literals;
TEST_SUITE_BEGIN("server.nomad");
TEST_CASE("nomad.client.lifecycle" * doctest::skip())
{
zen::nomad::NomadProcess NomadProc;
NomadProc.SpawnNomadAgent();
zen::nomad::NomadTestClient Client("http://localhost:4646/");
// Submit a simple batch job that sleeps briefly
# if ZEN_PLATFORM_WINDOWS
auto Job = Client.SubmitJob("zen-test-job", "cmd.exe", {"/C", "timeout /t 10 /nobreak"});
# else
auto Job = Client.SubmitJob("zen-test-job", "/bin/sleep", {"10"});
# endif
REQUIRE(!Job.Id.empty());
CHECK_EQ(Job.Status, "pending");
// Poll until the job is running (or dead)
{
Stopwatch Timer;
bool FoundRunning = false;
while (Timer.GetElapsedTimeMs() < 15000)
{
auto Status = Client.GetJobStatus("zen-test-job");
if (Status.Status == "running")
{
FoundRunning = true;
break;
}
if (Status.Status == "dead")
{
break;
}
Sleep(500);
}
CHECK(FoundRunning);
}
// Verify allocations exist
auto Allocs = Client.GetAllocations("zen-test-job");
CHECK(!Allocs.empty());
// Stop the job
Client.StopJob("zen-test-job");
// Verify it reaches dead state
{
Stopwatch Timer;
bool FoundDead = false;
while (Timer.GetElapsedTimeMs() < 10000)
{
auto Status = Client.GetJobStatus("zen-test-job");
if (Status.Status == "dead")
{
FoundDead = true;
break;
}
Sleep(500);
}
CHECK(FoundDead);
}
NomadProc.StopNomadAgent();
}
TEST_CASE("nomad.provisioner.integration" * doctest::skip())
{
zen::nomad::NomadProcess NomadProc;
NomadProc.SpawnNomadAgent();
// Spawn zenserver in compute mode with Nomad provisioning enabled
ZenServerInstance Instance(TestEnv, ZenServerInstance::ServerMode::kComputeServer);
Instance.SetDataDir(TestEnv.CreateNewTestDir());
std::filesystem::path ZenServerPath = TestEnv.ProgramBaseDir() / "zenserver" ZEN_EXE_SUFFIX_LITERAL;
std::string NomadArgs = fmt::format(
"--nomad-enabled=true"
" --nomad-server=http://localhost:4646"
" --nomad-driver=raw_exec"
" --nomad-binary-path={}"
" --nomad-max-cores=32"
" --nomad-cores-per-job=32",
ZenServerPath.string());
const uint16_t Port = Instance.SpawnServerAndWaitUntilReady(NomadArgs);
REQUIRE(Port != 0);
// Give the provisioner time to submit jobs.
// The management thread has a 5s wait between cycles, and the HTTP client has
// a 10s connect timeout, so we need to allow enough time for at least one full cycle.
Sleep(15000);
// Verify jobs were submitted to Nomad
zen::nomad::NomadTestClient NomadClient("http://localhost:4646/");
auto Jobs = NomadClient.ListJobs("zenserver-worker");
ZEN_INFO("nomad.provisioner.integration: found {} jobs with prefix 'zenserver-worker'", Jobs.size());
CHECK_MESSAGE(!Jobs.empty(), Instance.GetLogOutput());
Instance.Shutdown();
NomadProc.StopNomadAgent();
}
TEST_SUITE_END();
} // namespace zen::tests::nomad_tests
#endif
|