summaryrefslogtreecommitdiffstats
path: root/tokio/src/runtime/tests/mock_schedule.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tokio/src/runtime/tests/mock_schedule.rs')
-rw-r--r--tokio/src/runtime/tests/mock_schedule.rs131
1 files changed, 131 insertions, 0 deletions
diff --git a/tokio/src/runtime/tests/mock_schedule.rs b/tokio/src/runtime/tests/mock_schedule.rs
new file mode 100644
index 00000000..ab15c54e
--- /dev/null
+++ b/tokio/src/runtime/tests/mock_schedule.rs
@@ -0,0 +1,131 @@
+#![allow(warnings)]
+
+use crate::runtime::task::{Header, Schedule, Task};
+
+use std::collections::VecDeque;
+use std::sync::Mutex;
+use std::thread;
+
+pub(crate) struct Mock {
+ inner: Mutex<Inner>,
+}
+
+pub(crate) struct Noop;
+pub(crate) static NOOP_SCHEDULE: Noop = Noop;
+
+struct Inner {
+ calls: VecDeque<Call>,
+ pending_run: VecDeque<Task<Mock>>,
+ pending_drop: VecDeque<Task<Mock>>,
+}
+
+unsafe impl Send for Inner {}
+unsafe impl Sync for Inner {}
+
+#[derive(Debug, Eq, PartialEq)]
+enum Call {
+ Bind(*const Header),
+ Release,
+ ReleaseLocal,
+ Schedule,
+}
+
+pub(crate) fn mock() -> Mock {
+ Mock {
+ inner: Mutex::new(Inner {
+ calls: VecDeque::new(),
+ pending_run: VecDeque::new(),
+ pending_drop: VecDeque::new(),
+ }),
+ }
+}
+
+impl Mock {
+ pub(crate) fn bind(self, task: &Task<Mock>) -> Self {
+ self.push(Call::Bind(task.header() as *const _));
+ self
+ }
+
+ pub(crate) fn release(self) -> Self {
+ self.push(Call::Release);
+ self
+ }
+
+ pub(crate) fn release_local(self) -> Self {
+ self.push(Call::ReleaseLocal);
+ self
+ }
+
+ pub(crate) fn schedule(self) -> Self {
+ self.push(Call::Schedule);
+ self
+ }
+
+ pub(crate) fn next_pending_run(&self) -> Option<Task<Self>> {
+ self.inner.lock().unwrap().pending_run.pop_front()
+ }
+
+ pub(crate) fn next_pending_drop(&self) -> Option<Task<Self>> {
+ self.inner.lock().unwrap().pending_drop.pop_front()
+ }
+
+ fn push(&self, call: Call) {
+ self.inner.lock().unwrap().calls.push_back(call);
+ }
+
+ fn next(&self, name: &str) -> Call {
+ self.inner
+ .lock()
+ .unwrap()
+ .calls
+ .pop_front()
+ .expect(&format!("received `{}`, but none expected", name))
+ }
+}
+
+impl Schedule for Mock {
+ fn bind(&self, task: &Task<Self>) {
+ match self.next("bind") {
+ Call::Bind(ptr) => {
+ assert!(ptr.eq(&(task.header() as *const _)));
+ }
+ call => panic!("expected `Bind`, was {:?}", call),
+ }
+ }
+
+ fn release(&self, task: Task<Self>) {
+ match self.next("release") {
+ Call::Release => {
+ self.inner.lock().unwrap().pending_drop.push_back(task);
+ }
+ call => panic!("expected `Release`, was {:?}", call),
+ }
+ }
+
+ fn release_local(&self, _task: &Task<Self>) {
+ assert_eq!(Call::ReleaseLocal, self.next("release_local"));
+ }
+
+ fn schedule(&self, task: Task<Self>) {
+ self.inner.lock().unwrap().pending_run.push_back(task);
+ assert_eq!(Call::Schedule, self.next("schedule"));
+ }
+}
+
+impl Drop for Mock {
+ fn drop(&mut self) {
+ if !thread::panicking() {
+ assert!(self.inner.lock().unwrap().calls.is_empty());
+ }
+ }
+}
+
+impl Schedule for Noop {
+ fn bind(&self, _task: &Task<Self>) {}
+
+ fn release(&self, _task: Task<Self>) {}
+
+ fn release_local(&self, _task: &Task<Self>) {}
+
+ fn schedule(&self, _task: Task<Self>) {}
+}