Commit 9acfb5ef authored by Andrei-Laurențiu Olteanu's avatar Andrei-Laurențiu Olteanu Committed by Commit Bot

[Telemetry SWX] Add disk read routine

Add implementation to chrome://.

Add implementation to chrome-untrusted://.

Restrict maxFileSize to 10GB.

Add tests.

Bug: b:162051831
Change-Id: Ia011da2289e1808e2bd828ddd9bb82573ed73d46
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2401340
Commit-Queue: Laurențiu Olteanu <lolteanu@google.com>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarOleh Lamzin <lamzin@google.com>
Reviewed-by: default avatarMahmoud Gawad <mgawad@google.com>
Cr-Commit-Position: refs/heads/master@{#811644}
parent aa87186e
......@@ -190,6 +190,22 @@ void DiagnosticsService::RunNvmeSelfTestRoutine(
std::move(callback)));
}
void DiagnosticsService::RunDiskReadRoutine(
health::mojom::DiskReadRoutineTypeEnum type,
uint32_t length_seconds,
uint32_t file_size_mb,
RunDiskReadRoutineCallback callback) {
GetService()->RunDiskReadRoutine(
converters::Convert(type), length_seconds, file_size_mb,
base::BindOnce(
[](health::mojom::DiagnosticsService::RunDiskReadRoutineCallback
callback,
cros_healthd::mojom::RunRoutineResponsePtr ptr) {
std::move(callback).Run(converters::ConvertPtr(std::move(ptr)));
},
std::move(callback)));
}
void DiagnosticsService::RunPrimeSearchRoutine(
uint32_t length_seconds,
uint64_t max_num,
......
......@@ -63,6 +63,10 @@ class DiagnosticsService : public health::mojom::DiagnosticsService {
void RunNvmeSelfTestRoutine(
health::mojom::NvmeSelfTestTypeEnum nvme_self_test_type,
RunNvmeSelfTestRoutineCallback callback) override;
void RunDiskReadRoutine(health::mojom::DiskReadRoutineTypeEnum type,
uint32_t length_seconds,
uint32_t file_size_mb,
RunDiskReadRoutineCallback callback) override;
void RunPrimeSearchRoutine(uint32_t length_seconds,
uint64_t max_num,
RunPrimeSearchRoutineCallback callback) override;
......
......@@ -205,5 +205,20 @@ cros_healthd::mojom::NvmeSelfTestTypeEnum Convert(
1);
}
cros_healthd::mojom::DiskReadRoutineTypeEnum Convert(
health::mojom::DiskReadRoutineTypeEnum input) {
switch (input) {
case health::mojom::DiskReadRoutineTypeEnum::kLinearRead:
return cros_healthd::mojom::DiskReadRoutineTypeEnum::kLinearRead;
case health::mojom::DiskReadRoutineTypeEnum::kRandomRead:
return cros_healthd::mojom::DiskReadRoutineTypeEnum::kRandomRead;
}
NOTREACHED();
return static_cast<cros_healthd::mojom::DiskReadRoutineTypeEnum>(
static_cast<int>(
cros_healthd::mojom::DiskReadRoutineTypeEnum::kMaxValue) +
1);
}
} // namespace converters
} // namespace chromeos
......@@ -63,6 +63,9 @@ cros_healthd::mojom::AcPowerStatusEnum Convert(
cros_healthd::mojom::NvmeSelfTestTypeEnum Convert(
health::mojom::NvmeSelfTestTypeEnum input);
cros_healthd::mojom::DiskReadRoutineTypeEnum Convert(
health::mojom::DiskReadRoutineTypeEnum input);
} // namespace converters
} // namespace chromeos
......
......@@ -86,5 +86,15 @@ TEST(DiagnosticsServiceConvertersTest, ConvertNvmeSelfTestTypeEnum) {
cros_healthd::NvmeSelfTestTypeEnum::kLongSelfTest);
}
TEST(DiagnosticsServiceConvertersTest, ConvertDiskReadRoutineTypeEnum) {
namespace cros_healthd = ::chromeos::cros_healthd::mojom;
namespace health = ::chromeos::health::mojom;
EXPECT_EQ(Convert(health::DiskReadRoutineTypeEnum::kLinearRead),
cros_healthd::DiskReadRoutineTypeEnum::kLinearRead);
EXPECT_EQ(Convert(health::DiskReadRoutineTypeEnum::kRandomRead),
cros_healthd::DiskReadRoutineTypeEnum::kRandomRead);
}
} // namespace converters
} // namespace chromeos
......@@ -184,6 +184,28 @@ interface DiagnosticsService {
RunNvmeSelfTestRoutine(NvmeSelfTestTypeEnum nvme_self_test_type)
=> (RunRoutineResponse response);
// Requests that the DiskRead routine is created and started on the platform.
// The routine will create a test file with md5 checksum, read the test file
// either randomly or linearly, repeatedly for a dedicated duration. If the
// md5 checksum of read back is validated, then the test will pass.
// This routine is only available if GetAvailableRoutines returned kDiskRead.
//
// The request:
// * |type| - type of how disk reading is performed, either linear or random.
//
// * |length_seconds| - length of time, in seconds, to run the DiskRead
// routine for. This parameter needs to be strictly
// greater than zero.
// - TODO(b:167963397) - limit routine duration.
// * |file_size_mb| - test file size, in mega bytes, to test with DiskRead
// routine. Maximum file size is 10 GB.
// The response:
// * |response| - contains a unique identifier and status for the created
// routine.
RunDiskReadRoutine(DiskReadRoutineTypeEnum type, uint32 length_seconds,
uint32 file_size_mb)
=> (RunRoutineResponse response);
// Requests that the PrimeSearch routine is created and started on the
// platform. Calculate prime numbers between 2 to max_num and verify the
// calculation repeatedly in a duration. This routine is only available
......@@ -355,3 +377,9 @@ enum NvmeSelfTestTypeEnum {
kShortSelfTest = 0, // Short time self-test.
kLongSelfTest = 1, // Long time self-test.
};
// Enumeration of the possible DiskRead routine's command type
enum DiskReadRoutineTypeEnum {
kLinearRead,
kRandomRead,
};
......@@ -35,6 +35,7 @@ dpsl_internal.Message = {
'DiagnosticsService.RunNvmeWearLevelRoutine',
DIAGNOSTICS_RUN_NVME_SELF_TEST_ROUTINE:
'DiagnosticsService.RunNvmeSelfTestRoutine',
DIAGNOSTICS_RUN_DISK_READ_ROUTINE: 'DiagnosticsService.RunDiskReadRoutine',
DIAGNOSTICS_RUN_PRIME_SEARCH_ROUTINE:
'DiagnosticsService.RunPrimeSearchRoutine',
DIAGNOSTICS_RUN_BATTERY_DISCHARGE_ROUTINE:
......@@ -144,6 +145,16 @@ dpsl_internal.DiagnosticsRunNvmeWearLevelRoutineRequest;
*/
dpsl_internal.DiagnosticsRunNvmeSelfTestRoutineRequest;
/**
* Request message sent by the unprivileged context to the privileged
* context to run disk read routine.
* @typedef {{
* type: !string,
* lengthSeconds: !number,
* fileSizeMb: !number}}
*/
dpsl_internal.DiagnosticsRunDiskReadRoutineRequest;
/**
* Request message sent by the unprivileged context to the privileged
* context to run prime search routine.
......
......@@ -162,6 +162,24 @@ class DiagnosticsProxy {
throw RangeError(
'nvmeSelfTestTypeToEnum_ does not contain all items from enum!');
}
const diskReadRoutineTypeEnum =
chromeos.health.mojom.DiskReadRoutineTypeEnum;
/**
* @type { !Map<!string, !chromeos.health.mojom.DiskReadRoutineTypeEnum> }
* @const
*/
this.diskReadRoutineTypeToEnum_ = new Map([
['linear-read', diskReadRoutineTypeEnum.kLinearRead],
['random-read', diskReadRoutineTypeEnum.kRandomRead],
]);
if (this.diskReadRoutineTypeToEnum_.size !==
diskReadRoutineTypeEnum.MAX_VALUE + 1) {
throw RangeError(
'diskReadRoutineTypeToEnum_ does not contain all items from enum!');
}
}
/**
......@@ -477,6 +495,48 @@ class DiagnosticsProxy {
this.convertNvmeSelfTestTypeToEnum(request.nvmeSelfTestType));
};
/**
* Converts disk read type string to DiskReadRoutineTypeEnum.
* @param { !string } type
* @return { !chromeos.health.mojom.DiskReadRoutineTypeEnum }
*/
convertDiskReadTypeToEnum(type) {
if (!this.diskReadRoutineTypeToEnum_.has(type)) {
throw TypeError(`Diagnostic disk read type '${type}' is unknown.`);
}
return this.diskReadRoutineTypeToEnum_.get(type);
}
/**
* Throws an error if fileSizeMb exceeds maxSizeMb.
* @param { !number } fileSizeMb
* @param { !number } maxSizeMb
*/
assertFileSizeLargerThan(fileSizeMb, maxSizeMb) {
if (fileSizeMb > maxSizeMb) {
throw RangeError(
`Diagnostic disk read routine does not allow file sizes greater ` +
`than '${maxSizeMb}'.`);
}
}
/**
* Runs disk read routine.
* @param { !Object } message
* @return { !RunRoutineResponsePromise }
*/
async handleRunDiskReadRoutine(message) {
const request =
/** @type {!dpsl_internal.DiagnosticsRunDiskReadRoutineRequest} */
(message);
this.assertNumberIsPositive(request.lengthSeconds);
this.assertFileSizeLargerThan(request.fileSizeMb, 10 * 1000);
return await getOrCreateDiagnosticsService().runDiskReadRoutine(
this.convertDiskReadTypeToEnum(request.type), request.lengthSeconds,
request.fileSizeMb);
};
/**
* Runs prime search routine.
* @param { !Object } message
......@@ -856,6 +916,12 @@ untrustedMessagePipe.registerHandler(
(message) => diagnosticsProxy.handleRunNvmeSelfTestRoutine(message),
message));
untrustedMessagePipe.registerHandler(
dpsl_internal.Message.DIAGNOSTICS_RUN_DISK_READ_ROUTINE,
(message) => diagnosticsProxy.genericRunRoutineHandler(
(message) => diagnosticsProxy.handleRunDiskReadRoutine(message),
message));
untrustedMessagePipe.registerHandler(
dpsl_internal.Message.DIAGNOSTICS_RUN_PRIME_SEARCH_ROUTINE,
(message) => diagnosticsProxy.genericRunRoutineHandler(
......
......@@ -267,6 +267,30 @@ chromeos.test_support = {};
return response;
}
/**
* Requests disk read routine to be run.
* @param { !string } type
* @param { !number } lengthSeconds
* @param { !number } fileSizeMb
* @return { !Promise<!Object> }
* @public
*/
async runDiskReadRoutine(type, lengthSeconds, fileSizeMb) {
const message =
/**
@type {!dpsl_internal.DiagnosticsRunDiskReadRoutineRequest}
*/
({type: type, lengthSeconds: lengthSeconds, fileSizeMb: fileSizeMb});
const response =
/** @type {!Object} */ (await messagePipe.sendMessage(
dpsl_internal.Message.DIAGNOSTICS_RUN_DISK_READ_ROUTINE,
message));
if (response instanceof Error) {
throw response;
}
return response;
}
/**
* Requests prime search routine to be run.
* @param { !number } lengthSeconds
......
......@@ -133,6 +133,15 @@ TEST_F('TelemetryExtensionUIBrowserTest', 'ConvertDiagnosticsEnums', () => {
diagnosticsProxy.convertNvmeSelfTestTypeToEnum('long-self-test'),
nvmeSelfTestTypeEnum.kLongSelfTest);
// Unit tests for convertDiskReadTypeToEnum
const diskReadRoutineTypeEnum = chromeos.health.mojom.DiskReadRoutineTypeEnum;
assertEquals(
diagnosticsProxy.convertDiskReadTypeToEnum('linear-read'),
diskReadRoutineTypeEnum.kLinearRead);
assertEquals(
diagnosticsProxy.convertDiskReadTypeToEnum('random-read'),
diskReadRoutineTypeEnum.kRandomRead);
testDone();
});
......@@ -391,6 +400,8 @@ const untrustedTests = [
['UntrustedDiagnosticsRequestRunNvmeWearLevelRoutine'],
['UntrustedDiagnosticsRequestRunNvmeSelfTestRoutineInvalidInput'],
['UntrustedDiagnosticsRequestRunNvmeSelfTestRoutine'],
['UntrustedDiagnosticsRequestRunDiskReadRoutineInvalidInput'],
['UntrustedDiagnosticsRequestRunDiskReadRoutine'],
['UntrustedDiagnosticsRequestRunPrimeSearchRoutineInvalidInput'],
['UntrustedDiagnosticsRequestRunPrimeSearchRoutine'],
['UntrustedDiagnosticsRequestRunBatteryDischargeRoutineInvalidInput'],
......
......@@ -279,6 +279,66 @@ UNTRUSTED_TEST(
assertDeepEquals(response2, {id: 123456789, status: 'ready'});
});
// Tests that runDiskReadRoutine throws the correct error when invalid enum
// is passed as input.
UNTRUSTED_TEST(
'UntrustedDiagnosticsRequestRunDiskReadRoutineInvalidInput', async () => {
let caughtError1;
try {
await chromeos.diagnostics.runDiskReadRoutine(
'this-does-not-exist', 10, 10);
} catch (error) {
caughtError1 = error;
}
assertEquals(caughtError1.name, 'TypeError');
assertEquals(
caughtError1.message,
`Diagnostic disk read type \'this-does-not-exist\' is unknown.`);
let caughtError2;
try {
await chromeos.diagnostics.runDiskReadRoutine('linear-read', 0, 10);
} catch (error) {
caughtError2 = error;
}
let caughtError3;
try {
await chromeos.diagnostics.runDiskReadRoutine(
'random-read', -2147483648, 10);
} catch (error) {
caughtError3 = error;
}
assertEquals(caughtError3.name, 'RangeError');
assertEquals(caughtError3.message, `Parameter must be positive.`);
let caughtError4;
try {
await chromeos.diagnostics.runDiskReadRoutine(
'random-read', 10, 987654321);
} catch (error) {
caughtError4 = error;
}
assertEquals(caughtError4.name, 'RangeError');
assertEquals(
caughtError4.message,
`Diagnostic disk read routine does not allow file sizes greater ` +
`than '10000'.`);
});
// Tests that runDiskReadRoutine returns the correct Object.
UNTRUSTED_TEST('UntrustedDiagnosticsRequestRunDiskReadRoutine', async () => {
const response1 =
await chromeos.diagnostics.runDiskReadRoutine('linear-read', 12, 20);
assertDeepEquals(response1, {id: 123456789, status: 'ready'});
const response2 =
await chromeos.diagnostics.runDiskReadRoutine('random-read', 20, 10);
assertDeepEquals(response2, {id: 123456789, status: 'ready'});
});
// Tests that runPrimeSearchRoutine throws the correct error when invalid enum
// is passed as input.
UNTRUSTED_TEST(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment