blob: a3a770fe7ef76ec5614735ae4d59bdb94c410e27 [file] [log] [blame]
// Copyright 2019 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.
// Check that the test runs in a nested environment named "environment_name".
#include <lib/zx/job.h>
#include <lib/zx/object.h>
#include <lib/zx/process.h>
#include <src/lib/fxl/logging.h>
#include <task-utils/walker.h>
#include <zircon/status.h>
#include <string>
// Helper program to be executed as a benchmark. Verifies that it is executed
// under the nested environment created in trace record and returns with
// EXIT_SUCCESS if it is the case. Otherwise, returns with EXIT_FAILURE.
//
// The expected structure of jobs is:
// j:... environment_name # the job for the test environment
// j:... # the default job for this package
namespace {
// The name of the environment under which this trace benchmark will be
// executed. It is defined in nested_environment_test.tspec.
const char kEnvironmentName[] = "environment_name";
// A |TaskEnumerator| used to find the trace environment.
//
// After calling |WalkRootJobTree()| or |WalkJobTree()| the iteration will stop
// with status:
// - ZX_ERR_STOP if trace environment koid (given in the constructor) was
// successfully found and the name matched the expected one.
// - ZX_OK if the given koid was not found.
// - ZX_ERR_BAD_STATE if the koid was found, but didn't match the expected one.
class Walker final : public TaskEnumerator {
public:
// Creates a new Walker. |trace_env_koid| is the koid the trace environment's
// job is expected to have.
Walker(zx_koid_t trace_env_koid) : trace_env_koid_(trace_env_koid) {}
~Walker() = default;
// TaskEnumerator:
zx_status_t OnJob(int /*depth*/, zx_handle_t task, zx_koid_t koid,
zx_koid_t /*parent_koid*/) override {
if (koid != trace_env_koid_) {
return ZX_OK;
}
char task_name[ZX_MAX_NAME_LEN];
FXL_CHECK(zx::unowned<zx::job>(task)->get_property(
ZX_PROP_NAME, task_name, ZX_MAX_NAME_LEN) == ZX_OK);
std::string name(task_name);
if (name == kEnvironmentName) {
// The test finished successfully: the current task was the expected koid
// and name. Stop the iteration over the jobs and processes by returning a
// status different than ZK_OK.
return ZX_ERR_STOP;
}
// The koid was found, but doesn't correspond to the trace environment. Quit
// with an error.
FXL_LOG(ERROR) << "Expected to find " << kEnvironmentName
<< " as the parent process. Instead found: " << name;
return ZX_ERR_BAD_STATE;
}
protected:
// TaskEnumerator:
bool has_on_job() const override { return true; }
private:
zx_koid_t trace_env_koid_;
};
} // namespace
int main(int argc, char* argv[]) {
zx_info_handle_basic_t info;
zx_status_t status = zx::job::default_job()->get_info(
ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Failed to get default job's information.";
return EXIT_FAILURE;
}
// |info.related_koid| is the koid of the default job's parent object. The
// Walker will use this koid to verify that it corresponds to the nested
// environment.
zx_koid_t trace_env_koid = info.related_koid;
Walker walker(trace_env_koid);
status = walker.WalkRootJobTree();
if (status == ZX_OK) {
FXL_LOG(ERROR) << "Failed to find parent job with koid " << trace_env_koid;
return EXIT_FAILURE;
}
if (status == ZX_ERR_BAD_STATE) {
return EXIT_FAILURE;
}
FXL_CHECK(status == ZX_ERR_STOP) << status;
return EXIT_SUCCESS;
}