pw_unit_test: Add enable_if flag to test groups

This updates pw_test_groups to support the enable_if flag, similar to
unit tests. Disabled test groups become empty GN groups.

Change-Id: Icbdc80d80884d9d2864a72aa468ecd17fa52fbea
diff --git a/pw_unit_test/docs.rst b/pw_unit_test/docs.rst
index 3736199..01632e7 100644
--- a/pw_unit_test/docs.rst
+++ b/pw_unit_test/docs.rst
@@ -125,7 +125,7 @@
     sources = [ "foo_test.cc" ]
   }
 
-``pw_unit_test`` module provides a few optional libraries to simplify setup:
+The ``pw_unit_test`` module provides a few optional libraries to simplify setup:
 
  - ``simple_printing_event_handler```: When running tests, output test results
    as plain text over ``pw_sys_io``.
@@ -137,4 +137,67 @@
    using the ``logging_event_handler``.
 
 
+pw_test template
+----------------
+
+``pw_test`` defines a single test binary. It wraps ``pw_executable`` and pulls
+in the test framework as well as the test entry point defined by the
+``pw_unit_test_main`` build variable.
+
+**Arguments**
+
+* All GN executable arguments are accepted and forwarded to the underlying
+  ``pw_executable``.
+* ``enable_if``: Boolean indicating whether the test should be built. If false,
+  replaces the test with an empty target. Default true.
+
+**Example**
+
+.. code::
+
+  import("$dir_pw_unit_test/test.gni")
+
+  pw_test("large_test") {
+    sources = [ "large_test.cc" ]
+    enable_if = device_has_1m_flash
+  }
+
+
+pw_test_group template
+----------------------
+
+``pw_test_group`` defines a collection of tests or other test groups. Each
+module should expose a ``pw_test_group`` called ``tests`` with the module's test
+binaries.
+
+**Arguments**
+
+* ``tests``: List of the ``pw_test`` targets in the group.
+* ``group_deps``: List of other ``pw_test_group`` targets on which this one
+  depends.
+* ``enable_if``: Boolean indicating whether the group target should be created.
+  If false, an empty GN group is created instead. Default true.
+
+**Example**
+
+.. code::
+
+  import("$dir_pw_unit_test/test.gni")
+
+  pw_test_group("tests") {
+    tests = [
+      ":bar_test",
+      ":foo_test",
+    ]
+  }
+
+  pw_test("foo_test") {
+    # ...
+  }
+
+  pw_test("bar_test") {
+    # ...
+  }
+
+
 .. _Google Test: https://github.com/google/googletest/blob/master/googletest/docs/primer.md
diff --git a/pw_unit_test/test.gni b/pw_unit_test/test.gni
index 495126e..0481432 100644
--- a/pw_unit_test/test.gni
+++ b/pw_unit_test/test.gni
@@ -136,8 +136,10 @@
 # pw_test_group targets output a JSON metadata file for the Pigweed test runner.
 #
 # Args:
-#  tests: List of pw_test targets for each of the tests in the group.
-#  group_deps: Optional pw_test_group targets on which this group depends.
+#   - tests: List of pw_test targets for each of the tests in the group.
+#   - group_deps: (optional) pw_test_group targets on which this group depends.
+#   - enable_if: (optional) Conditionally enables or disables this test group.
+#         If false, an empty group is created. Defaults to true.
 template("pw_test_group") {
   _group_target = target_name
   _group_deps_metadata = []
@@ -147,66 +149,82 @@
     _deps = []
   }
 
-  if (defined(invoker.group_deps)) {
-    # If the group specified any other group dependencies, create a metadata
-    # entry for each of them indicating that they are another group and a group
-    # target to collect that metadata.
-    foreach(dep, invoker.group_deps) {
-      _group_deps_metadata += [
-        {
-          type = "dep"
-          group = get_path_info(dep, "abspath")
-        },
-      ]
+  _group_is_enabled = !defined(invoker.enable_if) || invoker.enable_if
+
+  if (_group_is_enabled) {
+    if (defined(invoker.group_deps)) {
+      # If the group specified any other group dependencies, create a metadata
+      # entry for each of them indicating that they are another group and a
+      # group target to collect that metadata.
+      foreach(dep, invoker.group_deps) {
+        _group_deps_metadata += [
+          {
+            type = "dep"
+            group = get_path_info(dep, "abspath")
+          },
+        ]
+      }
+
+      _deps += invoker.group_deps
     }
 
-    _deps += invoker.group_deps
-  }
+    _metadata_group_target = "${target_name}_pw_test_group_metadata"
+    group(_metadata_group_target) {
+      metadata = {
+        group_deps = _group_deps_metadata
+        self = [
+          {
+            type = "self"
+            name = get_path_info(":$_group_target", "abspath")
+          },
+        ]
 
-  _metadata_group_target = "${target_name}_pw_test_group_metadata"
-  group(_metadata_group_target) {
-    metadata = {
-      group_deps = _group_deps_metadata
-      self = [
-        {
-          type = "self"
-          name = get_path_info(":$_group_target", "abspath")
-        },
+        # Metadata from the group's own unit test targets is forwarded through
+        # the group dependencies group. This entry is listed as a "walk_key" in
+        # the generated file so that only test targets' metadata (not group
+        # targets) appear in the output.
+        if (defined(invoker.tests)) {
+          propagate_metadata_from = invoker.tests
+        }
+      }
+      deps = _deps
+    }
+
+    _test_group_deps = [ ":$_metadata_group_target" ]
+
+    generated_file(_group_target) {
+      outputs = [ "$target_out_dir/$target_name.testinfo.json" ]
+      data_keys = [
+        "group_deps",
+        "self",
+        "tests",
       ]
+      walk_keys = [ "propagate_metadata_from" ]
+      output_conversion = "json"
+      deps = _test_group_deps
+    }
 
-      # Metadata from the group's own unit test targets is forwarded through
-      # the group dependencies group. This entry is listed as a "walk_key" in
-      # the generated file so that only test targets' metadata (not group
-      # targets) appear in the output.
-      if (defined(invoker.tests)) {
-        propagate_metadata_from = invoker.tests
+    # If automatic test running is enabled, create a *_run group that collects
+    # all of the individual *_run targets and groups.
+    if (pw_automatic_test_runner != "") {
+      group(_group_target + "_run") {
+        deps = [ ":$_group_target" ]
+        foreach(_target, _deps) {
+          deps += [ "${_target}_run" ]
+        }
       }
     }
-    deps = _deps
-  }
+  } else {  # _group_is_enabled
+    # Create empty groups for the tests to avoid pulling in any dependencies.
+    group(_group_target) {
+    }
 
-  _test_group_deps = [ ":$_metadata_group_target" ]
-
-  generated_file(_group_target) {
-    outputs = [ "$target_out_dir/$target_name.testinfo.json" ]
-    data_keys = [
-      "group_deps",
-      "self",
-      "tests",
-    ]
-    walk_keys = [ "propagate_metadata_from" ]
-    output_conversion = "json"
-    deps = _test_group_deps
-  }
-
-  # If automatic test running is enabled, create a *_run group that collects all
-  # of the individual *_run targets and groups.
-  if (pw_automatic_test_runner != "") {
-    group(_group_target + "_run") {
-      deps = [ ":$_group_target" ]
-      foreach(_target, _deps) {
-        deps += [ "${_target}_run" ]
+    if (pw_automatic_test_runner != "") {
+      group(_group_target + "_run") {
       }
     }
+
+    not_needed("*")
+    not_needed(invoker, "*")
   }
 }