diff options
| author | Stefan Boberg <[email protected]> | 2021-06-18 15:43:58 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2021-06-18 15:43:58 +0200 |
| commit | 8d4e57692725dd76c82137577eedfc459cb959f4 (patch) | |
| tree | 749c6863edfe60ed72af7fc07e626f659fdac4d6 /zenserver-test/zenserver-test.cpp | |
| parent | Added ZenTestEnvironment::RootDir to construct a path to a subdirectory in th... (diff) | |
| download | zen-8d4e57692725dd76c82137577eedfc459cb959f4.tar.xz zen-8d4e57692725dd76c82137577eedfc459cb959f4.zip | |
Improved some logging in test harness, added launcher test
Diffstat (limited to 'zenserver-test/zenserver-test.cpp')
| -rw-r--r-- | zenserver-test/zenserver-test.cpp | 175 |
1 files changed, 174 insertions, 1 deletions
diff --git a/zenserver-test/zenserver-test.cpp b/zenserver-test/zenserver-test.cpp index 114c3e86b..187566d44 100644 --- a/zenserver-test/zenserver-test.cpp +++ b/zenserver-test/zenserver-test.cpp @@ -660,7 +660,7 @@ main(int argc, char** argv) TestEnv.Initialize(ProgramBaseDir, TestBaseDir); - spdlog::info("Running tests..."); + spdlog::info("Running tests...(base dir: '{}')", TestBaseDir); return doctest::Context(argc, argv).run(); } @@ -1177,4 +1177,177 @@ TEST_CASE("z$.basic") } } +struct RemoteExecutionRequest +{ + RemoteExecutionRequest(std::string_view Host, int Port, std::filesystem::path& TreePath) + : m_HostName(Host) + , m_PortNumber(Port) + , m_TreePath(TreePath) + { + } + + void Build(std::string_view Command, std::string_view Arguments) + { + zen::FileSystemTraversal Traversal; + Traversal.TraverseFileSystem(m_TreePath, m_Visit); + + zen::CbObjectWriter PrepReq; + + PrepReq << "cmd" + << Command; + PrepReq << "args" + << Arguments; + + PrepReq.BeginArray("files"); + + for (const auto& Kv : m_Visit.m_Files) + { + PrepReq.BeginObject(); + PrepReq << "file" << zen::WideToUtf8(Kv.first) << "size" << Kv.second.Size << "hash" << Kv.second.Hash; + PrepReq.EndObject(); + } + PrepReq.EndArray(); + + zen::BinaryWriter MemWriter(m_MemOut); + PrepReq.Save(MemWriter); + } + + void Prep() + { + cpr::Response Response = cpr::Post(cpr::Url("{}/prep"_format(m_BaseUri)), cpr::Body((const char*)m_MemOut.Data(), m_MemOut.Size())); + + if (Response.status_code < 300) + { + zen::IoBuffer Payload(zen::IoBuffer::Clone, Response.text.data(), Response.text.size()); + zen::CbObject Result = zen::LoadCompactBinaryObject(Payload); + + for (auto& Need : Result["need"]) + { + zen::IoHash NeedHash = Need.AsHash(); + + if (auto It = m_Visit.m_HashToFile.find(NeedHash); It != m_Visit.m_HashToFile.end()) + { + zen::IoBuffer FileData = zen::IoBufferBuilder::MakeFromFile(It->second.c_str()); + + cpr::Response CasResponse = cpr::Post(cpr::Url(m_CasUri), cpr::Body((const char*)FileData.Data(), FileData.Size())); + + if (CasResponse.status_code >= 300) + { + spdlog::error("CAS put failed with {}", CasResponse.status_code); + } + } + else + { + spdlog::error("unknown hash in 'need' list: {}", NeedHash); + } + } + } + } + + zen::CbObject Exec() + { + cpr::Response JobResponse = cpr::Post(cpr::Url(m_BaseUri), cpr::Body((const char*)m_MemOut.Data(), m_MemOut.Size())); + + if (JobResponse.status_code < 300) + { + zen::IoBuffer Payload(zen::IoBuffer::Clone, JobResponse.text.data(), JobResponse.text.size()); + return zen::LoadCompactBinaryObject(std::move(Payload)); + } + + spdlog::info("job exec: {}", JobResponse.status_code); + return {}; + } + +private: + struct Visitor : public zen::FileSystemTraversal::TreeVisitor + { + const std::filesystem::path& m_RootPath; + + Visitor(const std::filesystem::path& RootPath) : m_RootPath(RootPath) {} + + virtual void VisitFile(const std::filesystem::path& Parent, const std::wstring_view& FileName, uint64_t FileSize) override + { + std::filesystem::path FullPath = Parent / FileName; + + zen::IoHashStream Ios; + zen::ScanFile(FullPath, 64 * 1024, [&](const void* Data, size_t Size) { Ios.Append(Data, Size); }); + zen::IoHash Hash = Ios.GetHash(); + + std::wstring RelativePath = FullPath.lexically_relative(m_RootPath).native(); + // spdlog::info("File: {:32} => {} ({})", zen::WideToUtf8(RelativePath), Hash, FileSize); + + FileEntry& Entry = m_Files[RelativePath]; + Entry.Hash = Hash; + Entry.Size = FileSize; + + m_HashToFile[Hash] = FullPath; + } + + virtual bool VisitDirectory(const std::filesystem::path& Parent, const std::wstring_view& DirectoryName) override + { + std::filesystem::path FullPath = Parent / DirectoryName; + + if (DirectoryName.starts_with(L".")) + { + return false; + } + + return true; + } + + struct FileEntry + { + uint64_t Size; + zen::IoHash Hash; + }; + + std::map<std::wstring, FileEntry> m_Files; + std::unordered_map<zen::IoHash, std::filesystem::path, zen::IoHash::Hasher> m_HashToFile; + }; + + std::string m_HostName; + int m_PortNumber; + std::filesystem::path m_TreePath; + const std::string m_BaseUri = "http://{}:{}/exec/jobs"_format(m_HostName, m_PortNumber); + const std::string m_CasUri = "http://{}:{}/cas"_format(m_HostName, m_PortNumber); + Visitor m_Visit{m_TreePath}; + zen::MemoryOutStream m_MemOut; +}; + +TEST_CASE("exec.basic") +{ + using namespace std::literals; + + std::filesystem::path TestDir = TestEnv.CreateNewTestDir(); + + const uint16_t PortNumber = 13337; + + const int kIterationCount = 100; + + ZenServerInstance Zen1(TestEnv); + Zen1.SetTestDir(TestDir); + Zen1.SpawnServer(PortNumber); + Zen1.WaitUntilReady(); + + std::filesystem::path TreePath = TestEnv.RootDir("test/remote1"); + + { + RemoteExecutionRequest RemoteRequest("localhost", PortNumber, TreePath); + RemoteRequest.Build("zentest-appstub.exe", ""); + RemoteRequest.Prep(); + zen::CbObject Result = RemoteRequest.Exec(); + + CHECK(Result["exitcode"].AsInt32(-1) == 0); + } + + { + RemoteExecutionRequest RemoteRequest("localhost", PortNumber, TreePath); + RemoteRequest.Build("zentest-appstub.exe", "-f=1"); + RemoteRequest.Prep(); + zen::CbObject Result = RemoteRequest.Exec(); + + CHECK(Result["exitcode"].AsInt32(-1) == 1); + } +} + #endif |