1
0
mirror of https://github.com/ohwgiles/laminar.git synced 2024-10-27 20:34:20 +00:00
ohwgiles_laminar/test/laminar-functional.cpp

189 lines
6.7 KiB
C++
Raw Normal View History

///
/// Copyright 2019-2022 Oliver Giles
///
/// This file is part of Laminar
///
/// Laminar is free software: you can redistribute it and/or modify
/// it under the terms of the GNU General Public License as published by
/// the Free Software Foundation, either version 3 of the License, or
/// (at your option) any later version.
///
/// Laminar is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU General Public License for more details.
///
/// You should have received a copy of the GNU General Public License
/// along with Laminar. If not, see <http://www.gnu.org/licenses/>
///
#include <kj/async-unix.h>
#include "laminar-fixture.h"
#include "conf.h"
// TODO: consider handling this differently
kj::AsyncIoContext* LaminarFixture::ioContext;
TEST_F(LaminarFixture, EmptyStatusMessageStructure) {
auto es = eventSource("/");
ioContext->waitScope.poll();
ASSERT_EQ(1, es->messages().size());
auto json = es->messages().front().GetObject();
EXPECT_STREQ("status", json["type"].GetString());
EXPECT_STREQ("Laminar", json["title"].GetString());
EXPECT_LT(time(nullptr) - json["time"].GetInt64(), 1);
auto data = json["data"].GetObject();
EXPECT_TRUE(data.HasMember("recent"));
EXPECT_TRUE(data.HasMember("running"));
EXPECT_TRUE(data.HasMember("queued"));
EXPECT_TRUE(data.HasMember("executorsTotal"));
EXPECT_TRUE(data.HasMember("executorsBusy"));
EXPECT_TRUE(data.HasMember("buildsPerDay"));
EXPECT_TRUE(data.HasMember("buildsPerJob"));
EXPECT_TRUE(data.HasMember("timePerJob"));
EXPECT_TRUE(data.HasMember("resultChanged"));
EXPECT_TRUE(data.HasMember("lowPassRates"));
EXPECT_TRUE(data.HasMember("buildTimeChanges"));
}
TEST_F(LaminarFixture, JobNotifyHomePage) {
defineJob("foo", "true");
auto es = eventSource("/");
runJob("foo");
ASSERT_EQ(4, es->messages().size());
auto job_queued = es->messages().at(1).GetObject();
EXPECT_STREQ("job_queued", job_queued["type"].GetString());
EXPECT_STREQ("foo", job_queued["data"]["name"].GetString());
auto job_started = es->messages().at(2).GetObject();
EXPECT_STREQ("job_started", job_started["type"].GetString());
EXPECT_STREQ("foo", job_started["data"]["name"].GetString());
auto job_completed = es->messages().at(3).GetObject();
EXPECT_STREQ("job_completed", job_completed["type"].GetString());
EXPECT_STREQ("foo", job_completed["data"]["name"].GetString());
}
TEST_F(LaminarFixture, OnlyRelevantNotifications) {
defineJob("job1", "true");
defineJob("job2", "true");
auto esHome = eventSource("/");
auto esJobs = eventSource("/jobs");
auto es1Job = eventSource("/jobs/job1");
auto es2Job = eventSource("/jobs/job2");
auto es1Run = eventSource("/jobs/job1/1");
auto es2Run = eventSource("/jobs/job2/1");
runJob("job1");
runJob("job2");
EXPECT_EQ(7, esHome->messages().size());
EXPECT_EQ(7, esJobs->messages().size());
EXPECT_EQ(4, es1Job->messages().size());
EXPECT_EQ(4, es2Job->messages().size());
EXPECT_EQ(4, es1Run->messages().size());
EXPECT_EQ(4, es2Run->messages().size());
}
TEST_F(LaminarFixture, FailedStatus) {
defineJob("job1", "false");
auto run = runJob("job1");
ASSERT_EQ(LaminarCi::JobResult::FAILED, run.result);
}
TEST_F(LaminarFixture, WorkingDirectory) {
defineJob("job1", "pwd");
auto run = runJob("job1");
ASSERT_EQ(LaminarCi::JobResult::SUCCESS, run.result);
std::string cwd{tmp.path.append(kj::Path{"run","job1","1"}).toString(true).cStr()};
EXPECT_EQ(cwd + "\n", stripLaminarLogLines(run.log).cStr());
}
TEST_F(LaminarFixture, Environment) {
defineJob("foo", "env");
auto run = runJob("foo");
std::string ws{tmp.path.append(kj::Path{"run","foo","workspace"}).toString(true).cStr()};
std::string archive{tmp.path.append(kj::Path{"archive","foo","1"}).toString(true).cStr()};
StringMap map = parseFromString(run.log);
EXPECT_EQ("1", map["RUN"]);
EXPECT_EQ("foo", map["JOB"]);
EXPECT_EQ("success", map["RESULT"]);
EXPECT_EQ("unknown", map["LAST_RESULT"]);
EXPECT_EQ(ws, map["WORKSPACE"]);
EXPECT_EQ(archive, map["ARCHIVE"]);
}
TEST_F(LaminarFixture, ParamsToEnv) {
defineJob("foo", "env");
StringMap params;
params["foo"] = "bar";
auto run = runJob("foo", params);
StringMap map = parseFromString(run.log);
EXPECT_EQ("bar", map["foo"]);
}
TEST_F(LaminarFixture, Abort) {
defineJob("job1", "sleep inf");
auto req = client().runRequest();
req.setJobName("job1");
auto res = req.send();
// There isn't a nice way of knowing when the leader process is ready to
// handle SIGTERM. Just wait until it prints something to the log
ioContext->waitScope.poll();
kj::HttpHeaderTable headerTable;
char _;
kj::newHttpClient(ioContext->lowLevelProvider->getTimer(), headerTable,
*ioContext->provider->getNetwork().parseAddress(bind_http.c_str()).wait(ioContext->waitScope))
->request(kj::HttpMethod::GET, "/log/job1/1", kj::HttpHeaders(headerTable)).response.wait(ioContext->waitScope).body
->tryRead(&_, 1, 1).wait(ioContext->waitScope);
// now it should be ready to abort
ASSERT_TRUE(laminar->abort("job1", 1));
EXPECT_EQ(LaminarCi::JobResult::ABORTED, res.wait(ioContext->waitScope).getResult());
}
TEST_F(LaminarFixture, JobDescription) {
defineJob("foo", "true", "DESCRIPTION=bar");
auto es = eventSource("/jobs/foo");
ioContext->waitScope.poll();
ASSERT_EQ(1, es->messages().size());
auto json = es->messages().front().GetObject();
ASSERT_TRUE(json.HasMember("data"));
auto data = json["data"].GetObject();
ASSERT_TRUE(data.HasMember("description"));
EXPECT_STREQ("bar", data["description"].GetString());
}
TEST_F(LaminarFixture, QueueFront) {
setNumExecutors(0);
defineJob("foo", "true");
defineJob("bar", "true");
auto es = eventSource("/");
auto req1 = client().queueRequest();
req1.setJobName("foo");
auto res1 = req1.send();
auto req2 = client().queueRequest();
req2.setFrontOfQueue(true);
req2.setJobName("bar");
auto res2 = req2.send();
ioContext->waitScope.poll();
setNumExecutors(2);
ioContext->waitScope.poll();
ASSERT_GE(es->messages().size(), 5);
auto started1 = es->messages().at(3).GetObject();
EXPECT_STREQ("job_started", started1["type"].GetString());
EXPECT_STREQ("bar", started1["data"]["name"].GetString());
auto started2 = es->messages().at(4).GetObject();
EXPECT_STREQ("job_started", started2["type"].GetString());
EXPECT_STREQ("foo", started2["data"]["name"].GetString());
}