Skip to main content

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::fmt::Debug;
9
10use crate::sync::DynDebugReferences;
11use crate::testutil::{
12    AlwaysDefaultsSettingsContext, FakeAtomicInstant, FakeCryptoRng, FakeEventCtx, FakeFrameCtx,
13    FakeInstant, FakeTimerCtx, WithFakeTimerContext,
14};
15use crate::{
16    ContextProvider, DeferredResourceRemovalContext, EventContext, InstantBindingsTypes,
17    InstantContext, MatcherBindingsTypes, ReferenceNotifiers, RngContext, TimerBindingsTypes,
18    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> crate::BindingsSyncTypes
84    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
85{
86    type Mutex = crate::sync::lock_impl::RawMutex;
87    type RwLock = crate::sync::lock_impl::RawRwLock;
88    type Once = crate::sync::lock_impl::Once;
89}
90
91impl<TimerId, Event: Debug, State, FrameMeta> InstantBindingsTypes
92    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
93{
94    type Instant = FakeInstant;
95    type AtomicInstant = FakeAtomicInstant;
96}
97
98impl<TimerId, Event: Debug, State, FrameMeta> InstantContext
99    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
100{
101    fn now(&self) -> Self::Instant {
102        self.timers.now()
103    }
104}
105
106impl<Id: Debug + PartialEq + Clone + Send + Sync, Event: Debug, State, FrameMeta> TimerBindingsTypes
107    for FakeBindingsCtx<Id, Event, State, FrameMeta>
108{
109    type Timer = <FakeTimerCtx<Id> as TimerBindingsTypes>::Timer;
110    type DispatchId = <FakeTimerCtx<Id> as TimerBindingsTypes>::DispatchId;
111    type UniqueTimerId = <FakeTimerCtx<Id> as TimerBindingsTypes>::UniqueTimerId;
112}
113
114impl<Id: Debug + PartialEq + Clone + Send + Sync, Event: Debug, State, FrameMeta> TimerContext
115    for FakeBindingsCtx<Id, Event, State, FrameMeta>
116{
117    fn new_timer(&mut self, id: Self::DispatchId) -> Self::Timer {
118        self.timers.new_timer(id)
119    }
120
121    fn schedule_timer_instant(
122        &mut self,
123        time: Self::Instant,
124        timer: &mut Self::Timer,
125    ) -> Option<Self::Instant> {
126        self.timers.schedule_timer_instant(time, timer)
127    }
128
129    fn cancel_timer(&mut self, timer: &mut Self::Timer) -> Option<Self::Instant> {
130        self.timers.cancel_timer(timer)
131    }
132
133    fn scheduled_instant(&self, timer: &mut Self::Timer) -> Option<Self::Instant> {
134        self.timers.scheduled_instant(timer)
135    }
136
137    fn unique_timer_id(&self, timer: &Self::Timer) -> Self::UniqueTimerId {
138        self.timers.unique_timer_id(timer)
139    }
140}
141
142impl<Id, Event: Debug, State, FrameMeta> EventContext<Event>
143    for FakeBindingsCtx<Id, Event, State, FrameMeta>
144{
145    fn on_event(&mut self, event: Event) {
146        self.events.on_event(event)
147    }
148}
149
150impl<Id, Event: Debug, State, FrameMeta> ReferenceNotifiers
151    for FakeBindingsCtx<Id, Event, State, FrameMeta>
152{
153    type ReferenceReceiver<T: 'static> = !;
154
155    type ReferenceNotifier<T: Send + 'static> = !;
156
157    fn new_reference_notifier<T: Send + 'static>(
158        debug_references: DynDebugReferences,
159    ) -> (Self::ReferenceNotifier<T>, Self::ReferenceReceiver<T>) {
160        // NB: We don't want deferred destruction in core tests. These are
161        // always single-threaded and single-task, and we want to encourage
162        // explicit cleanup.
163        panic!(
164            "FakeBindingsCtx can't create deferred reference notifiers for type {}: \
165            debug_references={debug_references:?}",
166            core::any::type_name::<T>()
167        );
168    }
169}
170
171impl<Id, Event: Debug, State, FrameMeta> DeferredResourceRemovalContext
172    for FakeBindingsCtx<Id, Event, State, FrameMeta>
173{
174    fn defer_removal<T: Send + 'static>(&mut self, receiver: Self::ReferenceReceiver<T>) {
175        match receiver {}
176    }
177}
178
179impl<TimerId, Event: Debug, State, FrameMeta> WithFakeTimerContext<TimerId>
180    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
181{
182    fn with_fake_timer_ctx<O, F: FnOnce(&FakeTimerCtx<TimerId>) -> O>(&self, f: F) -> O {
183        f(&self.timers)
184    }
185
186    fn with_fake_timer_ctx_mut<O, F: FnOnce(&mut FakeTimerCtx<TimerId>) -> O>(
187        &mut self,
188        f: F,
189    ) -> O {
190        f(&mut self.timers)
191    }
192}
193
194impl<TimerId, Event: Debug, State, FrameMeta> AlwaysDefaultsSettingsContext
195    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
196{
197}
198
199impl<TimerId: Debug, Event: Debug, State, FrameMeta> MatcherBindingsTypes
200    for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
201{
202    type DeviceClass = ();
203    type BindingsPacketMatcher = !;
204}