mirror of
https://github.com/ohwgiles/laminar.git
synced 2024-10-27 20:34:20 +00:00
157 lines
5.7 KiB
C++
157 lines
5.7 KiB
C++
///
|
|
/// 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/>
|
|
///
|
|
#ifndef LAMINAR_FIXTURE_H_
|
|
#define LAMINAR_FIXTURE_H_
|
|
|
|
#include "laminar.capnp.h"
|
|
#include "eventsource.h"
|
|
#include "tempdir.h"
|
|
#include "laminar.h"
|
|
#include "log.h"
|
|
#include "server.h"
|
|
#include "conf.h"
|
|
|
|
#include <capnp/rpc-twoparty.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
class LaminarFixture : public ::testing::Test {
|
|
public:
|
|
LaminarFixture() {
|
|
home = tmp.path.toString(true).cStr();
|
|
bind_rpc = std::string("unix:/") + home + "/rpc.sock";
|
|
bind_http = std::string("unix:/") + home + "/http.sock";
|
|
settings.home = home.c_str();
|
|
settings.bind_rpc = bind_rpc.c_str();
|
|
settings.bind_http = bind_http.c_str();
|
|
settings.archive_url = "/test-archive/";
|
|
}
|
|
~LaminarFixture() noexcept(true) {}
|
|
|
|
void SetUp() override {
|
|
tmp.init();
|
|
server = new Server(*ioContext);
|
|
laminar = new Laminar(*server, settings);
|
|
}
|
|
|
|
void TearDown() override {
|
|
delete server;
|
|
delete laminar;
|
|
tmp.clean();
|
|
}
|
|
|
|
kj::Own<EventSource> eventSource(const char* path) {
|
|
return kj::heap<EventSource>(*ioContext, bind_http.c_str(), path);
|
|
}
|
|
|
|
void defineJob(const char* name, const char* scriptContent, const char* configContent = nullptr) {
|
|
KJ_IF_MAYBE(f, tmp.fs->tryOpenFile(kj::Path{"cfg", "jobs", std::string(name) + ".run"},
|
|
kj::WriteMode::CREATE | kj::WriteMode::CREATE_PARENT | kj::WriteMode::EXECUTABLE)) {
|
|
(*f)->writeAll(std::string("#!/bin/sh\n") + scriptContent + "\n");
|
|
}
|
|
if(configContent) {
|
|
KJ_IF_MAYBE(f, tmp.fs->tryOpenFile(kj::Path{"cfg", "jobs", std::string(name) + ".conf"}, kj::WriteMode::CREATE)) {
|
|
(*f)->writeAll(configContent);
|
|
}
|
|
}
|
|
}
|
|
|
|
struct RunExec {
|
|
LaminarCi::JobResult result;
|
|
kj::String log;
|
|
};
|
|
|
|
RunExec runJob(const char* name, kj::Maybe<StringMap> params = nullptr) {
|
|
auto req = client().runRequest();
|
|
req.setJobName(name);
|
|
KJ_IF_MAYBE(p, params) {
|
|
auto params = req.initParams(p->size());
|
|
int i = 0;
|
|
for(auto kv : *p) {
|
|
params[i].setName(kv.first);
|
|
params[i].setValue(kv.second);
|
|
i++;
|
|
}
|
|
}
|
|
auto res = req.send().wait(ioContext->waitScope);
|
|
std::string path = std::string{"/log/"} + name + "/" + std::to_string(res.getBuildNum());
|
|
kj::HttpHeaderTable headerTable;
|
|
kj::String log = kj::newHttpClient(ioContext->lowLevelProvider->getTimer(), headerTable,
|
|
*ioContext->provider->getNetwork().parseAddress(bind_http.c_str()).wait(ioContext->waitScope))
|
|
->request(kj::HttpMethod::GET, path, kj::HttpHeaders(headerTable)).response.wait(ioContext->waitScope).body
|
|
->readAllText().wait(ioContext->waitScope);
|
|
return { res.getResult(), kj::mv(log) };
|
|
}
|
|
|
|
void setNumExecutors(int nexec) {
|
|
KJ_IF_MAYBE(f, tmp.fs->tryOpenFile(kj::Path{"cfg", "contexts", "default.conf"},
|
|
kj::WriteMode::CREATE | kj::WriteMode::MODIFY | kj::WriteMode::CREATE_PARENT)) {
|
|
std::string content = "EXECUTORS=" + std::to_string(nexec);
|
|
(*f)->writeAll(content);
|
|
}
|
|
}
|
|
|
|
kj::String stripLaminarLogLines(const kj::String& str) {
|
|
auto out = kj::heapString(str.size());
|
|
char *o = out.begin();
|
|
for(const char *p = str.cStr(), *e = p + str.size(); p < e;) {
|
|
const char *nl = strchrnul(p, '\n');
|
|
if(!kj::StringPtr{p}.startsWith("[laminar]")) {
|
|
memcpy(o, p, nl - p + 1);
|
|
o += nl - p + 1;
|
|
}
|
|
p = nl + 1;
|
|
}
|
|
*o = '\0';
|
|
return out;
|
|
}
|
|
|
|
StringMap parseFromString(kj::StringPtr content) {
|
|
char tmp[16] = "/tmp/lt.XXXXXX";
|
|
int fd = mkstemp(tmp);
|
|
LSYSCALL(write(fd, content.begin(), content.size()));
|
|
close(fd);
|
|
StringMap map = parseConfFile(tmp);
|
|
unlink(tmp);
|
|
return map;
|
|
}
|
|
|
|
LaminarCi::Client client() {
|
|
if(!rpc) {
|
|
auto stream = ioContext->provider->getNetwork().parseAddress(bind_rpc).wait(ioContext->waitScope)->connect().wait(ioContext->waitScope);
|
|
auto net = kj::heap<capnp::TwoPartyVatNetwork>(*stream, capnp::rpc::twoparty::Side::CLIENT);
|
|
rpc = kj::heap<capnp::RpcSystem<capnp::rpc::twoparty::VatId>>(*net, nullptr).attach(kj::mv(net), kj::mv(stream));
|
|
}
|
|
static capnp::word scratch[4];
|
|
memset(scratch, 0, sizeof(scratch));
|
|
auto hostId = capnp::MallocMessageBuilder(scratch).getRoot<capnp::rpc::twoparty::VatId>();
|
|
hostId.setSide(capnp::rpc::twoparty::Side::SERVER);
|
|
return rpc->bootstrap(hostId).castAs<LaminarCi>();
|
|
}
|
|
|
|
kj::Own<capnp::RpcSystem<capnp::rpc::twoparty::VatId>> rpc;
|
|
TempDir tmp;
|
|
std::string home, bind_rpc, bind_http;
|
|
Settings settings;
|
|
Server* server;
|
|
Laminar* laminar;
|
|
static kj::AsyncIoContext* ioContext;
|
|
};
|
|
|
|
#endif // LAMINAR_FIXTURE_H_
|