cros_healthd: add prime search routines
Add a routine to calculate prime number repeatedly and validate the calculation results are correct in a duration. Bug: b:146513388 Test: chromeos_unittests --gtest_filter=CrosHealthdServiceConnectionTest.* Change-Id: I29c3d71d2b0f9d86043e552e135bc9178c95014f Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2049986 Commit-Queue: Oleh Lamzin <lamzin@google.com> Reviewed-by: Oleh Lamzin <lamzin@google.com> Reviewed-by: Maksim Ivanov <emaxx@chromium.org> Reviewed-by: Paul Moy <pmoy@chromium.org> Reviewed-by: Steven Bennetts <stevenjb@chromium.org> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Cr-Commit-Position: refs/heads/master@{#754004}
This commit is contained in:
chrome/browser/chromeos/policy/remote_commands
chromeos
dbus
services
@@ -400,6 +400,31 @@ void DeviceCommandRunRoutineJob::RunImpl(CallbackWithResult succeeded_callback,
|
|||||||
std::move(failed_callback)));
|
std::move(failed_callback)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kPrimeSearch: {
|
||||||
|
constexpr char kLengthSecondsFieldName[] = "lengthSeconds";
|
||||||
|
constexpr char kMaxNumFieldName[] = "maxNum";
|
||||||
|
base::Optional<int> length_seconds =
|
||||||
|
params_dict_.FindIntKey(kLengthSecondsFieldName);
|
||||||
|
base::Optional<int> max_num = params_dict_.FindIntKey(kMaxNumFieldName);
|
||||||
|
if (!length_seconds.has_value() || length_seconds.value() < 0 ||
|
||||||
|
!max_num.has_value() || max_num.value() < 0) {
|
||||||
|
SYSLOG(ERROR) << "Invalid parameters for prime search routine.";
|
||||||
|
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(std::move(failed_callback),
|
||||||
|
std::make_unique<Payload>(
|
||||||
|
MakeInvalidParametersResponse())));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto exec_duration = base::TimeDelta::FromSeconds(length_seconds.value());
|
||||||
|
chromeos::cros_healthd::ServiceConnection::GetInstance()
|
||||||
|
->RunPrimeSearchRoutine(
|
||||||
|
exec_duration, max_num.value(),
|
||||||
|
base::BindOnce(
|
||||||
|
&DeviceCommandRunRoutineJob::OnCrosHealthdResponseReceived,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(), std::move(succeeded_callback),
|
||||||
|
std::move(failed_callback)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -67,6 +67,10 @@ constexpr char kNvmeSelfTestTypeFieldName[] = "nvmeSelfTestType";
|
|||||||
constexpr char kTypeFieldName[] = "type";
|
constexpr char kTypeFieldName[] = "type";
|
||||||
constexpr char kFileSizeMbFieldName[] = "fileSizeMb";
|
constexpr char kFileSizeMbFieldName[] = "fileSizeMb";
|
||||||
|
|
||||||
|
// String constants identifying the parameter fields for the prime search
|
||||||
|
// routine
|
||||||
|
constexpr char kMaxNumFieldName[] = "maxNum";
|
||||||
|
|
||||||
// Dummy values to populate cros_healthd's RunRoutineResponse.
|
// Dummy values to populate cros_healthd's RunRoutineResponse.
|
||||||
constexpr uint32_t kId = 11;
|
constexpr uint32_t kId = 11;
|
||||||
constexpr chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum kStatus =
|
constexpr chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum kStatus =
|
||||||
@@ -1400,4 +1404,149 @@ TEST_F(DeviceCommandRunRoutineJobTest, RunDiskReadRoutineInvalidFileSizeMb) {
|
|||||||
run_loop.Run();
|
run_loop.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DeviceCommandRunRoutineJobTest, RunPrimeSearchRoutineSuccess) {
|
||||||
|
// Test that the routine succeeds with all parameters specified.
|
||||||
|
auto run_routine_response =
|
||||||
|
chromeos::cros_healthd::mojom::RunRoutineResponse::New(kId, kStatus);
|
||||||
|
chromeos::cros_healthd::FakeCrosHealthdClient::Get()
|
||||||
|
->SetRunRoutineResponseForTesting(run_routine_response);
|
||||||
|
base::Value params_dict(base::Value::Type::DICTIONARY);
|
||||||
|
params_dict.SetIntKey(kLengthSecondsFieldName,
|
||||||
|
/*length_seconds=*/2342);
|
||||||
|
params_dict.SetIntKey(kMaxNumFieldName,
|
||||||
|
/*max_num=*/100000);
|
||||||
|
std::unique_ptr<RemoteCommandJob> job =
|
||||||
|
std::make_unique<DeviceCommandRunRoutineJob>();
|
||||||
|
InitializeJob(
|
||||||
|
job.get(), kUniqueID, test_start_time_, base::TimeDelta::FromSeconds(30),
|
||||||
|
/*terminate_upon_input=*/false,
|
||||||
|
chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kPrimeSearch,
|
||||||
|
std::move(params_dict));
|
||||||
|
base::RunLoop run_loop;
|
||||||
|
bool success =
|
||||||
|
job->Run(base::Time::Now(), base::TimeTicks::Now(),
|
||||||
|
base::BindLambdaForTesting([&]() {
|
||||||
|
EXPECT_EQ(job->status(), RemoteCommandJob::SUCCEEDED);
|
||||||
|
std::unique_ptr<std::string> payload = job->GetResultPayload();
|
||||||
|
EXPECT_TRUE(payload);
|
||||||
|
EXPECT_EQ(CreateSuccessPayload(kId, kStatus), *payload);
|
||||||
|
run_loop.Quit();
|
||||||
|
}));
|
||||||
|
EXPECT_TRUE(success);
|
||||||
|
run_loop.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DeviceCommandRunRoutineJobTest,
|
||||||
|
RunPrimeSearchRoutineMissingLengthSeconds) {
|
||||||
|
// Test that leaving out the length_seconds parameter causes the routine to
|
||||||
|
// fail.
|
||||||
|
base::Value params_dict(base::Value::Type::DICTIONARY);
|
||||||
|
params_dict.SetIntKey(kMaxNumFieldName,
|
||||||
|
/*max_num=*/100000);
|
||||||
|
std::unique_ptr<RemoteCommandJob> job =
|
||||||
|
std::make_unique<DeviceCommandRunRoutineJob>();
|
||||||
|
InitializeJob(
|
||||||
|
job.get(), kUniqueID, test_start_time_, base::TimeDelta::FromSeconds(30),
|
||||||
|
/*terminate_upon_input=*/false,
|
||||||
|
chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kPrimeSearch,
|
||||||
|
std::move(params_dict));
|
||||||
|
base::RunLoop run_loop;
|
||||||
|
bool success =
|
||||||
|
job->Run(base::Time::Now(), base::TimeTicks::Now(),
|
||||||
|
base::BindLambdaForTesting([&]() {
|
||||||
|
EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
|
||||||
|
std::unique_ptr<std::string> payload = job->GetResultPayload();
|
||||||
|
EXPECT_TRUE(payload);
|
||||||
|
EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
|
||||||
|
run_loop.Quit();
|
||||||
|
}));
|
||||||
|
EXPECT_TRUE(success);
|
||||||
|
run_loop.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DeviceCommandRunRoutineJobTest, RunPrimeSearchRoutineMissingMaxNum) {
|
||||||
|
// Test that leaving out the max_num parameter causes the routine to fail.
|
||||||
|
base::Value params_dict(base::Value::Type::DICTIONARY);
|
||||||
|
params_dict.SetIntKey(kLengthSecondsFieldName,
|
||||||
|
/*length_seconds=*/2342);
|
||||||
|
std::unique_ptr<RemoteCommandJob> job =
|
||||||
|
std::make_unique<DeviceCommandRunRoutineJob>();
|
||||||
|
InitializeJob(
|
||||||
|
job.get(), kUniqueID, test_start_time_, base::TimeDelta::FromSeconds(30),
|
||||||
|
/*terminate_upon_input=*/false,
|
||||||
|
chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kPrimeSearch,
|
||||||
|
std::move(params_dict));
|
||||||
|
base::RunLoop run_loop;
|
||||||
|
bool success =
|
||||||
|
job->Run(base::Time::Now(), base::TimeTicks::Now(),
|
||||||
|
base::BindLambdaForTesting([&]() {
|
||||||
|
EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
|
||||||
|
std::unique_ptr<std::string> payload = job->GetResultPayload();
|
||||||
|
EXPECT_TRUE(payload);
|
||||||
|
EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
|
||||||
|
run_loop.Quit();
|
||||||
|
}));
|
||||||
|
EXPECT_TRUE(success);
|
||||||
|
run_loop.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DeviceCommandRunRoutineJobTest,
|
||||||
|
RunPrimeSearchRoutineInvalidLengthSeconds) {
|
||||||
|
// Test that an invalid value for the length_seconds parameter causes the
|
||||||
|
// routine to fail.
|
||||||
|
base::Value params_dict(base::Value::Type::DICTIONARY);
|
||||||
|
params_dict.SetIntKey(kLengthSecondsFieldName,
|
||||||
|
/*length_seconds=*/-1);
|
||||||
|
params_dict.SetIntKey(kMaxNumFieldName,
|
||||||
|
/*max_num=*/100000);
|
||||||
|
std::unique_ptr<RemoteCommandJob> job =
|
||||||
|
std::make_unique<DeviceCommandRunRoutineJob>();
|
||||||
|
InitializeJob(
|
||||||
|
job.get(), kUniqueID, test_start_time_, base::TimeDelta::FromSeconds(30),
|
||||||
|
/*terminate_upon_input=*/false,
|
||||||
|
chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kPrimeSearch,
|
||||||
|
std::move(params_dict));
|
||||||
|
base::RunLoop run_loop;
|
||||||
|
bool success =
|
||||||
|
job->Run(base::Time::Now(), base::TimeTicks::Now(),
|
||||||
|
base::BindLambdaForTesting([&]() {
|
||||||
|
EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
|
||||||
|
std::unique_ptr<std::string> payload = job->GetResultPayload();
|
||||||
|
EXPECT_TRUE(payload);
|
||||||
|
EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
|
||||||
|
run_loop.Quit();
|
||||||
|
}));
|
||||||
|
EXPECT_TRUE(success);
|
||||||
|
run_loop.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DeviceCommandRunRoutineJobTest, RunPrimeSearchRoutineInvalidMaxNum) {
|
||||||
|
// Test that an invalid value for the max_num parameter causes the
|
||||||
|
// routine to fail.
|
||||||
|
base::Value params_dict(base::Value::Type::DICTIONARY);
|
||||||
|
params_dict.SetIntKey(kLengthSecondsFieldName,
|
||||||
|
/*length_seconds=*/2342);
|
||||||
|
params_dict.SetIntKey(kMaxNumFieldName,
|
||||||
|
/*max_num=*/-1);
|
||||||
|
std::unique_ptr<RemoteCommandJob> job =
|
||||||
|
std::make_unique<DeviceCommandRunRoutineJob>();
|
||||||
|
InitializeJob(
|
||||||
|
job.get(), kUniqueID, test_start_time_, base::TimeDelta::FromSeconds(30),
|
||||||
|
/*terminate_upon_input=*/false,
|
||||||
|
chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kPrimeSearch,
|
||||||
|
std::move(params_dict));
|
||||||
|
base::RunLoop run_loop;
|
||||||
|
bool success =
|
||||||
|
job->Run(base::Time::Now(), base::TimeTicks::Now(),
|
||||||
|
base::BindLambdaForTesting([&]() {
|
||||||
|
EXPECT_EQ(job->status(), RemoteCommandJob::FAILED);
|
||||||
|
std::unique_ptr<std::string> payload = job->GetResultPayload();
|
||||||
|
EXPECT_TRUE(payload);
|
||||||
|
EXPECT_EQ(CreateInvalidParametersFailurePayload(), *payload);
|
||||||
|
run_loop.Quit();
|
||||||
|
}));
|
||||||
|
EXPECT_TRUE(success);
|
||||||
|
run_loop.Run();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace policy
|
} // namespace policy
|
||||||
|
@@ -108,6 +108,13 @@ void FakeCrosHealthdService::RunDiskReadRoutine(
|
|||||||
std::move(callback).Run(run_routine_response_.Clone());
|
std::move(callback).Run(run_routine_response_.Clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FakeCrosHealthdService::RunPrimeSearchRoutine(
|
||||||
|
uint32_t length_seconds,
|
||||||
|
uint64_t max_num,
|
||||||
|
RunPrimeSearchRoutineCallback callback) {
|
||||||
|
std::move(callback).Run(run_routine_response_.Clone());
|
||||||
|
}
|
||||||
|
|
||||||
void FakeCrosHealthdService::ProbeTelemetryInfo(
|
void FakeCrosHealthdService::ProbeTelemetryInfo(
|
||||||
const std::vector<mojom::ProbeCategoryEnum>& categories,
|
const std::vector<mojom::ProbeCategoryEnum>& categories,
|
||||||
ProbeTelemetryInfoCallback callback) {
|
ProbeTelemetryInfoCallback callback) {
|
||||||
|
@@ -70,6 +70,9 @@ class FakeCrosHealthdService final
|
|||||||
uint32_t length_seconds,
|
uint32_t length_seconds,
|
||||||
uint32_t file_size_mb,
|
uint32_t file_size_mb,
|
||||||
RunDiskReadRoutineCallback callback) override;
|
RunDiskReadRoutineCallback callback) override;
|
||||||
|
void RunPrimeSearchRoutine(uint32_t length_seconds,
|
||||||
|
uint64_t max_num,
|
||||||
|
RunPrimeSearchRoutineCallback callback) override;
|
||||||
|
|
||||||
// CrosHealthdProbeService overrides:
|
// CrosHealthdProbeService overrides:
|
||||||
void ProbeTelemetryInfo(
|
void ProbeTelemetryInfo(
|
||||||
|
@@ -84,6 +84,11 @@ class ServiceConnectionImpl : public ServiceConnection {
|
|||||||
uint32_t file_size_mb,
|
uint32_t file_size_mb,
|
||||||
mojom::CrosHealthdDiagnosticsService::RunDiskReadRoutineCallback callback)
|
mojom::CrosHealthdDiagnosticsService::RunDiskReadRoutineCallback callback)
|
||||||
override;
|
override;
|
||||||
|
void RunPrimeSearchRoutine(
|
||||||
|
base::TimeDelta& exec_duration,
|
||||||
|
uint64_t max_num,
|
||||||
|
mojom::CrosHealthdDiagnosticsService::RunPrimeSearchRoutineCallback
|
||||||
|
callback) override;
|
||||||
void ProbeTelemetryInfo(
|
void ProbeTelemetryInfo(
|
||||||
const std::vector<mojom::ProbeCategoryEnum>& categories_to_test,
|
const std::vector<mojom::ProbeCategoryEnum>& categories_to_test,
|
||||||
mojom::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback)
|
mojom::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback)
|
||||||
@@ -251,6 +256,17 @@ void ServiceConnectionImpl::RunDiskReadRoutine(
|
|||||||
type, exec_duration.InSeconds(), file_size_mb, std::move(callback));
|
type, exec_duration.InSeconds(), file_size_mb, std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServiceConnectionImpl::RunPrimeSearchRoutine(
|
||||||
|
base::TimeDelta& exec_duration,
|
||||||
|
uint64_t max_num,
|
||||||
|
mojom::CrosHealthdDiagnosticsService::RunPrimeSearchRoutineCallback
|
||||||
|
callback) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
BindCrosHealthdDiagnosticsServiceIfNeeded();
|
||||||
|
cros_healthd_diagnostics_service_->RunPrimeSearchRoutine(
|
||||||
|
exec_duration.InSeconds(), max_num, std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
void ServiceConnectionImpl::ProbeTelemetryInfo(
|
void ServiceConnectionImpl::ProbeTelemetryInfo(
|
||||||
const std::vector<mojom::ProbeCategoryEnum>& categories_to_test,
|
const std::vector<mojom::ProbeCategoryEnum>& categories_to_test,
|
||||||
mojom::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback) {
|
mojom::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback) {
|
||||||
|
@@ -131,6 +131,15 @@ class ServiceConnection {
|
|||||||
mojom::CrosHealthdDiagnosticsService::RunDiskReadRoutineCallback
|
mojom::CrosHealthdDiagnosticsService::RunDiskReadRoutineCallback
|
||||||
callback) = 0;
|
callback) = 0;
|
||||||
|
|
||||||
|
// Requests that cros_healthd runs the prime search routine. See
|
||||||
|
// src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
|
||||||
|
// details.
|
||||||
|
virtual void RunPrimeSearchRoutine(
|
||||||
|
base::TimeDelta& exec_duration,
|
||||||
|
uint64_t max_num,
|
||||||
|
mojom::CrosHealthdDiagnosticsService::RunPrimeSearchRoutineCallback
|
||||||
|
callback) = 0;
|
||||||
|
|
||||||
// Gather pieces of information about the platform. See
|
// Gather pieces of information about the platform. See
|
||||||
// src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
|
// src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
|
||||||
// details.
|
// details.
|
||||||
|
@@ -385,6 +385,21 @@ TEST_F(CrosHealthdServiceConnectionTest, RunDiskReadRoutine) {
|
|||||||
run_loop.Run();
|
run_loop.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CrosHealthdServiceConnectionTest, RunPrimeSearchRoutine) {
|
||||||
|
// Test that we can run the prime search routine.
|
||||||
|
auto response = MakeRunRoutineResponse();
|
||||||
|
FakeCrosHealthdClient::Get()->SetRunRoutineResponseForTesting(response);
|
||||||
|
base::RunLoop run_loop;
|
||||||
|
base::TimeDelta exec_duration = base::TimeDelta().FromSeconds(10);
|
||||||
|
ServiceConnection::GetInstance()->RunPrimeSearchRoutine(
|
||||||
|
/*exec_duration=*/exec_duration, /*max_num=*/1000000,
|
||||||
|
base::BindLambdaForTesting([&](mojom::RunRoutineResponsePtr response) {
|
||||||
|
EXPECT_EQ(response, MakeRunRoutineResponse());
|
||||||
|
run_loop.Quit();
|
||||||
|
}));
|
||||||
|
run_loop.Run();
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(CrosHealthdServiceConnectionTest, ProbeTelemetryInfo) {
|
TEST_F(CrosHealthdServiceConnectionTest, ProbeTelemetryInfo) {
|
||||||
// Test that we can send a request without categories.
|
// Test that we can send a request without categories.
|
||||||
auto empty_info = mojom::TelemetryInfo::New();
|
auto empty_info = mojom::TelemetryInfo::New();
|
||||||
|
@@ -227,6 +227,24 @@ interface CrosHealthdDiagnosticsService {
|
|||||||
RunDiskReadRoutine(DiskReadRoutineTypeEnum type, uint32 length_seconds,
|
RunDiskReadRoutine(DiskReadRoutineTypeEnum type, uint32 length_seconds,
|
||||||
uint32 file_size_mb)
|
uint32 file_size_mb)
|
||||||
=> (RunRoutineResponse response);
|
=> (RunRoutineResponse response);
|
||||||
|
|
||||||
|
// Requests that the PrimeSearch routine is created and started on the
|
||||||
|
// platform. Calculate prime numbers between 3 to max_num and verify the
|
||||||
|
// calculation repeatedly in a duration. This routine is only available
|
||||||
|
// if GetAvailableRoutines returned kPrimeSearch.
|
||||||
|
//
|
||||||
|
// The request:
|
||||||
|
// * |length_seconds| - length of time, in seconds, to run the PrimeSearch
|
||||||
|
// routine for. This parameter needs to be strictly
|
||||||
|
// greater than zero.
|
||||||
|
// * |max_num| - largest number that routine will calculate prime numbers up
|
||||||
|
// to.
|
||||||
|
//
|
||||||
|
// The response:
|
||||||
|
// * |response| - contains a unique identifier and status for the created
|
||||||
|
// routine.
|
||||||
|
RunPrimeSearchRoutine(uint32 length_seconds, uint64 max_num)
|
||||||
|
=> (RunRoutineResponse response);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Probe interface exposed by the cros_healthd daemon.
|
// Probe interface exposed by the cros_healthd daemon.
|
||||||
|
@@ -27,6 +27,7 @@ enum DiagnosticRoutineEnum {
|
|||||||
kNvmeWearLevel = 8,
|
kNvmeWearLevel = 8,
|
||||||
kNvmeSelfTest = 9,
|
kNvmeSelfTest = 9,
|
||||||
kDiskRead = 10,
|
kDiskRead = 10,
|
||||||
|
kPrimeSearch = 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Enumeration of the possible DiskRead routine's command type
|
// Enumeration of the possible DiskRead routine's command type
|
||||||
|
Reference in New Issue
Block a user