From fb98556d56d0defa325fab1296077627cce31aab Mon Sep 17 00:00:00 2001 From: ecyrbe Date: Sun, 23 Feb 2020 00:46:52 +0100 Subject: [PATCH] feat(std/node): add os.loadavg() (#4075) --- cli/js/deno.ts | 2 +- cli/js/dispatch.ts | 1 + cli/js/lib.deno.ns.d.ts | 6 ++++++ cli/js/os.ts | 8 ++++++++ cli/js/os_test.ts | 17 +++++++++++++++++ cli/ops/os.rs | 17 +++++++++++++++++ std/node/os.ts | 4 ++-- std/node/os_test.ts | 29 ++++++----------------------- 8 files changed, 58 insertions(+), 26 deletions(-) diff --git a/cli/js/deno.ts b/cli/js/deno.ts index d20c64281b..c1b074f3d5 100644 --- a/cli/js/deno.ts +++ b/cli/js/deno.ts @@ -85,7 +85,7 @@ export { ShutdownMode, shutdown } from "./net.ts"; -export { dir, env, exit, isTTY, execPath, hostname } from "./os.ts"; +export { dir, env, exit, isTTY, execPath, hostname, loadavg } from "./os.ts"; export { permissions, PermissionName, diff --git a/cli/js/dispatch.ts b/cli/js/dispatch.ts index 3d21389536..93f6dc0552 100644 --- a/cli/js/dispatch.ts +++ b/cli/js/dispatch.ts @@ -80,6 +80,7 @@ export let OP_TRANSPILE: number; export let OP_SIGNAL_BIND: number; export let OP_SIGNAL_UNBIND: number; export let OP_SIGNAL_POLL: number; +export let OP_LOADAVG: number; const PLUGIN_ASYNC_HANDLER_MAP: Map = new Map(); diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts index 39303677ae..d1770a15a7 100644 --- a/cli/js/lib.deno.ns.d.ts +++ b/cli/js/lib.deno.ns.d.ts @@ -40,6 +40,12 @@ declare namespace Deno { stderr: boolean; }; + /** Get the loadavg. Requires the `--allow-env` flag. + * + * console.log(Deno.loadavg()); + */ + export function loadavg(): number[]; + /** Get the hostname. Requires the `--allow-env` flag. * * console.log(Deno.hostname()); diff --git a/cli/js/os.ts b/cli/js/os.ts index 275dbdf1d5..d3c0d1b724 100644 --- a/cli/js/os.ts +++ b/cli/js/os.ts @@ -11,6 +11,14 @@ import * as util from "./util.ts"; export function isTTY(): { stdin: boolean; stdout: boolean; stderr: boolean } { return sendSync(dispatch.OP_IS_TTY); } +/** Get the loadavg. + * Requires the `--allow-env` flag. + * + * console.log(Deno.loadavg()); + */ +export function loadavg(): number[] { + return sendSync(dispatch.OP_LOADAVG); +} /** Get the hostname. * Requires the `--allow-env` flag. diff --git a/cli/js/os_test.ts b/cli/js/os_test.ts index fa4bf636b3..325cbdaa6d 100644 --- a/cli/js/os_test.ts +++ b/cli/js/os_test.ts @@ -283,6 +283,23 @@ testPerm({ env: false }, function execPathPerm(): void { assert(caughtError); }); +testPerm({ env: true }, function loadavgSuccess(): void { + const load = Deno.loadavg(); + assertEquals(load.length, 3); +}); + +testPerm({ env: false }, function loadavgPerm(): void { + let caughtError = false; + try { + Deno.loadavg(); + } catch (err) { + caughtError = true; + assert(err instanceof Deno.Err.PermissionDenied); + assertEquals(err.name, "PermissionDenied"); + } + assert(caughtError); +}); + testPerm({ env: true }, function hostnameDir(): void { assertNotEquals(Deno.hostname(), ""); }); diff --git a/cli/ops/os.rs b/cli/ops/os.rs index 8def5ac1ef..d1786a6dbb 100644 --- a/cli/ops/os.rs +++ b/cli/ops/os.rs @@ -19,6 +19,7 @@ pub fn init(i: &mut Isolate, s: &State) { i.register_op("get_env", s.core_op(json_op(s.stateful_op(op_get_env)))); i.register_op("get_dir", s.core_op(json_op(s.stateful_op(op_get_dir)))); i.register_op("hostname", s.core_op(json_op(s.stateful_op(op_hostname)))); + i.register_op("loadavg", s.core_op(json_op(s.stateful_op(op_loadavg)))); } #[derive(Deserialize)] @@ -158,6 +159,22 @@ fn op_is_tty( }))) } +fn op_loadavg( + state: &State, + _args: Value, + _zero_copy: Option, +) -> Result { + state.check_env()?; + match sys_info::loadavg() { + Ok(loadavg) => Ok(JsonOp::Sync(json!([ + loadavg.one, + loadavg.five, + loadavg.fifteen + ]))), + Err(_) => Ok(JsonOp::Sync(json!([0f64, 0f64, 0f64]))), + } +} + fn op_hostname( state: &State, _args: Value, diff --git a/std/node/os.ts b/std/node/os.ts index 8facde2921..51e5bbd930 100644 --- a/std/node/os.ts +++ b/std/node/os.ts @@ -133,12 +133,12 @@ export function hostname(): string { return Deno.hostname(); } -/** Not yet implemented */ +/** Returns an array containing the 1, 5, and 15 minute load averages */ export function loadavg(): number[] { if (Deno.build.os == "win") { return [0, 0, 0]; } - notImplemented(SEE_GITHUB_ISSUE); + return Deno.loadavg(); } /** Not yet implemented */ diff --git a/std/node/os_test.ts b/std/node/os_test.ts index f13589a4bc..f825ae192b 100644 --- a/std/node/os_test.ts +++ b/std/node/os_test.ts @@ -1,10 +1,5 @@ const { test } = Deno; -import { - assert, - assertThrows, - assertEquals, - AssertionError -} from "../testing/asserts.ts"; +import { assert, assertThrows, assertEquals } from "../testing/asserts.ts"; import * as os from "./os.ts"; test({ @@ -168,26 +163,14 @@ test({ } }); -// Method is currently implemented correctly for windows but not for any other os test({ name: "Load average is an array of 3 numbers", fn() { - try { - const result = os.loadavg(); - assert(result.length == 3); - assertEquals(typeof result[0], "number"); - assertEquals(typeof result[1], "number"); - assertEquals(typeof result[2], "number"); - } catch (error) { - if (!(Object.getPrototypeOf(error) === Error.prototype)) { - const errMsg = `Unexpected error class: ${error.name}`; - throw new AssertionError(errMsg); - } else if (!error.message.includes("Not implemented")) { - throw new AssertionError( - "Expected this error to contain 'Not implemented'" - ); - } - } + const result = os.loadavg(); + assert(result.length == 3); + assertEquals(typeof result[0], "number"); + assertEquals(typeof result[1], "number"); + assertEquals(typeof result[2], "number"); } });