From decce43efb3cc9b22f4f1662e391b17c99b325d6 Mon Sep 17 00:00:00 2001 From: Tobias Pfeiffer Date: Sun, 12 Jan 2025 16:16:35 +0100 Subject: [PATCH] Make system gathering more resilient This is in relation to #442 - we'd previously fail if a command wasn't available at all which definitely is wrong. This is a quicker fix vs. getting better CPU/memory information from elsewhere. --- lib/benchee/system.ex | 11 ++++++++++- test/benchee/system_test.exs | 37 +++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/lib/benchee/system.ex b/lib/benchee/system.ex index c70ea73c..007e1674 100644 --- a/lib/benchee/system.ex +++ b/lib/benchee/system.ex @@ -232,7 +232,16 @@ defmodule Benchee.System do @doc false def system_cmd(cmd, args, system_func \\ &System.cmd/2) do - {output, exit_code} = system_func.(cmd, args) + {output, exit_code} = + try do + system_func.(cmd, args) + rescue + e -> + message = Exception.format(:error, e, __STACKTRACE__) + + # this mimics an error return code from the command, which is the same behavior we want to have + {message, 1} + end if exit_code > 0 do IO.puts("Something went wrong trying to get system information:") diff --git a/test/benchee/system_test.exs b/test/benchee/system_test.exs index 24797142..d1aa06c2 100644 --- a/test/benchee/system_test.exs +++ b/test/benchee/system_test.exs @@ -5,7 +5,6 @@ defmodule Benchee.SystemTest do import Benchee.System alias Benchee.Suite - alias Benchee.System alias Benchee.Utility.ErlangVersion test ".system adds the content to a given suite" do @@ -104,20 +103,32 @@ defmodule Benchee.SystemTest do assert rest =~ ~r/GB/ end - test ".system_cmd handles errors gracefully" do - system_func = fn _, _ -> {"ERROR", 1} end + describe ".system_cmd/3" do + test "handles error return values gracefully" do + system_func = fn _, _ -> {"ERROR", 1} end - captured_io = - capture_io(fn -> - system_cmd("cat", "dev/null", system_func) - end) + captured_io = + capture_io(fn -> + system_cmd("cat", "dev/null", system_func) == "N/A" + end) + + assert captured_io =~ "Something went wrong" + assert captured_io =~ "ERROR" + end - assert captured_io =~ "Something went wrong" - assert captured_io =~ "ERROR" + # programs might not be installed or deprecated, see https://github.com/bencheeorg/benchee/issues/442 + test "handles exceptions gracefully" do + # this raises an ERlang error: :enoent - but in case that changes I wanted to trigger it directly + system_func = fn _, _ -> System.cmd("definitely-not-existing-command32832", ["bogus"]) end - capture_io(fn -> - assert system_cmd("cat", "dev/null", system_func) == "N/A" - end) + captured_io = + capture_io(fn -> + system_cmd("does", "not/matter", system_func) == "N/A" + end) + + assert captured_io =~ "Something went wrong" + assert captured_io =~ "enoent" + end end describe "all_protocols_consolidated?/1" do @@ -157,7 +168,7 @@ defmodule Benchee.SystemTest do end end - @system %System{ + @system %Benchee.System{ elixir: "1.4.0", erlang: "19.1", jit_enabled?: false,