File indexing completed on 2026-10-20 08:45:57
0001 #include <cassert>
0002 #include <cstdint>
0003 #include <cstdlib>
0004 #include <filesystem>
0005 #include <string>
0006 #include <sys/wait.h>
0007 #include <unistd.h>
0008
0009 #include "NPFold.h"
0010
0011 namespace
0012 {
0013 namespace fs = std::filesystem;
0014
0015 fs::path TestDirectory()
0016 {
0017 return fs::temp_directory_path() /
0018 ("sleak_test-" + std::to_string(static_cast<long long>(::getpid())));
0019 }
0020
0021 void SaveInputFold(const fs::path& directory)
0022 {
0023 NPFold fold;
0024 fold.add("run", NP::Make<std::int64_t>(1, 1));
0025 fold.save(directory.c_str());
0026 }
0027
0028 void RunSleak(
0029 const fs::path& executable,
0030 const fs::path& input,
0031 const fs::path& output,
0032 const fs::path& profile = {})
0033 {
0034 std::string command =
0035 "SLEAK_FOLD='" + output.string() + "' '" + executable.string() +
0036 "' '" + input.string() + "'";
0037 if (!profile.empty())
0038 command += " --event-timing-profile '" + profile.string() + "'";
0039 command += " >/dev/null 2>&1";
0040 const int status = std::system(command.c_str());
0041 assert(status != -1);
0042 assert(WIFEXITED(status));
0043 assert(WEXITSTATUS(status) == 0);
0044 }
0045
0046 void TestRealProfileIsSerialized(
0047 const fs::path& executable,
0048 const fs::path& fixture,
0049 const fs::path& directory)
0050 {
0051 const fs::path input = directory / "profiled-input";
0052 const fs::path output = directory / "profiled-output";
0053 const fs::path profile_path = input / "custom-profile.csv";
0054 SaveInputFold(input);
0055 fs::copy_file(fixture, profile_path);
0056
0057 RunSleak(executable, input, output, profile_path);
0058
0059 NPFold* result = NPFold::Load(output.c_str());
0060 assert(result);
0061 const NP* profile = result->get("runprof");
0062 assert(profile);
0063 assert(profile->shape.size() == 2u);
0064 assert(profile->shape[0] == 15);
0065 assert(profile->shape[1] == 4);
0066 assert(profile->names.size() == 15u);
0067 assert(profile->names.front() == "EventTimingProfile__Configure");
0068 assert(profile->cvalues<std::int64_t>()[1] == 900'000'000);
0069 delete result;
0070 }
0071
0072 void TestMissingProfileIsOmitted(
0073 const fs::path& executable,
0074 const fs::path& directory)
0075 {
0076 const fs::path input = directory / "unprofiled-input";
0077 const fs::path output = directory / "unprofiled-output";
0078 SaveInputFold(input);
0079
0080 RunSleak(executable, input, output);
0081
0082 NPFold* result = NPFold::Load(output.c_str());
0083 assert(result);
0084 assert(result->get("run"));
0085 assert(result->get("runprof") == nullptr);
0086 delete result;
0087 }
0088 }
0089
0090 int main(int argc, char** argv)
0091 {
0092 assert(argc == 3);
0093 const fs::path executable = argv[1];
0094 const fs::path fixture = argv[2];
0095 const fs::path directory = TestDirectory();
0096 fs::remove_all(directory);
0097 fs::create_directories(directory);
0098
0099 TestRealProfileIsSerialized(executable, fixture, directory);
0100 TestMissingProfileIsOmitted(executable, directory);
0101
0102 fs::remove_all(directory);
0103 return 0;
0104 }