Repository: mesonbuild/meson

Issue:
Empty test suite list causes backtrace
Specifying a test with an empty list of test suite names causes a backtrace:
```
test('name', executable, suite: [])
```
This is useful for consistency. Where a project has lots of tests and many (but not all) need suite names for filtering, it's more explicit to add a `suite: []` argument than just leaving it out. Example: 5 out of 10 tests need root permissions, so those tests have `suite: ['root']` while the others have `suite: []`. 

This currently triggers a backtrace:
```
$ meson test
...
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/mesonbuild/mesonmain.py", line 122, in run
    return options.run_func(options)
  File "/usr/lib/python3.7/site-packages/mesonbuild/mtest.py", line 1005, in run
    return th.doit()
  File "/usr/lib/python3.7/site-packages/mesonbuild/mtest.py", line 756, in doit
    self.run_tests(tests)
  File "/usr/lib/python3.7/site-packages/mesonbuild/mtest.py", line 896, in run_tests
    visible_name = self.get_pretty_suite(test)
  File "/usr/lib/python3.7/site-packages/mesonbuild/mtest.py", line 875, in get_pretty_suite
    rv = TestHarness.split_suite_string(test.suite[0])[0]
IndexError: list index out of range
```


Discussion:

Resolving patch:
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -873,7 +873,7 @@ def get_wrapper(options):
         return wrap
 
     def get_pretty_suite(self, test):
-        if len(self.suites) > 1:
+        if len(self.suites) > 1 and test.suite:
             rv = TestHarness.split_suite_string(test.suite[0])[0]
             s = "+".join(TestHarness.split_suite_string(s)[1] for s in test.suite)
             if len(s):
diff --git a/run_unittests.py b/run_unittests.py
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -1813,48 +1813,48 @@ def test_suite_selection(self):
         self.init(testdir)
         self.build()
 
-        self.assertFailedTestCount(3, self.mtest_command)
+        self.assertFailedTestCount(4, self.mtest_command)
 
         self.assertFailedTestCount(0, self.mtest_command + ['--suite', ':success'])
         self.assertFailedTestCount(3, self.mtest_command + ['--suite', ':fail'])
-        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', ':success'])
-        self.assertFailedTestCount(0, self.mtest_command + ['--no-suite', ':fail'])
+        self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', ':success'])
+        self.assertFailedTestCount(1, self.mtest_command + ['--no-suite', ':fail'])
 
         self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'mainprj'])
         self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc'])
         self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail'])
         self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjmix'])
-        self.assertFailedTestCount(2, self.mtest_command + ['--no-suite', 'mainprj'])
-        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjsucc'])
-        self.assertFailedTestCount(2, self.mtest_command + ['--no-suite', 'subprjfail'])
-        self.assertFailedTestCount(2, self.mtest_command + ['--no-suite', 'subprjmix'])
+        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'mainprj'])
+        self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc'])
+        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjfail'])
+        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjmix'])
 
         self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'mainprj:fail'])
         self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'mainprj:success'])
-        self.assertFailedTestCount(2, self.mtest_command + ['--no-suite', 'mainprj:fail'])
-        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'mainprj:success'])
+        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'mainprj:fail'])
+        self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'mainprj:success'])
 
         self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail:fail'])
         self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjfail:success'])
-        self.assertFailedTestCount(2, self.mtest_command + ['--no-suite', 'subprjfail:fail'])
-        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjfail:success'])
+        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjfail:fail'])
+        self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjfail:success'])
 
         self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc:fail'])
         self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc:success'])
-        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjsucc:fail'])
-        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjsucc:success'])
+        self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc:fail'])
+        self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc:success'])
 
         self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjmix:fail'])
         self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjmix:success'])
-        self.assertFailedTestCount(2, self.mtest_command + ['--no-suite', 'subprjmix:fail'])
-        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjmix:success'])
+        self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjmix:fail'])
+        self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjmix:success'])
 
         self.assertFailedTestCount(2, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix:fail'])
         self.assertFailedTestCount(3, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj'])
         self.assertFailedTestCount(2, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj', '--no-suite', 'subprjmix:fail'])
         self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj', '--no-suite', 'subprjmix:fail', 'mainprj-failing_test'])
 
-        self.assertFailedTestCount(1, self.mtest_command + ['--no-suite', 'subprjfail:fail', '--no-suite', 'subprjmix:fail'])
+        self.assertFailedTestCount(2, self.mtest_command + ['--no-suite', 'subprjfail:fail', '--no-suite', 'subprjmix:fail'])
 
     def test_build_by_default(self):
         testdir = os.path.join(self.common_test_dir, '134 build by default')


Test patch:
diff --git a/test cases/unit/4 suite selection/meson.build b/test cases/unit/4 suite selection/meson.build
--- a/test cases/unit/4 suite selection/meson.build	
+++ b/test cases/unit/4 suite selection/meson.build	
@@ -11,3 +11,7 @@ test('mainprj-failing_test',
 test('mainprj-successful_test',
   executable('successful_test', 'successful_test.c'),
   suite : 'success')
+
+test('mainprj-successful_test_no_suite',
+  executable('no_suite_test', 'successful_test.c'),
+  suite : [])
diff --git a/test cases/unit/4 suite selection/subprojects/subprjfail/meson.build b/test cases/unit/4 suite selection/subprojects/subprjfail/meson.build
--- a/test cases/unit/4 suite selection/subprojects/subprjfail/meson.build	
+++ b/test cases/unit/4 suite selection/subprojects/subprjfail/meson.build	
@@ -3,3 +3,7 @@ project('subprjfail', 'c')
 test('subprjfail-failing_test',
   executable('failing_test', 'failing_test.c'),
   suite : 'fail')
+
+test('subprjfail-failing_test_no_suite',
+  executable('failing_test_no_suite', 'failing_test.c'),
+  suite : [])
diff --git a/test cases/unit/4 suite selection/subprojects/subprjsucc/meson.build b/test cases/unit/4 suite selection/subprojects/subprjsucc/meson.build
--- a/test cases/unit/4 suite selection/subprojects/subprjsucc/meson.build	
+++ b/test cases/unit/4 suite selection/subprojects/subprjsucc/meson.build	
@@ -3,3 +3,7 @@ project('subprjsucc', 'c')
 test('subprjsucc-successful_test',
   executable('successful_test', 'successful_test.c'),
   suite : 'success')
+
+test('subprjsucc-successful_test_no_suite',
+  executable('successful_test_no_suite', 'successful_test.c'),
+  suite : [])