mirror of
https://github.com/ohwgiles/laminar.git
synced 2024-10-27 20:34:20 +00:00
39ca7e86cf
Large refactor that more closely aligns the codebase to the kj async style, more clearly exposes an interface for functional testing and removes cruft. There is a slight increase in coupling between the Laminar and Http/Rpc classes, but this was always an issue, just until now more obscured by the arbitrary pure virtual LaminarInterface class (which has been removed in this change) and the previous lumping together of all the async stuff in the Server class (which is now more spread around the code according to function). This change replaces the use of Websockets with Server Side Events (SSE). They are simpler and more suitable for the publish-style messages used by Laminar, and typically require less configuration of the reverse proxy HTTP server. Use of gmock is also removed, which eases testing in certain envs. Resolves #90.
137 lines
3.8 KiB
C++
137 lines
3.8 KiB
C++
///
|
|
/// Copyright 2018 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 <gtest/gtest.h>
|
|
#include "run.h"
|
|
#include "log.h"
|
|
#include "node.h"
|
|
#include "conf.h"
|
|
#include "tempdir.h"
|
|
|
|
class RunTest : public testing::Test {
|
|
protected:
|
|
RunTest() :
|
|
testing::Test(),
|
|
node(std::make_shared<Node>()),
|
|
tmp(),
|
|
run("foo", ParamMap{}, tmp.path.clone())
|
|
{
|
|
}
|
|
|
|
~RunTest() noexcept {}
|
|
|
|
void wait() {
|
|
int state = -1;
|
|
waitpid(run.current_pid.orDefault(0), &state, 0);
|
|
run.reaped(state);
|
|
}
|
|
|
|
void runAll() {
|
|
while(!run.step())
|
|
wait();
|
|
}
|
|
|
|
std::string readAllOutput() {
|
|
std::string res;
|
|
char tmp[64];
|
|
for(ssize_t n = read(run.output_fd, tmp, 64); n > 0; n = read(run.output_fd, tmp, 64))
|
|
res += std::string(tmp, n);
|
|
// strip the first "[laminar] executing.. line
|
|
return strchr(res.c_str(), '\n') + 1;
|
|
}
|
|
StringMap parseFromString(std::string content) {
|
|
char tmp[16] = "/tmp/lt.XXXXXX";
|
|
int fd = mkstemp(tmp);
|
|
write(fd, content.data(), content.size());
|
|
close(fd);
|
|
StringMap map = parseConfFile(tmp);
|
|
unlink(tmp);
|
|
return map;
|
|
}
|
|
|
|
std::shared_ptr<Node> node;
|
|
TempDir tmp;
|
|
class Run run;
|
|
|
|
void setRunLink(const char * path) {
|
|
KJ_IF_MAYBE(f, tmp.fs->tryOpenFile(kj::Path{"cfg", "jobs", run.name + ".run"},
|
|
kj::WriteMode::CREATE | kj::WriteMode::CREATE_PARENT | kj::WriteMode::EXECUTABLE)) {
|
|
(f->get())->writeAll(std::string("#!/bin/sh\nexec ") + path + "\n");
|
|
}
|
|
}
|
|
};
|
|
|
|
TEST_F(RunTest, WorkingDirectory) {
|
|
setRunLink("pwd");
|
|
run.configure(1, node, *tmp.fs);
|
|
runAll();
|
|
std::string cwd{tmp.path.append(kj::Path{"run","foo","1"}).toString(true).cStr()};
|
|
EXPECT_EQ(cwd + "\n", readAllOutput());
|
|
}
|
|
|
|
TEST_F(RunTest, SuccessStatus) {
|
|
setRunLink("true");
|
|
run.configure(1, node, *tmp.fs);
|
|
runAll();
|
|
EXPECT_EQ(RunState::SUCCESS, run.result);
|
|
}
|
|
|
|
TEST_F(RunTest, FailedStatus) {
|
|
setRunLink("false");
|
|
run.configure(1, node, *tmp.fs);
|
|
runAll();
|
|
EXPECT_EQ(RunState::FAILED, run.result);
|
|
}
|
|
|
|
TEST_F(RunTest, Environment) {
|
|
setRunLink("env");
|
|
run.configure(1234, node, *tmp.fs);
|
|
runAll();
|
|
|
|
std::string ws{tmp.path.append(kj::Path{"run","foo","workspace"}).toString(true).cStr()};
|
|
std::string archive{tmp.path.append(kj::Path{"archive","foo","1234"}).toString(true).cStr()};
|
|
|
|
StringMap map = parseFromString(readAllOutput());
|
|
EXPECT_EQ("1234", 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(RunTest, ParamsToEnv) {
|
|
setRunLink("env");
|
|
run.params["foo"] = "bar";
|
|
run.configure(1, node, *tmp.fs);
|
|
runAll();
|
|
StringMap map = parseFromString(readAllOutput());
|
|
EXPECT_EQ("bar", map["foo"]);
|
|
}
|
|
|
|
TEST_F(RunTest, Abort) {
|
|
setRunLink("yes");
|
|
run.configure(1, node, *tmp.fs);
|
|
run.step();
|
|
usleep(200); // TODO fix
|
|
run.abort(false);
|
|
wait();
|
|
EXPECT_EQ(RunState::ABORTED, run.result);
|
|
}
|
|
|