@jsenv/test 3.0.10 → 3.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import os, { cpus, totalmem, availableParallelism } from "node:os";
1
+ import os, { cpus, release, totalmem, availableParallelism, freemem } from "node:os";
2
2
  import process$1, { cpuUsage, memoryUsage } from "node:process";
3
3
  import { readdir, chmod, stat, lstat, promises, readFile as readFile$1, writeFileSync as writeFileSync$1, mkdirSync, unlink, openSync, closeSync, rmdir, chmodSync, statSync, lstatSync, unlinkSync, readdirSync, rmdirSync, readFileSync, existsSync } from "node:fs";
4
4
  import { takeCoverage } from "node:v8";
@@ -1456,7 +1456,7 @@ const humanizeFileSize = (numberOfBytes, { decimals, short } = {}) => {
1456
1456
  return inspectBytes(numberOfBytes, { decimals, short });
1457
1457
  };
1458
1458
 
1459
- const humanizeMemoryUsage = (metricValue, { decimals, short } = {}) => {
1459
+ const humanizeMemory = (metricValue, { decimals, short } = {}) => {
1460
1460
  return inspectBytes(metricValue, { decimals, fixedDecimals: true, short });
1461
1461
  };
1462
1462
 
@@ -3374,9 +3374,9 @@ const startMeasuringTotalCpuUsage = () => {
3374
3374
  );
3375
3375
  previousCpuUsage = processCpuUsage;
3376
3376
  const thisProcessActiveMs = thisProcessSystemMs + thisProcessUserMs;
3377
- thisProcess.active = thisProcessActiveMs / overallActiveMs;
3378
- thisProcess.system = thisProcessSystemMs / overallSystemMs;
3379
- thisProcess.user = thisProcessUserMs / overallUserMs;
3377
+ thisProcess.active = thisProcessActiveMs / overallMsEllapsed;
3378
+ thisProcess.system = thisProcessSystemMs / overallMsEllapsed;
3379
+ thisProcess.user = thisProcessUserMs / overallMsEllapsed;
3380
3380
 
3381
3381
  if (samples.length === 10) {
3382
3382
  let index = 0;
@@ -4967,7 +4967,9 @@ const replaceUrls = (source, replace) => {
4967
4967
  const reporterList = ({
4968
4968
  animated = true,
4969
4969
  mockFluctuatingValues, // used for snapshot testing logs
4970
- showMemoryUsage = true,
4970
+ platformInfo,
4971
+ memoryUsage: memoryUsage$1,
4972
+ cpuUsage,
4971
4973
  spy = () => {
4972
4974
  return {
4973
4975
  write: (log) => {
@@ -4988,7 +4990,9 @@ const reporterList = ({
4988
4990
  process.exitCode !== 1;
4989
4991
 
4990
4992
  const logOptions = {
4991
- showMemoryUsage,
4993
+ platformInfo,
4994
+ memoryUsage: memoryUsage$1,
4995
+ cpuUsage,
4992
4996
  mockFluctuatingValues,
4993
4997
  group: false,
4994
4998
  intermediateSummary: !animatedLogEnabled,
@@ -5049,7 +5053,7 @@ const reporterList = ({
5049
5053
  });
5050
5054
  infos.push(ANSI.color(duration, ANSI.GREY));
5051
5055
  const memoryHeapUsed = memoryUsage().heapUsed;
5052
- const memoryHeapUsedFormatted = humanizeMemoryUsage(memoryHeapUsed, {
5056
+ const memoryHeapUsedFormatted = humanizeMemory(memoryHeapUsed, {
5053
5057
  short: true,
5054
5058
  decimals: 0,
5055
5059
  });
@@ -5100,8 +5104,10 @@ const reporterList = ({
5100
5104
  reporters.push(
5101
5105
  reporterList({
5102
5106
  animated: false,
5107
+ platformInfo,
5108
+ memoryUsage: memoryUsage$1,
5109
+ cpuUsage,
5103
5110
  mockFluctuatingValues, // used for snapshot testing logs
5104
- showMemoryUsage,
5105
5111
  spy: () => {
5106
5112
  let rawOutput = "";
5107
5113
 
@@ -5121,58 +5127,59 @@ const reporterList = ({
5121
5127
  };
5122
5128
 
5123
5129
  const renderIntro = (testPlanResult, logOptions) => {
5124
- const { counters } = testPlanResult;
5125
- const planified = counters.planified;
5126
- const { groups } = testPlanResult;
5127
- const groupNames = Object.keys(groups);
5128
-
5129
- if (planified === 0) {
5130
- return `${renderBigSection({
5131
- title: "nothing to execute",
5132
- content: "",
5133
- })}\n\n`;
5134
- }
5135
- if (planified === 1) {
5136
- const groupName = groupNames[0];
5137
- const groupInfo = groups[groupName];
5138
- return `${renderBigSection({
5139
- title: "1 execution to run",
5140
- content: `${groupName} (${getGroupRenderedName(groupInfo, logOptions)})`,
5141
- })}\n\n`;
5142
- }
5143
- if (groupNames.length === 1) {
5144
- const groupName = groupNames[0];
5145
- const groupInfo = groups[groupName];
5146
- return `${renderBigSection({
5147
- title: `${planified} executions to run`,
5148
- content: `${groupName} (${getGroupRenderedName(groupInfo, logOptions)})`,
5149
- })}\n\n`;
5150
- }
5151
-
5152
- let introLines = [];
5153
- for (const groupName of groupNames) {
5154
- const groupInfo = groups[groupName];
5155
- introLines.push(
5156
- `${groupInfo.count} with ${groupName} (${getGroupRenderedName(
5157
- groupInfo,
5158
- logOptions,
5159
- )})`,
5160
- );
5130
+ const lines = [];
5131
+ if (logOptions.platformInfo) {
5132
+ {
5133
+ let osLine = `os: `;
5134
+ if (logOptions.mockFluctuatingValues) {
5135
+ osLine += `os@<mock>`;
5136
+ } else {
5137
+ osLine += `${testPlanResult.os.name}@${testPlanResult.os.version}`;
5138
+ }
5139
+ osLine += renderDetails({
5140
+ cpu: logOptions.mockFluctuatingValues
5141
+ ? "<mock>"
5142
+ : testPlanResult.os.availableCpu,
5143
+ memory: logOptions.mockFluctuatingValues
5144
+ ? "<mock>GB"
5145
+ : humanizeMemory(testPlanResult.os.availableMemory, {
5146
+ short: true,
5147
+ decimals: 0,
5148
+ }),
5149
+ });
5150
+ lines.push(osLine);
5151
+ }
5152
+ {
5153
+ const process = logOptions.mockFluctuatingValues
5154
+ ? `node@mock`
5155
+ : `${testPlanResult.process.name}@${testPlanResult.process.version}`;
5156
+ let processLine = `process: ${process}`;
5157
+ lines.push(processLine);
5158
+ }
5159
+ }
5160
+
5161
+ const directory = logOptions.mockFluctuatingValues
5162
+ ? "/mock/"
5163
+ : urlToFileSystemPath(testPlanResult.rootDirectoryUrl);
5164
+ const numberOfFiles = Object.keys(testPlanResult.results).length;
5165
+ let fileFoundLine = "";
5166
+ if (numberOfFiles === 0) {
5167
+ fileFoundLine += `no file matching "testPlan" in ${directory}:
5168
+ ${testPlanResult.patterns.join("\n")}`;
5169
+ } else if (numberOfFiles === 1) {
5170
+ fileFoundLine += `1 file matching "testPlan" in ${directory}`;
5171
+ } else {
5172
+ fileFoundLine += `${numberOfFiles} files matching "testPlan" in ${directory}`;
5161
5173
  }
5174
+
5175
+ lines.push(fileFoundLine);
5176
+
5162
5177
  return `${renderBigSection({
5163
- title: `${planified} executions to run`,
5164
- content: introLines.join("\n"),
5178
+ title: "execution start",
5179
+ content: lines.join("\n"),
5165
5180
  })}\n\n`;
5166
5181
  };
5167
5182
 
5168
- const getGroupRenderedName = (groupInfo, logOptions) => {
5169
- let { runtimeName, runtimeVersion } = groupInfo;
5170
- if (logOptions.mockFluctuatingValues && groupInfo.runtimeType === "node") {
5171
- runtimeVersion = "<mock>";
5172
- }
5173
- return `${runtimeName}@${runtimeVersion}`;
5174
- };
5175
-
5176
5183
  const renderExecutionLog = (execution, logOptions) => {
5177
5184
  let log = "";
5178
5185
  // label
@@ -5227,10 +5234,10 @@ const renderExecutionLabel = (execution, logOptions) => {
5227
5234
  : humanizeDuration(duration, { short: true });
5228
5235
  infos.push(ANSI.color(durationFormatted, ANSI.GREY));
5229
5236
  }
5230
- if (logOptions.showMemoryUsage && typeof memoryUsage === "number") {
5237
+ if (logOptions.memoryUsage && typeof memoryUsage === "number") {
5231
5238
  const memoryUsageFormatted = logOptions.mockFluctuatingValues
5232
5239
  ? `<mock>MB`
5233
- : humanizeMemoryUsage(memoryUsage, { short: true });
5240
+ : humanizeMemory(memoryUsage, { short: true });
5234
5241
  infos.push(ANSI.color(memoryUsageFormatted, ANSI.GREY));
5235
5242
  }
5236
5243
  if (infos.length) {
@@ -5492,55 +5499,87 @@ const renderErrors = (execution, logOptions) => {
5492
5499
  };
5493
5500
 
5494
5501
  const renderOutro = (testPlanResult, logOptions = {}) => {
5495
- let finalSummary = "";
5502
+ const lines = [];
5496
5503
  const { counters } = testPlanResult;
5497
5504
  const { planified } = counters;
5498
5505
 
5499
- if (planified === 1) {
5500
- finalSummary += `1 execution: `;
5506
+ let executionLine = "";
5507
+ if (planified === 0) {
5508
+ executionLine += `no execution`;
5509
+ } else if (planified === 1) {
5510
+ executionLine += `1 execution: `;
5501
5511
  } else {
5502
- finalSummary += `${planified} executions: `;
5512
+ executionLine += `${planified} executions: `;
5503
5513
  }
5504
- finalSummary += renderStatusRepartition(counters);
5514
+ executionLine += renderStatusRepartition(counters);
5515
+ lines.push(executionLine);
5505
5516
 
5506
- let durationLog = ``;
5517
+ let durationLine = `duration: `;
5507
5518
  const { timings } = testPlanResult;
5508
5519
  if (logOptions.mockFluctuatingValues) {
5509
- durationLog += "<mock>s";
5520
+ durationLine += "<mock>s";
5510
5521
  } else {
5511
- durationLog += humanizeDuration(timings.end, { short: true });
5522
+ durationLine += humanizeDuration(timings.end, { short: true });
5512
5523
  const namedTimings = {
5513
- setup: timings.executionStart,
5514
- execution: timings.executionEnd,
5515
- teardown: timings.teardownEnd - timings.executionEnd,
5524
+ setup: humanizeTiming(timings.executionStart),
5525
+ execution: humanizeTiming(timings.executionEnd),
5526
+ teardown: humanizeTiming(timings.teardownEnd - timings.executionEnd),
5516
5527
  ...(testPlanResult.coverage
5517
- ? { coverage: timings.coverageTeardownEnd - timings.teardownEnd }
5528
+ ? {
5529
+ coverage: humanizeTiming(
5530
+ timings.coverageTeardownEnd - timings.teardownEnd,
5531
+ ),
5532
+ }
5518
5533
  : {}),
5519
5534
  };
5520
- const timingDetails = [];
5521
- for (const key of Object.keys(namedTimings)) {
5522
- const value = namedTimings[key];
5523
- const timingDuration = humanizeDuration(value, { short: true });
5524
- const timingString = `${ANSI.color(`${key}:`, ANSI.GREY)} ${ANSI.color(
5525
- timingDuration,
5526
- ANSI.GREY,
5527
- )}`;
5528
- timingDetails.push(ANSI.color(timingString, ANSI.GREY));
5529
- }
5530
- if (timingDetails.length) {
5531
- durationLog += ` ${ANSI.color("(", ANSI.GREY)}${timingDetails.join(
5532
- ANSI.color(", ", ANSI.GREY),
5533
- )}${ANSI.color(")", ANSI.GREY)}`;
5534
- }
5535
+ durationLine += renderDetails(namedTimings);
5536
+ }
5537
+ lines.push(durationLine);
5538
+
5539
+ if (logOptions.cpuUsage) {
5540
+ const processCpuUsage = testPlanResult.cpuUsage.process;
5541
+ let cpuUsageLine = "cpu: ";
5542
+ cpuUsageLine += `${humanizeProcessCpuUsage(processCpuUsage.end)}`;
5543
+ cpuUsageLine += renderDetails({
5544
+ med: humanizeProcessCpuUsage(processCpuUsage.median),
5545
+ min: humanizeProcessCpuUsage(processCpuUsage.min),
5546
+ max: humanizeProcessCpuUsage(processCpuUsage.max),
5547
+ });
5548
+ lines.push(cpuUsageLine);
5549
+ }
5550
+ if (logOptions.memoryUsage) {
5551
+ const processMemoryUsage = testPlanResult.memoryUsage.process;
5552
+ let memoryUsageLine = "memory: ";
5553
+ memoryUsageLine += `${humanizeProcessMemoryUsage(processMemoryUsage.end)}`;
5554
+ memoryUsageLine += renderDetails({
5555
+ med: humanizeProcessMemoryUsage(processMemoryUsage.median),
5556
+ min: humanizeProcessMemoryUsage(processMemoryUsage.min),
5557
+ max: humanizeProcessMemoryUsage(processMemoryUsage.max),
5558
+ });
5559
+ lines.push(memoryUsageLine);
5535
5560
  }
5536
- finalSummary += `\nduration: ${durationLog}`;
5537
5561
 
5538
- return `\n${renderBigSection({ title: "summary", content: finalSummary })}\n`;
5562
+ return `\n${renderBigSection({ title: "summary", content: lines.join("\n") })}\n`;
5563
+ };
5564
+
5565
+ const humanizeTiming = (value) => {
5566
+ return humanizeDuration(value, { short: true });
5567
+ };
5568
+
5569
+ const humanizeProcessCpuUsage = (ratio) => {
5570
+ const percentageAsNumber = ratio * 100;
5571
+ const percentageAsNumberRounded = Math.round(percentageAsNumber);
5572
+ const percentage = `${percentageAsNumberRounded}%`;
5573
+ return percentage;
5574
+ };
5575
+
5576
+ const humanizeProcessMemoryUsage = (value) => {
5577
+ return humanizeMemory(value, { short: true, decimals: 0 });
5539
5578
  };
5540
5579
 
5541
5580
  const renderStatusRepartition = (counters, { showProgression } = {}) => {
5542
5581
  if (counters.planified === 0) {
5543
- return `nothing to run`;
5582
+ return ``;
5544
5583
  }
5545
5584
  if (counters.aborted === counters.planified) {
5546
5585
  return `all ${ANSI.color(`aborted`, COLOR_ABORTED)}`;
@@ -5627,6 +5666,29 @@ const renderSection = ({
5627
5666
  return section;
5628
5667
  };
5629
5668
 
5669
+ const renderDetails = (data) => {
5670
+ const details = [];
5671
+ for (const key of Object.keys(data)) {
5672
+ const value = data[key];
5673
+ let valueString = "";
5674
+ valueString += ANSI.color(`${key}:`, ANSI.GREY);
5675
+ const useNonGreyAnsiColor =
5676
+ typeof value === "string" && value.includes("\x1b");
5677
+ valueString += " ";
5678
+ valueString += useNonGreyAnsiColor ? value : ANSI.color(value, ANSI.GREY);
5679
+ details.push(valueString);
5680
+ }
5681
+ if (details.length === 0) {
5682
+ return "";
5683
+ }
5684
+
5685
+ let string = "";
5686
+ string += ` ${ANSI.color("(", ANSI.GREY)}`;
5687
+ string += details.join(ANSI.color(", ", ANSI.GREY));
5688
+ string += ANSI.color(")", ANSI.GREY);
5689
+ return string;
5690
+ };
5691
+
5630
5692
  /*
5631
5693
  *
5632
5694
  */
@@ -5648,6 +5710,9 @@ const logsDefault = {
5648
5710
  level: "info",
5649
5711
  type: "list",
5650
5712
  animated: true,
5713
+ platformInfo: false,
5714
+ memoryUsage: false,
5715
+ cpuUsage: false,
5651
5716
  fileUrl: undefined,
5652
5717
  };
5653
5718
  const githubCheckDefault = {
@@ -5744,12 +5809,63 @@ const executeTestPlan = async ({
5744
5809
  });
5745
5810
  }
5746
5811
 
5747
- const timingOrigin = Date.now();
5812
+ const cpuUsage = startMeasuringTotalCpuUsage();
5813
+ operation.addEndCallback(cpuUsage.stop);
5814
+ const processCpuUsageMonitoring = startMonitoringMetric(() => {
5815
+ return cpuUsage.thisProcess.active;
5816
+ });
5817
+ const osCpuUsageMonitoring = startMonitoringMetric(() => {
5818
+ return cpuUsage.overall.active;
5819
+ });
5820
+ const processMemoryUsageMonitoring = startMonitoringMetric(() => {
5821
+ return memoryUsage().rss;
5822
+ });
5823
+ const osMemoryUsageMonitoring = startMonitoringMetric(() => {
5824
+ const total = totalmem();
5825
+ const free = freemem();
5826
+ return total - free;
5827
+ });
5828
+
5829
+ const timingsOrigin = Date.now();
5748
5830
  const takeTiming = () => {
5749
- return Date.now() - timingOrigin;
5831
+ return Date.now() - timingsOrigin;
5750
5832
  };
5751
5833
  const testPlanResult = {
5834
+ os: {
5835
+ name:
5836
+ process.platform === "darwin"
5837
+ ? "mac"
5838
+ : process.platform === "win32" || process.platform === "win64"
5839
+ ? "windows"
5840
+ : process.platform === "linux"
5841
+ ? "linux"
5842
+ : "other",
5843
+ version: release(),
5844
+ availableCpu: countAvailableCpus(),
5845
+ availableMemory: totalmem(),
5846
+ },
5847
+ process: {
5848
+ name: "node",
5849
+ version: process.version.slice(1),
5850
+ },
5851
+ memoryUsage: {
5852
+ os: osMemoryUsageMonitoring.info,
5853
+ process: processMemoryUsageMonitoring.info,
5854
+ },
5855
+ cpuUsage: {
5856
+ os: osCpuUsageMonitoring.info,
5857
+ process: processCpuUsageMonitoring.info,
5858
+ },
5859
+ timings: {
5860
+ origin: timingsOrigin,
5861
+ executionStart: null,
5862
+ executionEnd: null,
5863
+ teardownEnd: null,
5864
+ coverageTeardownEnd: null,
5865
+ end: null,
5866
+ },
5752
5867
  rootDirectoryUrl: String(rootDirectoryUrl),
5868
+ patterns: Object.keys(testPlan),
5753
5869
  groups: {},
5754
5870
  counters: {
5755
5871
  planified: 0,
@@ -5766,14 +5882,6 @@ const executeTestPlan = async ({
5766
5882
  },
5767
5883
  aborted: false,
5768
5884
  failed: false,
5769
- timings: {
5770
- origin: timingOrigin,
5771
- executionStart: null,
5772
- executionEnd: null,
5773
- teardownEnd: null,
5774
- coverageTeardownEnd: null,
5775
- end: null,
5776
- },
5777
5885
  coverage: null,
5778
5886
  results: {},
5779
5887
  };
@@ -5801,9 +5909,6 @@ const executeTestPlan = async ({
5801
5909
  let finalizeCoverage;
5802
5910
 
5803
5911
  try {
5804
- const cpuUsage = startMeasuringTotalCpuUsage();
5805
- operation.addEndCallback(cpuUsage.stop);
5806
-
5807
5912
  let logger;
5808
5913
  const runtimeInfo = {
5809
5914
  someNeedsServer: false,
@@ -5834,6 +5939,10 @@ const executeTestPlan = async ({
5834
5939
 
5835
5940
  if (logs.type === "list" && logger.levels.info) {
5836
5941
  const listReporterOptions = {
5942
+ mockFluctuatingValues: logs.mockFluctuatingValues,
5943
+ platformInfo: logs.platformInfo,
5944
+ memoryUsage: logs.memoryUsage,
5945
+ cpuUsage: logs.cpuUsage,
5837
5946
  animated: logger.levels.debug ? false : logs.animated,
5838
5947
  fileUrl:
5839
5948
  logs.fileUrl === undefined
@@ -5892,8 +6001,8 @@ const executeTestPlan = async ({
5892
6001
  const max = parallel.max;
5893
6002
  if (typeof max === "string") {
5894
6003
  const maxAsRatio = assertPercentageAndConvertToRatio(max);
5895
- const availableCpus = countAvailableCpus();
5896
- parallel.max = Math.round(maxAsRatio * availableCpus) || 1;
6004
+ parallel.max =
6005
+ Math.round(maxAsRatio * testPlanResult.os.availableCpu) || 1;
5897
6006
  } else if (typeof max === "number") {
5898
6007
  if (max < 1) {
5899
6008
  parallel.max = 1;
@@ -5907,8 +6016,9 @@ const executeTestPlan = async ({
5907
6016
  const maxMemory = parallel.maxMemory;
5908
6017
  if (typeof maxMemory === "string") {
5909
6018
  const maxMemoryAsRatio = assertPercentageAndConvertToRatio(maxMemory);
5910
- const totalMemory = totalmem();
5911
- parallel.maxMemory = Math.round(maxMemoryAsRatio * totalMemory);
6019
+ parallel.maxMemory = Math.round(
6020
+ maxMemoryAsRatio * testPlanResult.os.availableMemory,
6021
+ );
5912
6022
  } else if (typeof maxMemory !== "number") {
5913
6023
  throw new TypeError(
5914
6024
  `parallel.maxMemory must be a number or a percentage, got ${maxMemory}`,
@@ -6446,17 +6556,22 @@ To fix this warning:
6446
6556
  // if nothing is executing these limitations don't apply
6447
6557
  executionExecutingSet.size > 0
6448
6558
  ) {
6449
- const memoryUsedByThisProcess = memoryUsage().rss;
6450
- if (memoryUsedByThisProcess > parallel.maxMemory) {
6559
+ if (processMemoryUsageMonitoring.measure() > parallel.maxMemory) {
6451
6560
  // retry after Xms in case memory usage decreases
6452
- const promise = operation.wait(200);
6561
+ const promise = (async () => {
6562
+ await operation.wait(200);
6563
+ await startAsMuchAsPossible();
6564
+ })();
6453
6565
  promises.push(promise);
6454
6566
  break;
6455
6567
  }
6456
6568
 
6457
- if (cpuUsage.thisProcess.active > parallel.maxCpu) {
6569
+ if (processCpuUsageMonitoring.measure() > parallel.maxCpu) {
6458
6570
  // retry after Xms in case cpu usage decreases
6459
- const promise = operation.wait(200);
6571
+ const promise = (async () => {
6572
+ await operation.wait(200);
6573
+ await startAsMuchAsPossible();
6574
+ })();
6460
6575
  promises.push(promise);
6461
6576
  break;
6462
6577
  }
@@ -6480,7 +6595,6 @@ To fix this warning:
6480
6595
  if (promises.length) {
6481
6596
  await Promise.all(promises);
6482
6597
  promises.length = 0;
6483
- await startAsMuchAsPossible();
6484
6598
  }
6485
6599
  };
6486
6600
 
@@ -6559,6 +6673,11 @@ To fix this warning:
6559
6673
  timings.coverageTeardownEnd = takeTiming();
6560
6674
  timings.end = takeTiming();
6561
6675
 
6676
+ osMemoryUsageMonitoring.end();
6677
+ processMemoryUsageMonitoring.end();
6678
+ osCpuUsageMonitoring.end();
6679
+ processCpuUsageMonitoring.end();
6680
+
6562
6681
  afterEachCallbackSet.clear();
6563
6682
  afterEachInOrderCallbackSet.clear();
6564
6683
  for (const afterAllCallback of afterAllCallbackSet) {
@@ -6571,6 +6690,51 @@ To fix this warning:
6571
6690
  return testPlanResult;
6572
6691
  };
6573
6692
 
6693
+ const startMonitoringMetric = (measure) => {
6694
+ const metrics = [];
6695
+ const takeMeasure = () => {
6696
+ const value = measure();
6697
+ metrics.push(value);
6698
+ return value;
6699
+ };
6700
+
6701
+ const info = {
6702
+ start: takeMeasure(),
6703
+ min: null,
6704
+ max: null,
6705
+ median: null,
6706
+ end: null,
6707
+ };
6708
+ return {
6709
+ info,
6710
+ measure: takeMeasure,
6711
+ end: () => {
6712
+ info.end = takeMeasure();
6713
+ metrics.sort((a, b) => a - b);
6714
+ info.min = metrics[0];
6715
+ info.max = metrics[metrics.length - 1];
6716
+ info.median = medianFromSortedArray(metrics);
6717
+ metrics.length = 0;
6718
+ },
6719
+ };
6720
+ };
6721
+
6722
+ const medianFromSortedArray = (array) => {
6723
+ const length = array.length;
6724
+ const isOdd = length % 2 === 1;
6725
+ if (isOdd) {
6726
+ const medianNumberIndex = (length - 1) / 2;
6727
+ const medianNumber = array[medianNumberIndex];
6728
+ return medianNumber;
6729
+ }
6730
+ const rightMiddleNumberIndex = length / 2;
6731
+ const leftMiddleNumberIndex = rightMiddleNumberIndex - 1;
6732
+ const leftMiddleNumber = array[leftMiddleNumberIndex];
6733
+ const rightMiddleNumber = array[rightMiddleNumberIndex];
6734
+ const medianNumber = (leftMiddleNumber + rightMiddleNumber) / 2;
6735
+ return medianNumber;
6736
+ };
6737
+
6574
6738
  const countAvailableCpus = () => {
6575
6739
  if (typeof availableParallelism === "function") {
6576
6740
  return availableParallelism();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/test",
3
- "version": "3.0.10",
3
+ "version": "3.0.12",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -38,13 +38,13 @@
38
38
  "dependencies": {
39
39
  "@c88/v8-coverage": "0.1.1",
40
40
  "@jsenv/abort": "4.3.0",
41
- "@jsenv/ast": "6.0.2",
42
- "@jsenv/filesystem": "4.6.4",
43
- "@jsenv/github-check-run": "0.1.9",
41
+ "@jsenv/ast": "6.0.3",
42
+ "@jsenv/filesystem": "4.6.5",
43
+ "@jsenv/github-check-run": "0.1.10",
44
44
  "@jsenv/humanize": "1.0.0",
45
- "@jsenv/plugin-supervisor": "1.4.2",
45
+ "@jsenv/plugin-supervisor": "1.4.3",
46
46
  "@jsenv/url-meta": "8.4.0",
47
- "@jsenv/urls": "2.2.2",
47
+ "@jsenv/urls": "2.2.3",
48
48
  "@jsenv/utils": "2.1.1",
49
49
  "istanbul-lib-coverage": "3.2.2",
50
50
  "istanbul-lib-instrument": "6.0.1",
@@ -2,7 +2,13 @@
2
2
  *
3
3
  */
4
4
 
5
- import { cpus, availableParallelism, totalmem } from "node:os";
5
+ import {
6
+ release,
7
+ cpus,
8
+ availableParallelism,
9
+ totalmem,
10
+ freemem,
11
+ } from "node:os";
6
12
  import { memoryUsage } from "node:process";
7
13
  import { existsSync } from "node:fs";
8
14
  import { takeCoverage } from "node:v8";
@@ -44,6 +50,9 @@ const logsDefault = {
44
50
  level: "info",
45
51
  type: "list",
46
52
  animated: true,
53
+ platformInfo: false,
54
+ memoryUsage: false,
55
+ cpuUsage: false,
47
56
  fileUrl: undefined,
48
57
  };
49
58
  const githubCheckDefault = {
@@ -140,12 +149,63 @@ export const executeTestPlan = async ({
140
149
  });
141
150
  }
142
151
 
143
- const timingOrigin = Date.now();
152
+ const cpuUsage = startMeasuringTotalCpuUsage();
153
+ operation.addEndCallback(cpuUsage.stop);
154
+ const processCpuUsageMonitoring = startMonitoringMetric(() => {
155
+ return cpuUsage.thisProcess.active;
156
+ });
157
+ const osCpuUsageMonitoring = startMonitoringMetric(() => {
158
+ return cpuUsage.overall.active;
159
+ });
160
+ const processMemoryUsageMonitoring = startMonitoringMetric(() => {
161
+ return memoryUsage().rss;
162
+ });
163
+ const osMemoryUsageMonitoring = startMonitoringMetric(() => {
164
+ const total = totalmem();
165
+ const free = freemem();
166
+ return total - free;
167
+ });
168
+
169
+ const timingsOrigin = Date.now();
144
170
  const takeTiming = () => {
145
- return Date.now() - timingOrigin;
171
+ return Date.now() - timingsOrigin;
146
172
  };
147
173
  const testPlanResult = {
174
+ os: {
175
+ name:
176
+ process.platform === "darwin"
177
+ ? "mac"
178
+ : process.platform === "win32" || process.platform === "win64"
179
+ ? "windows"
180
+ : process.platform === "linux"
181
+ ? "linux"
182
+ : "other",
183
+ version: release(),
184
+ availableCpu: countAvailableCpus(),
185
+ availableMemory: totalmem(),
186
+ },
187
+ process: {
188
+ name: "node",
189
+ version: process.version.slice(1),
190
+ },
191
+ memoryUsage: {
192
+ os: osMemoryUsageMonitoring.info,
193
+ process: processMemoryUsageMonitoring.info,
194
+ },
195
+ cpuUsage: {
196
+ os: osCpuUsageMonitoring.info,
197
+ process: processCpuUsageMonitoring.info,
198
+ },
199
+ timings: {
200
+ origin: timingsOrigin,
201
+ executionStart: null,
202
+ executionEnd: null,
203
+ teardownEnd: null,
204
+ coverageTeardownEnd: null,
205
+ end: null,
206
+ },
148
207
  rootDirectoryUrl: String(rootDirectoryUrl),
208
+ patterns: Object.keys(testPlan),
149
209
  groups: {},
150
210
  counters: {
151
211
  planified: 0,
@@ -162,14 +222,6 @@ export const executeTestPlan = async ({
162
222
  },
163
223
  aborted: false,
164
224
  failed: false,
165
- timings: {
166
- origin: timingOrigin,
167
- executionStart: null,
168
- executionEnd: null,
169
- teardownEnd: null,
170
- coverageTeardownEnd: null,
171
- end: null,
172
- },
173
225
  coverage: null,
174
226
  results: {},
175
227
  };
@@ -197,9 +249,6 @@ export const executeTestPlan = async ({
197
249
  let finalizeCoverage;
198
250
 
199
251
  try {
200
- const cpuUsage = startMeasuringTotalCpuUsage();
201
- operation.addEndCallback(cpuUsage.stop);
202
-
203
252
  let logger;
204
253
  const runtimeInfo = {
205
254
  someNeedsServer: false,
@@ -230,6 +279,10 @@ export const executeTestPlan = async ({
230
279
 
231
280
  if (logs.type === "list" && logger.levels.info) {
232
281
  const listReporterOptions = {
282
+ mockFluctuatingValues: logs.mockFluctuatingValues,
283
+ platformInfo: logs.platformInfo,
284
+ memoryUsage: logs.memoryUsage,
285
+ cpuUsage: logs.cpuUsage,
233
286
  animated: logger.levels.debug ? false : logs.animated,
234
287
  fileUrl:
235
288
  logs.fileUrl === undefined
@@ -288,8 +341,8 @@ export const executeTestPlan = async ({
288
341
  const max = parallel.max;
289
342
  if (typeof max === "string") {
290
343
  const maxAsRatio = assertPercentageAndConvertToRatio(max);
291
- const availableCpus = countAvailableCpus();
292
- parallel.max = Math.round(maxAsRatio * availableCpus) || 1;
344
+ parallel.max =
345
+ Math.round(maxAsRatio * testPlanResult.os.availableCpu) || 1;
293
346
  } else if (typeof max === "number") {
294
347
  if (max < 1) {
295
348
  parallel.max = 1;
@@ -303,8 +356,9 @@ export const executeTestPlan = async ({
303
356
  const maxMemory = parallel.maxMemory;
304
357
  if (typeof maxMemory === "string") {
305
358
  const maxMemoryAsRatio = assertPercentageAndConvertToRatio(maxMemory);
306
- const totalMemory = totalmem();
307
- parallel.maxMemory = Math.round(maxMemoryAsRatio * totalMemory);
359
+ parallel.maxMemory = Math.round(
360
+ maxMemoryAsRatio * testPlanResult.os.availableMemory,
361
+ );
308
362
  } else if (typeof maxMemory !== "number") {
309
363
  throw new TypeError(
310
364
  `parallel.maxMemory must be a number or a percentage, got ${maxMemory}`,
@@ -842,17 +896,22 @@ To fix this warning:
842
896
  // if nothing is executing these limitations don't apply
843
897
  executionExecutingSet.size > 0
844
898
  ) {
845
- const memoryUsedByThisProcess = memoryUsage().rss;
846
- if (memoryUsedByThisProcess > parallel.maxMemory) {
899
+ if (processMemoryUsageMonitoring.measure() > parallel.maxMemory) {
847
900
  // retry after Xms in case memory usage decreases
848
- const promise = operation.wait(200);
901
+ const promise = (async () => {
902
+ await operation.wait(200);
903
+ await startAsMuchAsPossible();
904
+ })();
849
905
  promises.push(promise);
850
906
  break;
851
907
  }
852
908
 
853
- if (cpuUsage.thisProcess.active > parallel.maxCpu) {
909
+ if (processCpuUsageMonitoring.measure() > parallel.maxCpu) {
854
910
  // retry after Xms in case cpu usage decreases
855
- const promise = operation.wait(200);
911
+ const promise = (async () => {
912
+ await operation.wait(200);
913
+ await startAsMuchAsPossible();
914
+ })();
856
915
  promises.push(promise);
857
916
  break;
858
917
  }
@@ -876,7 +935,6 @@ To fix this warning:
876
935
  if (promises.length) {
877
936
  await Promise.all(promises);
878
937
  promises.length = 0;
879
- await startAsMuchAsPossible();
880
938
  }
881
939
  };
882
940
 
@@ -956,6 +1014,11 @@ To fix this warning:
956
1014
  timings.coverageTeardownEnd = takeTiming();
957
1015
  timings.end = takeTiming();
958
1016
 
1017
+ osMemoryUsageMonitoring.end();
1018
+ processMemoryUsageMonitoring.end();
1019
+ osCpuUsageMonitoring.end();
1020
+ processCpuUsageMonitoring.end();
1021
+
959
1022
  afterEachCallbackSet.clear();
960
1023
  afterEachInOrderCallbackSet.clear();
961
1024
  for (const afterAllCallback of afterAllCallbackSet) {
@@ -968,6 +1031,51 @@ To fix this warning:
968
1031
  return testPlanResult;
969
1032
  };
970
1033
 
1034
+ const startMonitoringMetric = (measure) => {
1035
+ const metrics = [];
1036
+ const takeMeasure = () => {
1037
+ const value = measure();
1038
+ metrics.push(value);
1039
+ return value;
1040
+ };
1041
+
1042
+ const info = {
1043
+ start: takeMeasure(),
1044
+ min: null,
1045
+ max: null,
1046
+ median: null,
1047
+ end: null,
1048
+ };
1049
+ return {
1050
+ info,
1051
+ measure: takeMeasure,
1052
+ end: () => {
1053
+ info.end = takeMeasure();
1054
+ metrics.sort((a, b) => a - b);
1055
+ info.min = metrics[0];
1056
+ info.max = metrics[metrics.length - 1];
1057
+ info.median = medianFromSortedArray(metrics);
1058
+ metrics.length = 0;
1059
+ },
1060
+ };
1061
+ };
1062
+
1063
+ const medianFromSortedArray = (array) => {
1064
+ const length = array.length;
1065
+ const isOdd = length % 2 === 1;
1066
+ if (isOdd) {
1067
+ const medianNumberIndex = (length - 1) / 2;
1068
+ const medianNumber = array[medianNumberIndex];
1069
+ return medianNumber;
1070
+ }
1071
+ const rightMiddleNumberIndex = length / 2;
1072
+ const leftMiddleNumberIndex = rightMiddleNumberIndex - 1;
1073
+ const leftMiddleNumber = array[leftMiddleNumberIndex];
1074
+ const rightMiddleNumber = array[rightMiddleNumberIndex];
1075
+ const medianNumber = (leftMiddleNumber + rightMiddleNumber) / 2;
1076
+ return medianNumber;
1077
+ };
1078
+
971
1079
  const countAvailableCpus = () => {
972
1080
  if (typeof availableParallelism === "function") {
973
1081
  return availableParallelism();
@@ -1,13 +1,14 @@
1
- import { memoryUsage } from "node:process";
1
+ import { memoryUsage as processMemoryUsage } from "node:process";
2
2
  import stripAnsi from "strip-ansi";
3
3
  import { writeFileSync } from "@jsenv/filesystem";
4
4
  import {
5
5
  createDynamicLog,
6
6
  humanizeDuration,
7
- humanizeMemoryUsage,
7
+ humanizeMemory,
8
8
  ANSI,
9
9
  UNICODE,
10
10
  } from "@jsenv/humanize";
11
+ import { urlToFileSystemPath } from "@jsenv/urls";
11
12
 
12
13
  import { formatErrorForTerminal } from "../format_error_for_terminal.js";
13
14
 
@@ -36,7 +37,9 @@ import { formatErrorForTerminal } from "../format_error_for_terminal.js";
36
37
  export const reporterList = ({
37
38
  animated = true,
38
39
  mockFluctuatingValues, // used for snapshot testing logs
39
- showMemoryUsage = true,
40
+ platformInfo,
41
+ memoryUsage,
42
+ cpuUsage,
40
43
  spy = () => {
41
44
  return {
42
45
  write: (log) => {
@@ -57,7 +60,9 @@ export const reporterList = ({
57
60
  process.exitCode !== 1;
58
61
 
59
62
  const logOptions = {
60
- showMemoryUsage,
63
+ platformInfo,
64
+ memoryUsage,
65
+ cpuUsage,
61
66
  mockFluctuatingValues,
62
67
  group: false,
63
68
  intermediateSummary: !animatedLogEnabled,
@@ -117,8 +122,8 @@ export const reporterList = ({
117
122
  rounded: false,
118
123
  });
119
124
  infos.push(ANSI.color(duration, ANSI.GREY));
120
- const memoryHeapUsed = memoryUsage().heapUsed;
121
- const memoryHeapUsedFormatted = humanizeMemoryUsage(memoryHeapUsed, {
125
+ const memoryHeapUsed = processMemoryUsage().heapUsed;
126
+ const memoryHeapUsedFormatted = humanizeMemory(memoryHeapUsed, {
122
127
  short: true,
123
128
  decimals: 0,
124
129
  });
@@ -169,8 +174,10 @@ export const reporterList = ({
169
174
  reporters.push(
170
175
  reporterList({
171
176
  animated: false,
177
+ platformInfo,
178
+ memoryUsage,
179
+ cpuUsage,
172
180
  mockFluctuatingValues, // used for snapshot testing logs
173
- showMemoryUsage,
174
181
  spy: () => {
175
182
  let rawOutput = "";
176
183
 
@@ -190,58 +197,59 @@ export const reporterList = ({
190
197
  };
191
198
 
192
199
  const renderIntro = (testPlanResult, logOptions) => {
193
- const { counters } = testPlanResult;
194
- const planified = counters.planified;
195
- const { groups } = testPlanResult;
196
- const groupNames = Object.keys(groups);
200
+ const lines = [];
201
+ if (logOptions.platformInfo) {
202
+ os_line: {
203
+ let osLine = `os: `;
204
+ if (logOptions.mockFluctuatingValues) {
205
+ osLine += `os@<mock>`;
206
+ } else {
207
+ osLine += `${testPlanResult.os.name}@${testPlanResult.os.version}`;
208
+ }
209
+ osLine += renderDetails({
210
+ cpu: logOptions.mockFluctuatingValues
211
+ ? "<mock>"
212
+ : testPlanResult.os.availableCpu,
213
+ memory: logOptions.mockFluctuatingValues
214
+ ? "<mock>GB"
215
+ : humanizeMemory(testPlanResult.os.availableMemory, {
216
+ short: true,
217
+ decimals: 0,
218
+ }),
219
+ });
220
+ lines.push(osLine);
221
+ }
222
+ process_line: {
223
+ const process = logOptions.mockFluctuatingValues
224
+ ? `node@mock`
225
+ : `${testPlanResult.process.name}@${testPlanResult.process.version}`;
226
+ let processLine = `process: ${process}`;
227
+ lines.push(processLine);
228
+ }
229
+ }
197
230
 
198
- if (planified === 0) {
199
- return `${renderBigSection({
200
- title: "nothing to execute",
201
- content: "",
202
- })}\n\n`;
203
- }
204
- if (planified === 1) {
205
- const groupName = groupNames[0];
206
- const groupInfo = groups[groupName];
207
- return `${renderBigSection({
208
- title: "1 execution to run",
209
- content: `${groupName} (${getGroupRenderedName(groupInfo, logOptions)})`,
210
- })}\n\n`;
211
- }
212
- if (groupNames.length === 1) {
213
- const groupName = groupNames[0];
214
- const groupInfo = groups[groupName];
215
- return `${renderBigSection({
216
- title: `${planified} executions to run`,
217
- content: `${groupName} (${getGroupRenderedName(groupInfo, logOptions)})`,
218
- })}\n\n`;
219
- }
220
-
221
- let introLines = [];
222
- for (const groupName of groupNames) {
223
- const groupInfo = groups[groupName];
224
- introLines.push(
225
- `${groupInfo.count} with ${groupName} (${getGroupRenderedName(
226
- groupInfo,
227
- logOptions,
228
- )})`,
229
- );
231
+ const directory = logOptions.mockFluctuatingValues
232
+ ? "/mock/"
233
+ : urlToFileSystemPath(testPlanResult.rootDirectoryUrl);
234
+ const numberOfFiles = Object.keys(testPlanResult.results).length;
235
+ let fileFoundLine = "";
236
+ if (numberOfFiles === 0) {
237
+ fileFoundLine += `no file matching "testPlan" in ${directory}:
238
+ ${testPlanResult.patterns.join("\n")}`;
239
+ } else if (numberOfFiles === 1) {
240
+ fileFoundLine += `1 file matching "testPlan" in ${directory}`;
241
+ } else {
242
+ fileFoundLine += `${numberOfFiles} files matching "testPlan" in ${directory}`;
230
243
  }
244
+
245
+ lines.push(fileFoundLine);
246
+
231
247
  return `${renderBigSection({
232
- title: `${planified} executions to run`,
233
- content: introLines.join("\n"),
248
+ title: "execution start",
249
+ content: lines.join("\n"),
234
250
  })}\n\n`;
235
251
  };
236
252
 
237
- const getGroupRenderedName = (groupInfo, logOptions) => {
238
- let { runtimeName, runtimeVersion } = groupInfo;
239
- if (logOptions.mockFluctuatingValues && groupInfo.runtimeType === "node") {
240
- runtimeVersion = "<mock>";
241
- }
242
- return `${runtimeName}@${runtimeVersion}`;
243
- };
244
-
245
253
  const renderExecutionLog = (execution, logOptions) => {
246
254
  let log = "";
247
255
  // label
@@ -296,10 +304,10 @@ const renderExecutionLabel = (execution, logOptions) => {
296
304
  : humanizeDuration(duration, { short: true });
297
305
  infos.push(ANSI.color(durationFormatted, ANSI.GREY));
298
306
  }
299
- if (logOptions.showMemoryUsage && typeof memoryUsage === "number") {
307
+ if (logOptions.memoryUsage && typeof memoryUsage === "number") {
300
308
  const memoryUsageFormatted = logOptions.mockFluctuatingValues
301
309
  ? `<mock>MB`
302
- : humanizeMemoryUsage(memoryUsage, { short: true });
310
+ : humanizeMemory(memoryUsage, { short: true });
303
311
  infos.push(ANSI.color(memoryUsageFormatted, ANSI.GREY));
304
312
  }
305
313
  if (infos.length) {
@@ -561,55 +569,87 @@ const renderErrors = (execution, logOptions) => {
561
569
  };
562
570
 
563
571
  export const renderOutro = (testPlanResult, logOptions = {}) => {
564
- let finalSummary = "";
572
+ const lines = [];
565
573
  const { counters } = testPlanResult;
566
574
  const { planified } = counters;
567
575
 
568
- if (planified === 1) {
569
- finalSummary += `1 execution: `;
576
+ let executionLine = "";
577
+ if (planified === 0) {
578
+ executionLine += `no execution`;
579
+ } else if (planified === 1) {
580
+ executionLine += `1 execution: `;
570
581
  } else {
571
- finalSummary += `${planified} executions: `;
582
+ executionLine += `${planified} executions: `;
572
583
  }
573
- finalSummary += renderStatusRepartition(counters);
584
+ executionLine += renderStatusRepartition(counters);
585
+ lines.push(executionLine);
574
586
 
575
- let durationLog = ``;
587
+ let durationLine = `duration: `;
576
588
  const { timings } = testPlanResult;
577
589
  if (logOptions.mockFluctuatingValues) {
578
- durationLog += "<mock>s";
590
+ durationLine += "<mock>s";
579
591
  } else {
580
- durationLog += humanizeDuration(timings.end, { short: true });
592
+ durationLine += humanizeDuration(timings.end, { short: true });
581
593
  const namedTimings = {
582
- setup: timings.executionStart,
583
- execution: timings.executionEnd,
584
- teardown: timings.teardownEnd - timings.executionEnd,
594
+ setup: humanizeTiming(timings.executionStart),
595
+ execution: humanizeTiming(timings.executionEnd),
596
+ teardown: humanizeTiming(timings.teardownEnd - timings.executionEnd),
585
597
  ...(testPlanResult.coverage
586
- ? { coverage: timings.coverageTeardownEnd - timings.teardownEnd }
598
+ ? {
599
+ coverage: humanizeTiming(
600
+ timings.coverageTeardownEnd - timings.teardownEnd,
601
+ ),
602
+ }
587
603
  : {}),
588
604
  };
589
- const timingDetails = [];
590
- for (const key of Object.keys(namedTimings)) {
591
- const value = namedTimings[key];
592
- const timingDuration = humanizeDuration(value, { short: true });
593
- const timingString = `${ANSI.color(`${key}:`, ANSI.GREY)} ${ANSI.color(
594
- timingDuration,
595
- ANSI.GREY,
596
- )}`;
597
- timingDetails.push(ANSI.color(timingString, ANSI.GREY));
598
- }
599
- if (timingDetails.length) {
600
- durationLog += ` ${ANSI.color("(", ANSI.GREY)}${timingDetails.join(
601
- ANSI.color(", ", ANSI.GREY),
602
- )}${ANSI.color(")", ANSI.GREY)}`;
603
- }
605
+ durationLine += renderDetails(namedTimings);
606
+ }
607
+ lines.push(durationLine);
608
+
609
+ if (logOptions.cpuUsage) {
610
+ const processCpuUsage = testPlanResult.cpuUsage.process;
611
+ let cpuUsageLine = "cpu: ";
612
+ cpuUsageLine += `${humanizeProcessCpuUsage(processCpuUsage.end)}`;
613
+ cpuUsageLine += renderDetails({
614
+ med: humanizeProcessCpuUsage(processCpuUsage.median),
615
+ min: humanizeProcessCpuUsage(processCpuUsage.min),
616
+ max: humanizeProcessCpuUsage(processCpuUsage.max),
617
+ });
618
+ lines.push(cpuUsageLine);
619
+ }
620
+ if (logOptions.memoryUsage) {
621
+ const processMemoryUsage = testPlanResult.memoryUsage.process;
622
+ let memoryUsageLine = "memory: ";
623
+ memoryUsageLine += `${humanizeProcessMemoryUsage(processMemoryUsage.end)}`;
624
+ memoryUsageLine += renderDetails({
625
+ med: humanizeProcessMemoryUsage(processMemoryUsage.median),
626
+ min: humanizeProcessMemoryUsage(processMemoryUsage.min),
627
+ max: humanizeProcessMemoryUsage(processMemoryUsage.max),
628
+ });
629
+ lines.push(memoryUsageLine);
604
630
  }
605
- finalSummary += `\nduration: ${durationLog}`;
606
631
 
607
- return `\n${renderBigSection({ title: "summary", content: finalSummary })}\n`;
632
+ return `\n${renderBigSection({ title: "summary", content: lines.join("\n") })}\n`;
633
+ };
634
+
635
+ const humanizeTiming = (value) => {
636
+ return humanizeDuration(value, { short: true });
637
+ };
638
+
639
+ const humanizeProcessCpuUsage = (ratio) => {
640
+ const percentageAsNumber = ratio * 100;
641
+ const percentageAsNumberRounded = Math.round(percentageAsNumber);
642
+ const percentage = `${percentageAsNumberRounded}%`;
643
+ return percentage;
644
+ };
645
+
646
+ const humanizeProcessMemoryUsage = (value) => {
647
+ return humanizeMemory(value, { short: true, decimals: 0 });
608
648
  };
609
649
 
610
650
  const renderStatusRepartition = (counters, { showProgression } = {}) => {
611
651
  if (counters.planified === 0) {
612
- return `nothing to run`;
652
+ return ``;
613
653
  }
614
654
  if (counters.aborted === counters.planified) {
615
655
  return `all ${ANSI.color(`aborted`, COLOR_ABORTED)}`;
@@ -695,3 +735,26 @@ const renderSection = ({
695
735
  section += bottomDashes;
696
736
  return section;
697
737
  };
738
+
739
+ const renderDetails = (data) => {
740
+ const details = [];
741
+ for (const key of Object.keys(data)) {
742
+ const value = data[key];
743
+ let valueString = "";
744
+ valueString += ANSI.color(`${key}:`, ANSI.GREY);
745
+ const useNonGreyAnsiColor =
746
+ typeof value === "string" && value.includes("\x1b");
747
+ valueString += " ";
748
+ valueString += useNonGreyAnsiColor ? value : ANSI.color(value, ANSI.GREY);
749
+ details.push(valueString);
750
+ }
751
+ if (details.length === 0) {
752
+ return "";
753
+ }
754
+
755
+ let string = "";
756
+ string += ` ${ANSI.color("(", ANSI.GREY)}`;
757
+ string += details.join(ANSI.color(", ", ANSI.GREY));
758
+ string += ANSI.color(")", ANSI.GREY);
759
+ return string;
760
+ };
@@ -85,9 +85,9 @@ export const startMeasuringTotalCpuUsage = () => {
85
85
  );
86
86
  previousCpuUsage = processCpuUsage;
87
87
  const thisProcessActiveMs = thisProcessSystemMs + thisProcessUserMs;
88
- thisProcess.active = thisProcessActiveMs / overallActiveMs;
89
- thisProcess.system = thisProcessSystemMs / overallSystemMs;
90
- thisProcess.user = thisProcessUserMs / overallUserMs;
88
+ thisProcess.active = thisProcessActiveMs / overallMsEllapsed;
89
+ thisProcess.system = thisProcessSystemMs / overallMsEllapsed;
90
+ thisProcess.user = thisProcessUserMs / overallMsEllapsed;
91
91
 
92
92
  if (samples.length === 10) {
93
93
  let index = 0;