/// /// 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 /// #include #include "run.h" #include "log.h" #include "context.h" #include "conf.h" #include "tempdir.h" class RunTest : public testing::Test { protected: RunTest() : testing::Test(), context(std::make_shared()), 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 context; 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, context, *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, context, *tmp.fs); runAll(); EXPECT_EQ(RunState::SUCCESS, run.result); } TEST_F(RunTest, FailedStatus) { setRunLink("false"); run.configure(1, context, *tmp.fs); runAll(); EXPECT_EQ(RunState::FAILED, run.result); } TEST_F(RunTest, Environment) { setRunLink("env"); run.configure(1234, context, *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, context, *tmp.fs); runAll(); StringMap map = parseFromString(readAllOutput()); EXPECT_EQ("bar", map["foo"]); } TEST_F(RunTest, Abort) { setRunLink("yes"); run.configure(1, context, *tmp.fs); run.step(); usleep(200); // TODO fix run.abort(false); wait(); EXPECT_EQ(RunState::ABORTED, run.result); }