[SetUI][core] Cleanup Setting Handler Tests.

This changelist consolidates duplicate code and
removes the need for generics for test setting handler
types.

Fixed: 50217
MULTIPLY: setui_service_tests
Test: fx test -o setui_service_tests

Change-Id: Idacd307d04a1cdf214e3b0081ed2f57ca118f2ef
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/404983
Commit-Queue: Bryce Lee <brycelee@google.com>
Reviewed-by: William Xiao <wxyz@google.com>
Reviewed-by: Paul Faria <paulfaria@google.com>
Testability-Review: William Xiao <wxyz@google.com>
diff --git a/garnet/bin/setui/src/tests/setting_handler_tests.rs b/garnet/bin/setui/src/tests/setting_handler_tests.rs
index 6b5fd2b..3040714 100644
--- a/garnet/bin/setui/src/tests/setting_handler_tests.rs
+++ b/garnet/bin/setui/src/tests/setting_handler_tests.rs
@@ -31,103 +31,96 @@
 const ENV_NAME: &str = "settings_service_setting_handler_test_environment";
 const CONTEXT_ID: u64 = 0;
 
-/// The Control trait provides static functions that control the behavior of
-/// test controllers. Since controllers are created from a trait themselves,
-/// we must specify this functionality as a trait so that the impl types can
-/// be supplied as generic parameters.
-trait Control {
-    fn should_init_succeed() -> bool;
-}
+macro_rules! gen_controller {
+    ($name:ident, $succeed:expr) => {
+        /// Controller is a simple controller test implementation that refers to a
+        /// Control type for how to behave.
+        struct $name {}
 
-/// SucceedControl provides a Control implementation that will succeed on
-/// initialization.
-struct SucceedControl {}
-
-impl Control for SucceedControl {
-    fn should_init_succeed() -> bool {
-        true
-    }
-}
-
-/// FailControl provides a Control implementation that will fail on
-/// initialization.
-struct FailControl {}
-
-impl Control for FailControl {
-    fn should_init_succeed() -> bool {
-        false
-    }
-}
-
-/// Controller is a simple controller test implementation that refers to a
-/// Control type for how to behave.
-struct Controller<C: Control + Sync + Send + 'static> {
-    _data: PhantomData<C>,
-}
-
-#[async_trait]
-impl<C: Control + Sync + Send + 'static> controller::Create for Controller<C> {
-    async fn create(_: ClientProxy) -> Result<Self, ControllerError> {
-        if C::should_init_succeed() {
-            Ok(Self { _data: PhantomData })
-        } else {
-            Err(ControllerError::InitFailure { description: "failure".to_string() })
+        #[async_trait]
+        impl controller::Create for $name {
+            async fn create(_: ClientProxy) -> Result<Self, ControllerError> {
+                if $succeed {
+                    Ok(Self {})
+                } else {
+                    Err(ControllerError::InitFailure { description: "failure".to_string() })
+                }
+            }
         }
-    }
-}
 
-#[async_trait]
-impl<C: Control + Sync + Send + 'static> controller::Handle for Controller<C> {
-    async fn handle(&self, _: SettingRequest) -> Option<SettingResponseResult> {
-        return None;
-    }
+        #[async_trait]
+        impl controller::Handle for $name {
+            async fn handle(&self, _: SettingRequest) -> Option<SettingResponseResult> {
+                return None;
+            }
 
-    async fn change_state(&mut self, _: State) -> Option<ControllerStateResult> {
-        return None;
-    }
-}
-
-/// The DataController is a controller implementation with storage that
-/// defers to a Control type for how to behave.
-struct DataController<C: Control + Sync + Send + 'static, S: Storage> {
-    _control: PhantomData<C>,
-    _storage: PhantomData<S>,
-}
-
-#[async_trait]
-impl<C: Control + Sync + Send + 'static, S: Storage> data_controller::Create<S>
-    for DataController<C, S>
-{
-    async fn create(_: DataClientProxy<S>) -> Result<Self, ControllerError> {
-        if C::should_init_succeed() {
-            Ok(Self { _control: PhantomData, _storage: PhantomData })
-        } else {
-            Err(ControllerError::InitFailure { description: "failure".to_string() })
+            async fn change_state(&mut self, _: State) -> Option<ControllerStateResult> {
+                return None;
+            }
         }
-    }
+    };
 }
 
-#[async_trait]
-impl<C: Control + Sync + Send + 'static, S: Storage> controller::Handle for DataController<C, S> {
-    async fn handle(&self, _: SettingRequest) -> Option<SettingResponseResult> {
-        return None;
-    }
+gen_controller!(SucceedController, true);
+gen_controller!(FailController, false);
 
-    async fn change_state(&mut self, _: State) -> Option<ControllerStateResult> {
-        return None;
-    }
+macro_rules! gen_data_controller {
+    ($name:ident, $succeed:expr) => {
+        /// The DataController is a controller implementation with storage that
+        /// defers to a Control type for how to behave.
+        struct $name<S: Storage> {
+            _storage: PhantomData<S>,
+        }
+
+        #[async_trait]
+        impl<S: Storage> data_controller::Create<S> for $name<S> {
+            async fn create(_: DataClientProxy<S>) -> Result<Self, ControllerError> {
+                if $succeed {
+                    Ok(Self { _storage: PhantomData })
+                } else {
+                    Err(ControllerError::InitFailure { description: "failure".to_string() })
+                }
+            }
+        }
+
+        #[async_trait]
+        impl<S: Storage> controller::Handle for $name<S> {
+            async fn handle(&self, _: SettingRequest) -> Option<SettingResponseResult> {
+                return None;
+            }
+
+            async fn change_state(&mut self, _: State) -> Option<ControllerStateResult> {
+                return None;
+            }
+        }
+    };
+}
+
+gen_data_controller!(SucceedDataController, true);
+gen_data_controller!(FailDataController, false);
+
+macro_rules! verify_handle {
+    ($spawn:expr) => {
+        assert!(EnvironmentBuilder::new(InMemoryStorageFactory::create())
+            .handler(SettingType::Unknown, Box::new($spawn))
+            .agents(&[restore_agent::blueprint::create()])
+            .settings(&[SettingType::Unknown])
+            .spawn_nested(ENV_NAME)
+            .await
+            .is_ok());
+    };
 }
 
 #[fuchsia_async::run_until_stalled(test)]
 async fn test_spawn() {
     // Exercises successful spawn of a simple controller.
-    verify_handler::<SucceedControl>(true).await;
+    verify_handle!(Handler::<SucceedController>::spawn);
     // Exercises failed spawn of a simple controller.
-    verify_handler::<FailControl>(true).await;
+    verify_handle!(Handler::<FailController>::spawn);
     // Exercises successful spawn of a data controller.
-    verify_data_handler::<SucceedControl>(true).await;
+    verify_handle!(DataHandler::<DoNotDisturbInfo, SucceedDataController<DoNotDisturbInfo>>::spawn);
     // Exercises failed spawn of a data controller.
-    verify_data_handler::<FailControl>(true).await;
+    verify_handle!(DataHandler::<DoNotDisturbInfo, FailDataController<DoNotDisturbInfo>>::spawn);
 }
 
 #[fuchsia_async::run_until_stalled(test)]
@@ -221,37 +214,6 @@
     assert!(result.is_ok() && result.into_response_result().is_ok());
 }
 
-async fn verify_handler<C: Control + Sync + Send + 'static>(should_succeed: bool) {
-    assert_eq!(
-        should_succeed,
-        EnvironmentBuilder::new(InMemoryStorageFactory::create())
-            .handler(SettingType::Unknown, Box::new(Handler::<Controller<C>>::spawn))
-            .agents(&[restore_agent::blueprint::create()])
-            .settings(&[SettingType::Unknown])
-            .spawn_nested(ENV_NAME)
-            .await
-            .is_ok()
-    );
-}
-
-async fn verify_data_handler<C: Control + Sync + Send + 'static>(should_succeed: bool) {
-    assert_eq!(
-        should_succeed,
-        EnvironmentBuilder::new(InMemoryStorageFactory::create())
-            .handler(
-                SettingType::Unknown,
-                Box::new(
-                    DataHandler::<DoNotDisturbInfo, DataController<C, DoNotDisturbInfo>>::spawn,
-                ),
-            )
-            .agents(&[restore_agent::blueprint::create()])
-            .settings(&[SettingType::Unknown])
-            .spawn_nested(ENV_NAME)
-            .await
-            .is_ok()
-    );
-}
-
 /// StateController allows for exposing incoming handler state to an outside
 /// listener.
 struct StateController {