Repository: spack/spack

Issue:
spack test lists warnings about sysctl on macOS


### Steps to reproduce the issue

```console
$ spack test cmd/compiler_command.py
==================================================================== test session starts ====================================================================
platform darwin -- Python 3.7.3, pytest-3.2.5, py-1.4.34, pluggy-0.4.0
rootdir: /Users/Adam/spack/lib/spack/spack/test, inifile: pytest.ini
collected 2101 items                                                                                                                                         

cmd/compiler_command.py .

================================================================= slowest 20 test durations =================================================================
0.34s call     cmd/compiler_command.py::test_compiler_find_without_paths
0.11s setup    cmd/compiler_command.py::test_compiler_find_without_paths
0.01s teardown cmd/compiler_command.py::test_compiler_find_without_paths
===================================================================== warnings summary ======================================================================
cmd/compiler_command.py::test_compiler_find_without_paths
  /Users/Adam/spack/lib/spack/llnl/util/cpu/detect.py:127: UserWarning: [Errno 2] No such file or directory: 'sysctl': 'sysctl'
    warnings.warn(str(e))
  /Users/Adam/spack/lib/spack/llnl/util/cpu/detect.py:127: UserWarning: [Errno 2] No such file or directory: 'sysctl': 'sysctl'
    warnings.warn(str(e))

-- Docs: http://doc.pytest.org/en/latest/warnings.html
=================================================================== 2100 tests deselected ===================================================================
=================================================== 1 passed, 2100 deselected, 2 warnings in 3.60 seconds ===================================================
```

### Information on your system

- macOS 10.15 Catalina

@alalazo 
Make sure sysctl tests can actually find sysctl
Fixes #13138 

@alalazo 


Discussion:
I guess the question here is whether this warning is important (in which case we should fix it) or unimportant (in which case we should hide it). Pytest has plenty of features for capturing warnings: https://docs.pytest.org/en/latest/warnings.html


Resolving patch:
diff --git a/lib/spack/llnl/util/cpu/detect.py b/lib/spack/llnl/util/cpu/detect.py
--- a/lib/spack/llnl/util/cpu/detect.py
+++ b/lib/spack/llnl/util/cpu/detect.py
@@ -4,6 +4,7 @@
 # SPDX-License-Identifier: (Apache-2.0 OR MIT)
 import collections
 import functools
+import os
 import platform
 import re
 import subprocess
@@ -75,31 +76,38 @@ def proc_cpuinfo():
     return info
 
 
-def check_output(args):
-    output = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]
+def check_output(args, env):
+    output = subprocess.Popen(
+        args, stdout=subprocess.PIPE, env=env
+    ).communicate()[0]
     return six.text_type(output.decode('utf-8'))
 
 
 @info_dict(operating_system='Darwin')
-def sysctl():
+def sysctl_info_dict():
     """Returns a raw info dictionary parsing the output of sysctl."""
-
-    info = {}
-    info['vendor_id'] = check_output(
-        ['sysctl', '-n', 'machdep.cpu.vendor']
-    ).strip()
-    info['flags'] = check_output(
-        ['sysctl', '-n', 'machdep.cpu.features']
-    ).strip().lower()
-    info['flags'] += ' ' + check_output(
-        ['sysctl', '-n', 'machdep.cpu.leaf7_features']
-    ).strip().lower()
-    info['model'] = check_output(
-        ['sysctl', '-n', 'machdep.cpu.model']
-    ).strip()
-    info['model name'] = check_output(
-        ['sysctl', '-n', 'machdep.cpu.brand_string']
-    ).strip()
+    # Make sure that /sbin and /usr/sbin are in PATH as sysctl is
+    # usually found there
+    child_environment = dict(os.environ.items())
+    search_paths = child_environment.get('PATH', '').split(os.pathsep)
+    for additional_path in ('/sbin', '/usr/sbin'):
+        if additional_path not in search_paths:
+            search_paths.append(additional_path)
+    child_environment['PATH'] = os.pathsep.join(search_paths)
+
+    def sysctl(*args):
+        return check_output(
+            ['sysctl'] + list(args), env=child_environment
+        ).strip()
+
+    flags = (sysctl('-n', 'machdep.cpu.features').lower() + ' '
+             + sysctl('-n', 'machdep.cpu.leaf7_features').lower())
+    info = {
+        'vendor_id': sysctl('-n', 'machdep.cpu.vendor'),
+        'flags': flags,
+        'model': sysctl('-n', 'machdep.cpu.model'),
+        'model name': sysctl('-n', 'machdep.cpu.brand_string')
+    }
 
     # Super hacky way to deal with slight representation differences
     # Would be better to somehow consider these "identical"


Test patch:
diff --git a/lib/spack/spack/test/cmd/compiler_command.py b/lib/spack/spack/test/cmd/compiler_command.py
--- a/lib/spack/spack/test/cmd/compiler_command.py
+++ b/lib/spack/spack/test/cmd/compiler_command.py
@@ -24,7 +24,7 @@ def no_compilers_yaml(mutable_config, monkeypatch):
             os.remove(compilers_yaml)
 
 
-@pytest.mark.regression('11678')
+@pytest.mark.regression('11678,13138')
 def test_compiler_find_without_paths(no_compilers_yaml, working_env, tmpdir):
     with tmpdir.as_cwd():
         with open('gcc', 'w') as f:
diff --git a/lib/spack/spack/test/llnl/util/cpu.py b/lib/spack/spack/test/llnl/util/cpu.py
--- a/lib/spack/spack/test/llnl/util/cpu.py
+++ b/lib/spack/spack/test/llnl/util/cpu.py
@@ -67,7 +67,7 @@ def _open(not_used_arg):
                 key, value = line.split(':')
                 info[key.strip()] = value.strip()
 
-        def _check_output(args):
+        def _check_output(args, env):
             current_key = args[-1]
             return info[current_key]