blob: befc41720846c47e055c42684b390fb54a2ee011 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "spec_fixture.h"
#include "spec_utils.h"
#include <benchmark/benchmark.h>
#include <fcntl.h>
#include <fstream>
#include <glog/logging.h>
#include <launchpad/launchpad.h>
#include <magenta/syscalls.h>
#include <magenta/syscalls/object.h>
#include <sys/stat.h>
#include <unistd.h>
extern std::string executableDir;
extern std::string tmpDir;
extern std::ofstream result;
namespace {
class ScopedGuard {
public:
explicit ScopedGuard(std::function<void()> f) : f_(f) {}
~ScopedGuard() noexcept { f_(); }
ScopedGuard(const ScopedGuard&) = delete;
ScopedGuard(ScopedGuard&&) = delete;
ScopedGuard& operator=(const ScopedGuard&) = delete;
ScopedGuard& operator=(ScopedGuard&&) = delete;
private:
std::function<void()> f_;
};
} // namespace
void SpecFixture::SetUp(benchmark::State& st) {
DLOG(INFO) << "Preparing benchmark: " << benchmark_name;
run_dir_name = tmpDir + "/" + benchmark_name;
DLOG(INFO) << "Changing dir to: " << executableDir.c_str();
CHECK_EQ(chdir(executableDir.c_str()), 0) << "Not able to change dir to "
<< executableDir;
CHECK_EQ(mkdir(run_dir_name.c_str(), 0600), 0)
<< "Not able to create dir: " << run_dir_name
<< ", Error: " << strerror(errno);
CHECK_EQ(CopyDir(run_dir_name, "data/" + benchmark_name), 0)
<< "Error copying dir: " << run_dir_name
<< ", Error: " << strerror(errno);
CHECK_EQ(CopyFile(run_dir_name + "/" + benchmark_name, benchmark_name), 0)
<< "Error copying binary, Error: " << strerror(errno);
}
void SpecFixture::TearDown(benchmark::State& st) {
CHECK_EQ(DeleteDir(run_dir_name), 0) << "Error Deleting directory "
<< run_dir_name
<< ", Error: " << strerror(errno);
}
int SpecFixture::RunSpec(const char* args[], int args_length) {
char** argv = new char*[args_length + 1];
argv[0] = (char*)(benchmark_name.c_str());
if (args_length > 0) {
memcpy(argv + 1, args, args_length * sizeof(char*));
}
if (chdir(run_dir_name.c_str()) != 0) {
LOG(ERROR) << "Not able to change dir to " << run_dir_name
<< ", Error: " << strerror(errno);
return errno;
}
DLOG(INFO) << "Running benchmark";
// Capture output
char buffer[PAGE_SIZE];
int out_p[2];
int old_stdout = dup(STDOUT_FILENO);
if (pipe2(out_p, O_NONBLOCK) != 0) {
LOG(ERROR) << "Not able create pipe, Error: " << strerror(errno);
return errno;
}
ScopedGuard guard([&]() { close(out_p[0]); });
dup2(out_p[1], STDOUT_FILENO);
close(out_p[1]);
int status = LaunchProcess(argv, args_length + 1);
fflush(stdout);
dup2(old_stdout, STDOUT_FILENO);
if (chdir(executableDir.c_str()) != 0) {
LOG(ERROR) << "Not able to change dir to " << executableDir
<< ", Error: " << strerror(errno);
return errno;
}
delete[] argv;
if (status != 0) {
// Dump output
LOG(ERROR) << "Error while running benchmark";
ssize_t len;
do {
len = read(out_p[0], buffer, PAGE_SIZE);
if (len == -1) {
LOG(ERROR) << "Error reading from pipe, Error: " << strerror(errno);
return errno;
}
fwrite(buffer, sizeof(char), len, stderr);
} while (len == PAGE_SIZE);
fprintf(stderr, "\n");
return 1;
}
return 0;
}
// TODO: This is for fuchsia, need to write linux specific
#ifdef __Fuchsia__
int SpecFixture::LaunchProcess(char** args, int args_length) {
mx_handle_t handle = launchpad_launch_mxio(args[0], args_length, args);
if (handle < 0) {
LOG(ERROR) << "Failed to launch " << args[0] << ":" << handle;
return handle;
}
mx_status_t status =
mx_handle_wait_one(handle, MX_SIGNAL_SIGNALED, MX_TIME_INFINITE, NULL);
if (status != NO_ERROR) {
LOG(ERROR) << "Failed to wait for process exiting " << args[0] << ":"
<< status;
return status;
}
mx_info_process_t proc_info;
ssize_t info_status = mx_object_get_info(handle, MX_INFO_PROCESS, &proc_info,
sizeof(proc_info), NULL, NULL);
mx_handle_close(handle);
if (info_status < 0) {
LOG(ERROR) << "Failed to get process return code " << args[0] << ":"
<< info_status;
return 1;
}
return proc_info.return_code;
}
#endif