Skip to content

Commit 016901b

Browse files
committed
[hyperactor] assert_behaves!
Pull Request resolved: #1826 This adds a macro that asserts an actor's behavior; we use it to test the mesh behavior: ``` hyperactor::assert_behaves!(TestMeshController as Controller<TestMesh>); ``` It is implemented by statically validating that the actor type can bind to the defined behavior. This then provide a way to both document the intended behavior of an actor, and also to statically validate at the definition site that the behavior is implemented correctly. (We already statically validate this at the *use* site, but then the errors are already "at a distance".) Differential Revision: [D86786231](https://our.internmc.facebook.com/intern/diff/D86786231/) **NOTE FOR REVIEWERS**: This PR has internal Meta-specific changes or comments, please review them on [Phabricator](https://our.internmc.facebook.com/intern/diff/D86786231/)! ghstack-source-id: 322613843
1 parent 49657a3 commit 016901b

File tree

2 files changed

+41
-11
lines changed

2 files changed

+41
-11
lines changed

hyperactor/src/actor.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,46 @@ pub trait Binds<A: Actor>: Referable {
715715
/// is handled by a specific actor type.
716716
pub trait RemoteHandles<M: RemoteMessage>: Referable {}
717717

718+
/// Check if the actor behaves-as the a given behavior (defined by [`behavior!`]).
719+
///
720+
/// ```
721+
/// # use serde::Serialize;
722+
/// # use serde::Deserialize;
723+
/// # use hyperactor::Named;
724+
///
725+
/// // First, define a behavior, based on handling a single message type `()`.
726+
/// hyperactor::behavior!(
727+
/// UnitBehavior,
728+
/// (),
729+
/// )
730+
///
731+
/// #[derive(hyperactor::Actor, Default)]
732+
/// struct MyActor;
733+
///
734+
/// #[async_trait::async_trait]
735+
/// impl hyperactor::Handler<()> for MyActor {
736+
/// async fn handle(
737+
/// &mut self,
738+
/// _cx: &hyperactor::Context<Self>,
739+
/// _message: (),
740+
/// ) -> Result<(), anyhow::Error> {
741+
/// // no-op
742+
/// Ok(())
743+
/// }
744+
/// }
745+
///
746+
/// hyperactor::assert_behaves!(MyActor as UnitBehavior);
747+
/// ```
748+
#[macro_export]
749+
macro_rules! assert_behaves {
750+
($ty:ty as $behavior:ty) => {
751+
const _: fn() = || {
752+
fn check<B: hyperactor::actor::Binds<$ty>>() {}
753+
check::<$behavior>();
754+
};
755+
};
756+
}
757+
718758
#[cfg(test)]
719759
mod tests {
720760
use std::sync::Mutex;

hyperactor_mesh/src/resource/mesh.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ hyperactor::behavior!(
6464
#[cfg(test)]
6565
mod test {
6666
use hyperactor::Actor;
67-
use hyperactor::ActorRef;
6867
use hyperactor::Context;
6968
use hyperactor::Handler;
7069

@@ -114,14 +113,5 @@ mod test {
114113
_message: Stop => unimplemented!(),
115114
}
116115

117-
#[test]
118-
fn test_controller_behavior() {
119-
use hyperactor::ActorHandle;
120-
121-
// This is a compile-time check that TestMeshController implements
122-
// the Controller<TestMesh> behavior correctly.
123-
fn _assert_bind(handle: ActorHandle<TestMeshController>) -> ActorRef<Controller<TestMesh>> {
124-
handle.bind()
125-
}
126-
}
116+
hyperactor::assert_behaves!(TestMeshController as Controller<TestMesh>);
127117
}

0 commit comments

Comments
 (0)