netstack3_base/testutil/
fake_bindings.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! A shareable fake bindings context.
6
7use alloc::vec::Vec;
8use core::convert::Infallible as Never;
9use core::fmt::Debug;
10
11use crate::sync::DynDebugReferences;
12use crate::testutil::{
13    AlwaysDefaultsSettingsContext, FakeAtomicInstant, FakeCryptoRng, FakeEventCtx, FakeFrameCtx,
14    FakeInstant, FakeTimerCtx, WithFakeTimerContext,
15};
16use crate::{
17    ContextProvider, DeferredResourceRemovalContext, EventContext, InstantBindingsTypes,
18    InstantContext, ReferenceNotifiers, RngContext, TimerBindingsTypes, TimerContext,
19};
20
21/// A test helper used to provide an implementation of a bindings context.
22pub struct FakeBindingsCtx<TimerId, Event: Debug, State, FrameMeta> {
23    /// Provides [`RngContext`].
24    pub rng: FakeCryptoRng,
25    /// Provides [`TimerContext`].
26    pub timers: FakeTimerCtx<TimerId>,
27    /// Provides [`EventContext`].
28    pub events: FakeEventCtx<Event>,
29    /// Provides [`SendFrameContext`].
30    pub frames: FakeFrameCtx<FrameMeta>,
31    /// Generic state used by specific tests.
32    pub state: State,
33}
34
35impl<TimerId, Event: Debug, State, FrameMeta> ContextProvider
36    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
37{
38    type Context = Self;
39    fn context(&mut self) -> &mut Self::Context {
40        self
41    }
42}
43
44impl<TimerId, Event: Debug, State: Default, FrameMeta> Default
45    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
46{
47    fn default() -> Self {
48        Self {
49            rng: FakeCryptoRng::new_xorshift(0),
50            timers: FakeTimerCtx::default(),
51            events: FakeEventCtx::default(),
52            frames: FakeFrameCtx::default(),
53            state: Default::default(),
54        }
55    }
56}
57
58impl<TimerId, Event: Debug, State, FrameMeta> FakeBindingsCtx<TimerId, Event, State, FrameMeta> {
59    /// Seed the testing RNG with a specific value.
60    pub fn seed_rng(&mut self, seed: u128) {
61        self.rng = FakeCryptoRng::new_xorshift(seed);
62    }
63
64    /// Takes all the accumulated events from the [`FakeEventCtx`].
65    pub fn take_events(&mut self) -> Vec<Event> {
66        self.events.take()
67    }
68}
69
70impl<TimerId, Event: Debug, State, FrameMeta> RngContext
71    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
72{
73    type Rng<'a>
74        = FakeCryptoRng
75    where
76        Self: 'a;
77
78    fn rng(&mut self) -> Self::Rng<'_> {
79        self.rng.clone()
80    }
81}
82
83impl<TimerId, Event: Debug, State, FrameMeta> InstantBindingsTypes
84    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
85{
86    type Instant = FakeInstant;
87    type AtomicInstant = FakeAtomicInstant;
88}
89
90impl<TimerId, Event: Debug, State, FrameMeta> InstantContext
91    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
92{
93    fn now(&self) -> Self::Instant {
94        self.timers.now()
95    }
96}
97
98impl<Id: Debug + PartialEq + Clone + Send + Sync, Event: Debug, State, FrameMeta> TimerBindingsTypes
99    for FakeBindingsCtx<Id, Event, State, FrameMeta>
100{
101    type Timer = <FakeTimerCtx<Id> as TimerBindingsTypes>::Timer;
102    type DispatchId = <FakeTimerCtx<Id> as TimerBindingsTypes>::DispatchId;
103    type UniqueTimerId = <FakeTimerCtx<Id> as TimerBindingsTypes>::UniqueTimerId;
104}
105
106impl<Id: Debug + PartialEq + Clone + Send + Sync, Event: Debug, State, FrameMeta> TimerContext
107    for FakeBindingsCtx<Id, Event, State, FrameMeta>
108{
109    fn new_timer(&mut self, id: Self::DispatchId) -> Self::Timer {
110        self.timers.new_timer(id)
111    }
112
113    fn schedule_timer_instant(
114        &mut self,
115        time: Self::Instant,
116        timer: &mut Self::Timer,
117    ) -> Option<Self::Instant> {
118        self.timers.schedule_timer_instant(time, timer)
119    }
120
121    fn cancel_timer(&mut self, timer: &mut Self::Timer) -> Option<Self::Instant> {
122        self.timers.cancel_timer(timer)
123    }
124
125    fn scheduled_instant(&self, timer: &mut Self::Timer) -> Option<Self::Instant> {
126        self.timers.scheduled_instant(timer)
127    }
128
129    fn unique_timer_id(&self, timer: &Self::Timer) -> Self::UniqueTimerId {
130        self.timers.unique_timer_id(timer)
131    }
132}
133
134impl<Id, Event: Debug, State, FrameMeta> EventContext<Event>
135    for FakeBindingsCtx<Id, Event, State, FrameMeta>
136{
137    fn on_event(&mut self, event: Event) {
138        self.events.on_event(event)
139    }
140}
141
142impl<Id, Event: Debug, State, FrameMeta> ReferenceNotifiers
143    for FakeBindingsCtx<Id, Event, State, FrameMeta>
144{
145    type ReferenceReceiver<T: 'static> = Never;
146
147    type ReferenceNotifier<T: Send + 'static> = Never;
148
149    fn new_reference_notifier<T: Send + 'static>(
150        debug_references: DynDebugReferences,
151    ) -> (Self::ReferenceNotifier<T>, Self::ReferenceReceiver<T>) {
152        // NB: We don't want deferred destruction in core tests. These are
153        // always single-threaded and single-task, and we want to encourage
154        // explicit cleanup.
155        panic!(
156            "FakeBindingsCtx can't create deferred reference notifiers for type {}: \
157            debug_references={debug_references:?}",
158            core::any::type_name::<T>()
159        );
160    }
161}
162
163impl<Id, Event: Debug, State, FrameMeta> DeferredResourceRemovalContext
164    for FakeBindingsCtx<Id, Event, State, FrameMeta>
165{
166    fn defer_removal<T: Send + 'static>(&mut self, receiver: Self::ReferenceReceiver<T>) {
167        match receiver {}
168    }
169}
170
171impl<TimerId, Event: Debug, State, FrameMeta> WithFakeTimerContext<TimerId>
172    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
173{
174    fn with_fake_timer_ctx<O, F: FnOnce(&FakeTimerCtx<TimerId>) -> O>(&self, f: F) -> O {
175        f(&self.timers)
176    }
177
178    fn with_fake_timer_ctx_mut<O, F: FnOnce(&mut FakeTimerCtx<TimerId>) -> O>(
179        &mut self,
180        f: F,
181    ) -> O {
182        f(&mut self.timers)
183    }
184}
185
186impl<TimerId, Event: Debug, State, FrameMeta> AlwaysDefaultsSettingsContext
187    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
188{
189}