blob: e37cc16f51722d8c39e754403238386fc9cde6ce [file] [log] [blame]
/* Copyright 2018 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef RUNTIME_PROBE_FUNCTIONS_SYSFS_H_
#define RUNTIME_PROBE_FUNCTIONS_SYSFS_H_
#include <memory>
#include <string>
#include <vector>
#include <base/files/file_path.h>
#include <base/values.h>
#include <gtest/gtest.h>
#include "runtime_probe/probe_function.h"
namespace runtime_probe {
/* Read system directory into key value pairs.
*
* Kernel modules export attributes as files under /sys, this funciton is
* aimed to read this kind of structure.
*
* For example,
* /sys/bus/cool/devices/Da/ contains file "1",
*
* /sys/bus/cool/devices/Db/ contains file "1",
* /sys/bus/cool/devices/Db/ contains file "2",
*
* /sys/bus/cool/devices/Dc/ contains file "2",
* /sys/bus/cool/devices/Dc/ contains file "4",
*
* And the probe statement is::
* {
* "dir_path": "/sys/bus/cool/devices/D*",
* "keys": ["1"],
* "optional_keys": ["2"]
* }
*
* Then the probe result will be::
* [
* {
* "1": "<content of Da/1>"
* // no entry "2" because "Da/2" doesn't exists.
* },
* {
* "1": "<content of Db/1>",
* "2": "<content of Db/2>"
* }
* // No report for "Dc" because "Dc/1" doesn't exists.
* ]
*/
class SysfsFunction : public ProbeFunction {
/* All probe functions should inherit runtime_probe::ProbeFunction */
public:
/* The identifier / function name of this probe function.
*
* It will be used for both parsing and logging.
*/
static constexpr auto function_name = "sysfs";
/* Define a parser for this function.
*
* This function takes the arguments in `const base::DictionaryValue&` type.
* This function should parse the `dict_value`, if the `dict_value` has
* correct format, this function should return a new instance of
* `SysfsFunction` whose members are decided by `dict_value`.
*
* @args dict_value: a JSON dictionary to parse arguments from.
*
* @return pointer to new `SysfsFunction` instance on success, nullptr
* otherwise.
*/
static std::unique_ptr<ProbeFunction> FromDictionaryValue(
const base::DictionaryValue& dict_value) {
/* Create an instance of SysfsFunction.
* **NOTE: The name should always be "instance" for PARSE_ARGUMENT to work**
*/
std::unique_ptr<SysfsFunction> instance{new SysfsFunction()};
bool result = true;
/* Parse each argument one by one.
*
* 1. Due to the template declaration, the type of default value and member
* must match exactly. That is, the default value of a double argument must
* be double (3.0 instead of 3). And default value of string argument must
* be std::string{...}.
*
* 2. Due to the behavior of "&=", all parser will be executed even if some
* of them failed.
*/
result &= PARSE_ARGUMENT(dir_path);
result &= PARSE_ARGUMENT(keys);
result &= PARSE_ARGUMENT(optional_keys, {});
if (result)
return instance;
return nullptr;
}
/* Override `Eval` function, which should return a list of DictionaryValue */
DataType Eval() const override;
private:
/* Declare a register for this function. This has to be defined for
* `REGISTER_PROBE_FUNCTION(...)` to work.
*/
static ProbeFunction::Register<SysfsFunction> register_;
/* Declare function arguments */
/* The path of target sysfs folder, the last component can contain '*' */
std::string dir_path_;
/* Required file names in the sysfs folder */
std::vector<std::string> keys_;
/* Optional fils names in the sysfs folder */
std::vector<std::string> optional_keys_;
/* A mocked sysfs path that we allow to read while testing. */
base::FilePath sysfs_path_for_testing_;
/* Set mocked sysfs path for testing.
*
* Normally, this probe function will fail if |dir_path_| is not a
* subdirectory of /sys/. Call this function to allow an additional path.
*
* This function will fail if the mock path is set twice.
*/
void MockSysfsPathForTesting(base::FilePath mock_path);
FRIEND_TEST(SysfsFunctionTest, TestRead);
};
/* Register the SysfsFunction */
REGISTER_PROBE_FUNCTION(SysfsFunction);
} // namespace runtime_probe
#endif // RUNTIME_PROBE_FUNCTIONS_SYSFS_H_