From 358eb10f1df7dca34c25095e4d34fd1a92bc7ca7 Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Tue, 15 Oct 2024 17:25:56 -0700 Subject: [PATCH] fix process-cpuusage.test.js --- src/bun.js/bindings/BunProcess.cpp | 33 +++--- .../test/parallel/process-cpuusage.test.js | 110 ++++++++++++++++++ 2 files changed, 123 insertions(+), 20 deletions(-) create mode 100644 test/js/node/test/parallel/process-cpuusage.test.js diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index 422be9b37f..d99fedf38a 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -2371,8 +2371,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionCpuUsage, if (!comparatorValue.isUndefined()) { JSC::JSObject* comparator = comparatorValue.getObject(); if (UNLIKELY(!comparator)) { - throwTypeError(globalObject, throwScope, "Expected an object as the first argument"_s); - return JSC::JSValue::encode(JSC::jsUndefined()); + return Bun::ERR::INVALID_ARG_TYPE(throwScope, globalObject, "previousValue"_s, "object"_s, comparatorValue); } JSValue userValue; @@ -2382,34 +2381,28 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionCpuUsage, userValue = comparator->getDirect(0); systemValue = comparator->getDirect(1); } else { - userValue = comparator->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "user"_s)); - RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::jsUndefined())); + userValue = comparator->get(globalObject, JSC::Identifier::fromString(vm, "user"_s)); + RETURN_IF_EXCEPTION(throwScope, {}); - systemValue = comparator->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "system"_s)); - RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::jsUndefined())); + systemValue = comparator->get(globalObject, JSC::Identifier::fromString(vm, "system"_s)); + RETURN_IF_EXCEPTION(throwScope, {}); } - if (UNLIKELY(!userValue || !userValue.isNumber())) { - throwTypeError(globalObject, throwScope, "Expected a number for the 'user' property"_s); - return JSC::JSValue::encode(JSC::jsUndefined()); - } + Bun::V::validateNumber(throwScope, globalObject, userValue, jsString(vm, String("prevValue.user"_s)), jsUndefined(), jsUndefined()); + RETURN_IF_EXCEPTION(throwScope, {}); - if (UNLIKELY(!systemValue || !systemValue.isNumber())) { - throwTypeError(globalObject, throwScope, "Expected a number for the 'system' property"_s); - return JSC::JSValue::encode(JSC::jsUndefined()); - } + Bun::V::validateNumber(throwScope, globalObject, systemValue, jsString(vm, String("prevValue.system"_s)), jsUndefined(), jsUndefined()); + RETURN_IF_EXCEPTION(throwScope, {}); double userComparator = userValue.toNumber(globalObject); double systemComparator = systemValue.toNumber(globalObject); - if (userComparator > JSC::maxSafeInteger() || userComparator < 0 || std::isnan(userComparator)) { - throwRangeError(globalObject, throwScope, "The 'user' property must be a number between 0 and 2^53"_s); - return JSC::JSValue::encode(JSC::jsUndefined()); + if (!(userComparator >= 0 && userComparator <= JSC::maxSafeInteger())) { + return Bun::ERR::INVALID_ARG_VALUE(throwScope, globalObject, "prevValue.user"_s, userValue, "is invalid"_s); } - if (systemComparator > JSC::maxSafeInteger() || systemComparator < 0 || std::isnan(systemComparator)) { - throwRangeError(globalObject, throwScope, "The 'system' property must be a number between 0 and 2^53"_s); - return JSC::JSValue::encode(JSC::jsUndefined()); + if (!(systemComparator >= 0 && systemComparator <= JSC::maxSafeInteger())) { + return Bun::ERR::INVALID_ARG_VALUE(throwScope, globalObject, "prevValue.system"_s, systemValue, "is invalid"_s); } user -= userComparator; diff --git a/test/js/node/test/parallel/process-cpuusage.test.js b/test/js/node/test/parallel/process-cpuusage.test.js new file mode 100644 index 0000000000..c3c1a92d91 --- /dev/null +++ b/test/js/node/test/parallel/process-cpuusage.test.js @@ -0,0 +1,110 @@ +//#FILE: test-process-cpuUsage.js +//#SHA1: 68c5aeede535139b8caa17340dcad82df9677047 +//----------------- +"use strict"; + +test("process.cpuUsage", () => { + const result = process.cpuUsage(); + + // Validate the result of calling with no previous value argument. + validateResult(result); + + // Validate the result of calling with a previous value argument. + validateResult(process.cpuUsage(result)); + + // Ensure the results are >= the previous. + let thisUsage; + let lastUsage = process.cpuUsage(); + for (let i = 0; i < 10; i++) { + thisUsage = process.cpuUsage(); + validateResult(thisUsage); + expect(thisUsage.user).toBeGreaterThanOrEqual(lastUsage.user); + expect(thisUsage.system).toBeGreaterThanOrEqual(lastUsage.system); + lastUsage = thisUsage; + } + + // Ensure that the diffs are >= 0. + let startUsage; + let diffUsage; + for (let i = 0; i < 10; i++) { + startUsage = process.cpuUsage(); + diffUsage = process.cpuUsage(startUsage); + validateResult(startUsage); + validateResult(diffUsage); + expect(diffUsage.user).toBeGreaterThanOrEqual(0); + expect(diffUsage.system).toBeGreaterThanOrEqual(0); + } + + // Ensure that an invalid shape for the previous value argument throws an error. + expect(() => process.cpuUsage(1)).toThrow( + expect.objectContaining({ + code: "ERR_INVALID_ARG_TYPE", + name: "TypeError", + message: expect.stringContaining(`The "previousValue" argument must be of type object. Received`), + }), + ); + + // Check invalid types. + [{}, { user: "a" }, { user: null, system: "c" }].forEach(value => { + expect(() => process.cpuUsage(value)).toThrow( + expect.objectContaining({ + code: "ERR_INVALID_ARG_TYPE", + name: "TypeError", + message: expect.stringContaining(`The "prevValue.user" argument must be of type number. Received`), + }), + ); + }); + + [ + { user: 3, system: "b" }, + { user: 3, system: null }, + ].forEach(value => { + expect(() => process.cpuUsage(value)).toThrow( + expect.objectContaining({ + code: "ERR_INVALID_ARG_TYPE", + name: "TypeError", + message: expect.stringContaining(`The "prevValue.system" argument must be of type number. Received`), + }), + ); + }); + + // Check invalid values. + [ + { user: -1, system: 2 }, + { user: Number.POSITIVE_INFINITY, system: 4 }, + ].forEach(value => { + expect(() => process.cpuUsage(value)).toThrow( + expect.objectContaining({ + code: "ERR_INVALID_ARG_VALUE", + name: "TypeError", + message: expect.stringContaining(`The argument 'prevValue.user' is invalid. Received`), + }), + ); + }); + + [ + { user: 3, system: -2 }, + { user: 5, system: Number.NEGATIVE_INFINITY }, + ].forEach(value => { + expect(() => process.cpuUsage(value)).toThrow( + expect.objectContaining({ + code: "ERR_INVALID_ARG_VALUE", + name: "TypeError", + message: expect.stringContaining(`The argument 'prevValue.system' is invalid. Received`), + }), + ); + }); +}); + +// Ensure that the return value is the expected shape. +function validateResult(result) { + expect(result).not.toBeNull(); + + expect(Number.isFinite(result.user)).toBe(true); + expect(Number.isFinite(result.system)).toBe(true); + + expect(result.user).toBeGreaterThanOrEqual(0); + expect(result.system).toBeGreaterThanOrEqual(0); +} + +//<#END_FILE: test-process-cpuUsage.js