From 4c5e989df3f891bf5bd2692643f2a935e1f47820 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Wed, 3 Apr 2019 00:14:14 +0000 Subject: [PATCH 01/12] futures: add support for std::futures::Future and futures 0.3 - To support async functions, the inner future must be boxed. - If someone can figure out how to support !Unpin futures, please do so. --- tracing-futures/src/lib.rs | 39 ++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/tracing-futures/src/lib.rs b/tracing-futures/src/lib.rs index 48fb80ed54..55d6374678 100644 --- a/tracing-futures/src/lib.rs +++ b/tracing-futures/src/lib.rs @@ -22,7 +22,12 @@ extern crate tokio_executor; #[cfg_attr(test, macro_use)] extern crate tracing; -use futures::{Future, Poll, Sink, StartSend, Stream}; +use std::{ + pin::Pin, + task::Context, +}; + +use futures::{Sink, StartSend, Stream}; use tracing::{dispatcher, Dispatch, Span}; pub mod executor; @@ -32,6 +37,10 @@ pub trait Instrument: Sized { fn instrument(self, span: Span) -> Instrumented { Instrumented { inner: self, span } } + + fn boxed_instrument(self, span: Span) -> Instrumented>> { + Instrumented { inner: Box::pin(self), span } + } } pub trait WithSubscriber: Sized { @@ -60,11 +69,21 @@ pub struct WithDispatch { impl Instrument for T {} -impl Future for Instrumented { +impl std::future::Future for Instrumented

{ + type Output = P::Output; + + fn poll(self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll { + let this = self.get_mut(); + let _enter = this.span.enter(); + Pin::new(&mut this.inner).poll(lw) + } +} + +impl futures::Future for Instrumented { type Item = T::Item; type Error = T::Error; - fn poll(&mut self) -> Poll { + fn poll(&mut self) -> futures::Poll { let _enter = self.span.enter(); self.inner.poll() } @@ -74,7 +93,7 @@ impl Stream for Instrumented { type Item = T::Item; type Error = T::Error; - fn poll(&mut self) -> Poll, Self::Error> { + fn poll(&mut self) -> futures::Poll, Self::Error> { let _enter = self.span.enter(); self.inner.poll() } @@ -89,7 +108,7 @@ impl Sink for Instrumented { self.inner.start_send(item) } - fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { + fn poll_complete(&mut self) -> futures::Poll<(), Self::SinkError> { let _enter = self.span.enter(); self.inner.poll_complete() } @@ -116,11 +135,11 @@ impl Instrumented { impl WithSubscriber for T {} -impl Future for WithDispatch { +impl futures::Future for WithDispatch { type Item = T::Item; type Error = T::Error; - fn poll(&mut self) -> Poll { + fn poll(&mut self) -> futures::Poll { let inner = &mut self.inner; dispatcher::with_default(&self.dispatch, || inner.poll()) } @@ -157,7 +176,7 @@ mod tests { extern crate tokio; use super::{test_support::*, *}; - use futures::{future, stream, task, Async}; + use futures::{future, stream, task, Async, Future}; use tracing::{subscriber::with_default, Level}; struct PollN { @@ -166,10 +185,10 @@ mod tests { polls: usize, } - impl Future for PollN { + impl futures::Future for PollN { type Item = T; type Error = E; - fn poll(&mut self) -> Poll { + fn poll(&mut self) -> futures::Poll { self.polls += 1; if self.polls == self.finish_at { self.and_return From 15c663a4e075f78142e0514af8b9ce58ac489136 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Mon, 8 Jul 2019 20:42:30 +0000 Subject: [PATCH 02/12] futures: support std::futures::Future with !Unpin futures - Thank you Eliza Weisman (hawkw) for the solution using the pin-utils crate - Added feature gates for the futures 0.1, tokio, and std::future implementations --- tracing-futures/Cargo.toml | 7 +++-- tracing-futures/src/executor.rs | 29 +++++++++++++------- tracing-futures/src/lib.rs | 47 +++++++++++++++++++++++++-------- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/tracing-futures/Cargo.toml b/tracing-futures/Cargo.toml index 264e54d8fa..df5901000a 100644 --- a/tracing-futures/Cargo.toml +++ b/tracing-futures/Cargo.toml @@ -5,10 +5,13 @@ authors = ["Eliza Weisman "] edition = "2018" [features] -default = ["tokio"] +default = ["futures-01", "tokio"] +futures-01 = ["futures"] +std-future = ["pin-utils"] [dependencies] -futures = "0.1" +futures = { version = "0.1", optional = true } +pin-utils = { version = "0.1.0-alpha.4", optional = true } tracing = "0.1" tokio = { version = "0.1", optional = true } tokio-executor = { version = "0.1", optional = true } diff --git a/tracing-futures/src/executor.rs b/tracing-futures/src/executor.rs index 521f09dfc7..24bf37d94d 100644 --- a/tracing-futures/src/executor.rs +++ b/tracing-futures/src/executor.rs @@ -1,15 +1,14 @@ use crate::{Instrument, Instrumented, WithDispatch}; +#[cfg(feature = "futures-01")] use futures::{ - future::{ExecuteError, Executor}, - Future, -}; - -#[cfg(feature = "tokio")] -use tokio::{ - executor::{Executor as TokioExecutor, SpawnError}, - runtime::{current_thread, Runtime, TaskExecutor}, + future::{ExecuteError, Executor}, + Future, }; +#[cfg(feature = "futures-01")] +use tokio::executor::{Executor as TokioExecutor, SpawnError}; +use tokio::runtime::{current_thread, Runtime, TaskExecutor}; +#[cfg(feature = "futures-01")] macro_rules! deinstrument_err { ($e:expr) => { $e.map_err(|e| { @@ -20,6 +19,7 @@ macro_rules! deinstrument_err { }; } +#[cfg(feature = "futures-01")] impl Executor for Instrumented where T: Executor>, @@ -31,7 +31,7 @@ where } } -#[cfg(feature = "tokio")] +#[cfg(all(feature = "futures-01", feature = "tokio"))] impl TokioExecutor for Instrumented where T: TokioExecutor, @@ -56,6 +56,7 @@ impl Instrumented { /// /// This method simply wraps a call to `tokio::runtime::Runtime::spawn`, /// instrumenting the spawned future beforehand. + #[cfg(feature = "futures-01")] pub fn spawn(&mut self, future: F) -> &mut Self where F: Future + Send + 'static, @@ -80,6 +81,7 @@ impl Instrumented { /// /// This function panics if the executor is at capacity, if the provided /// future panics, or if called within an asynchronous execution context. + #[cfg(feature = "futures-01")] pub fn block_on(&mut self, future: F) -> Result where F: Send + 'static + Future, @@ -108,6 +110,7 @@ impl Instrumented { /// /// This method simply wraps a call to `current_thread::Runtime::spawn`, /// instrumenting the spawned future beforehand. + #[cfg(feature = "futures-01")] pub fn spawn(&mut self, future: F) -> &mut Self where F: Future + 'static, @@ -141,6 +144,7 @@ impl Instrumented { /// /// This function panics if the executor is at capacity, if the provided /// future panics, or if called within an asynchronous execution context. + #[cfg(feature = "futures-01")] pub fn block_on(&mut self, future: F) -> Result where F: 'static + Future, @@ -165,6 +169,7 @@ impl Instrumented { } } +#[cfg(feature = "futures-01")] impl Executor for WithDispatch where T: Executor>, @@ -176,7 +181,7 @@ where } } -#[cfg(feature = "tokio")] +#[cfg(all(feature = "futures-01", feature = "tokio"))] impl TokioExecutor for WithDispatch where T: TokioExecutor, @@ -202,6 +207,7 @@ impl WithDispatch { /// /// This method simply wraps a call to `tokio::runtime::Runtime::spawn`, /// instrumenting the spawned future beforehand. + #[cfg(feature = "futures-01")] pub fn spawn(&mut self, future: F) -> &mut Self where F: Future + Send + 'static, @@ -227,6 +233,7 @@ impl WithDispatch { /// /// This function panics if the executor is at capacity, if the provided /// future panics, or if called within an asynchronous execution context. + #[cfg(feature = "futures-01")] pub fn block_on(&mut self, future: F) -> Result where F: Send + 'static + Future, @@ -257,6 +264,7 @@ impl WithDispatch { /// /// This method simply wraps a call to `current_thread::Runtime::spawn`, /// instrumenting the spawned future beforehand. + #[cfg(feature = "futures-01")] pub fn spawn(&mut self, future: F) -> &mut Self where F: Future + 'static, @@ -290,6 +298,7 @@ impl WithDispatch { /// /// This function panics if the executor is at capacity, if the provided /// future panics, or if called within an asynchronous execution context. + #[cfg(feature = "futures-01")] pub fn block_on(&mut self, future: F) -> Result where F: 'static + Future, diff --git a/tracing-futures/src/lib.rs b/tracing-futures/src/lib.rs index 55d6374678..7eac5855c0 100644 --- a/tracing-futures/src/lib.rs +++ b/tracing-futures/src/lib.rs @@ -14,7 +14,10 @@ //! //! [`Instrument`]: trait.Instrument.html //! [`WithSubscriber`]: trait.WithSubscriber.html +#[cfg(feature = "futures-01")] extern crate futures; +#[cfg(feature = "std-future")] +extern crate pin_utils; #[cfg(feature = "tokio")] extern crate tokio; #[cfg(feature = "tokio-executor")] @@ -22,14 +25,19 @@ extern crate tokio_executor; #[cfg_attr(test, macro_use)] extern crate tracing; +#[cfg(feature = "std-future")] use std::{ pin::Pin, task::Context, }; +#[cfg(feature = "futures-01")] use futures::{Sink, StartSend, Stream}; -use tracing::{dispatcher, Dispatch, Span}; +#[cfg(feature = "futures-01")] +use tracing::dispatcher; +use tracing::{Dispatch, Span}; +#[cfg(feature = "tokio")] pub mod executor; // TODO: seal? @@ -37,10 +45,6 @@ pub trait Instrument: Sized { fn instrument(self, span: Span) -> Instrumented { Instrumented { inner: self, span } } - - fn boxed_instrument(self, span: Span) -> Instrumented>> { - Instrumented { inner: Box::pin(self), span } - } } pub trait WithSubscriber: Sized { @@ -69,16 +73,26 @@ pub struct WithDispatch { impl Instrument for T {} -impl std::future::Future for Instrumented

{ - type Output = P::Output; +#[cfg(feature = "std-future")] +impl Instrumented { + pin_utils::unsafe_pinned!(inner: T); +} - fn poll(self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll { - let this = self.get_mut(); - let _enter = this.span.enter(); - Pin::new(&mut this.inner).poll(lw) +#[cfg(feature = "std-future")] +impl std::future::Future for Instrumented { + type Output = T::Output; + + fn poll(mut self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll { + let span = self.as_ref().span.clone(); + let _enter = span.enter(); + self.as_mut().inner().poll(lw) } } +#[cfg(feature = "std-future")] +impl Unpin for Instrumented {} + +#[cfg(feature = "futures-01")] impl futures::Future for Instrumented { type Item = T::Item; type Error = T::Error; @@ -89,6 +103,7 @@ impl futures::Future for Instrumented { } } +#[cfg(feature = "futures-01")] impl Stream for Instrumented { type Item = T::Item; type Error = T::Error; @@ -99,6 +114,7 @@ impl Stream for Instrumented { } } +#[cfg(feature = "futures-01")] impl Sink for Instrumented { type SinkItem = T::SinkItem; type SinkError = T::SinkError; @@ -135,6 +151,7 @@ impl Instrumented { impl WithSubscriber for T {} +#[cfg(feature = "futures-01")] impl futures::Future for WithDispatch { type Item = T::Item; type Error = T::Error; @@ -146,6 +163,7 @@ impl futures::Future for WithDispatch { } impl WithDispatch { + #[cfg(feature = "tokio")] pub(crate) fn with_dispatch(&self, inner: U) -> WithDispatch { WithDispatch { dispatch: self.dispatch.clone(), @@ -176,6 +194,8 @@ mod tests { extern crate tokio; use super::{test_support::*, *}; + + #[cfg(feature = "futures-01")] use futures::{future, stream, task, Async, Future}; use tracing::{subscriber::with_default, Level}; @@ -185,6 +205,7 @@ mod tests { polls: usize, } + #[cfg(feature = "futures-01")] impl futures::Future for PollN { type Item = T; type Error = E; @@ -220,6 +241,7 @@ mod tests { } } + #[cfg(feature = "futures-01")] #[test] fn future_enter_exit_is_reasonable() { let (subscriber, handle) = subscriber::mock() @@ -239,6 +261,7 @@ mod tests { handle.assert_finished(); } + #[cfg(feature = "futures-01")] #[test] fn future_error_ends_span() { let (subscriber, handle) = subscriber::mock() @@ -259,6 +282,7 @@ mod tests { handle.assert_finished(); } + #[cfg(feature = "futures-01")] #[test] fn stream_enter_exit_is_reasonable() { let (subscriber, handle) = subscriber::mock() @@ -282,6 +306,7 @@ mod tests { handle.assert_finished(); } + #[cfg(feature = "futures-01")] #[test] fn span_follows_future_onto_threadpool() { let (subscriber, handle) = subscriber::mock() From 00e44b3298699e08935ced61a4eefbf1d157d08b Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Mon, 8 Jul 2019 20:56:37 +0000 Subject: [PATCH 03/12] futures: fix formatting --- tracing-futures/src/executor.rs | 4 ++-- tracing-futures/src/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tracing-futures/src/executor.rs b/tracing-futures/src/executor.rs index 24bf37d94d..3a6a2bd2b4 100644 --- a/tracing-futures/src/executor.rs +++ b/tracing-futures/src/executor.rs @@ -1,8 +1,8 @@ use crate::{Instrument, Instrumented, WithDispatch}; #[cfg(feature = "futures-01")] use futures::{ - future::{ExecuteError, Executor}, - Future, + future::{ExecuteError, Executor}, + Future, }; #[cfg(feature = "futures-01")] use tokio::executor::{Executor as TokioExecutor, SpawnError}; diff --git a/tracing-futures/src/lib.rs b/tracing-futures/src/lib.rs index 7eac5855c0..1959531c7b 100644 --- a/tracing-futures/src/lib.rs +++ b/tracing-futures/src/lib.rs @@ -27,8 +27,8 @@ extern crate tracing; #[cfg(feature = "std-future")] use std::{ - pin::Pin, - task::Context, + pin::Pin, + task::Context, }; #[cfg(feature = "futures-01")] From a332aed4535c23268837ba3ec0d7ba6095b21211 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Mon, 8 Jul 2019 21:05:44 +0000 Subject: [PATCH 04/12] futures: rustfmt --- tracing-futures/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tracing-futures/src/lib.rs b/tracing-futures/src/lib.rs index 1959531c7b..05e0600e15 100644 --- a/tracing-futures/src/lib.rs +++ b/tracing-futures/src/lib.rs @@ -26,10 +26,7 @@ extern crate tokio_executor; extern crate tracing; #[cfg(feature = "std-future")] -use std::{ - pin::Pin, - task::Context, -}; +use std::{pin::Pin, task::Context}; #[cfg(feature = "futures-01")] use futures::{Sink, StartSend, Stream}; From a93068d16da0ac678c6033fb0329d09508e2f872 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Thu, 11 Jul 2019 01:30:56 +0000 Subject: [PATCH 05/12] futures: use tokio-test for testing std::future::Future unit tests --- tracing-futures/Cargo.toml | 1 + tracing-futures/src/lib.rs | 83 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/tracing-futures/Cargo.toml b/tracing-futures/Cargo.toml index df5901000a..499b514dc3 100644 --- a/tracing-futures/Cargo.toml +++ b/tracing-futures/Cargo.toml @@ -18,5 +18,6 @@ tokio-executor = { version = "0.1", optional = true } [dev-dependencies] tokio = "0.1.22" +tokio-test = { git = "https://github.com/tokio-rs/tokio.git" } tracing-fmt = { path = "../tracing-fmt" } tracing-core = "0.1.2" diff --git a/tracing-futures/src/lib.rs b/tracing-futures/src/lib.rs index 05e0600e15..69b1e2d393 100644 --- a/tracing-futures/src/lib.rs +++ b/tracing-futures/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(all(feature = "std-future", test), feature(futures_api))] + //! Futures compatibility for `tracing` //! //! # Feature flags @@ -194,6 +196,8 @@ mod tests { #[cfg(feature = "futures-01")] use futures::{future, stream, task, Async, Future}; + #[cfg(feature = "std-future")] + use tokio_test::task::MockTask; use tracing::{subscriber::with_default, Level}; struct PollN { @@ -202,6 +206,30 @@ mod tests { polls: usize, } + #[cfg(feature = "std-future")] + impl std::future::Future for PollN + where + T: Unpin, + E: Unpin, + { + type Output = Result; + fn poll(self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll { + let this = self.get_mut(); + + this.polls += 1; + if this.polls == this.finish_at { + let value = this.and_return + .take() + .expect("polled after ready"); + + std::task::Poll::Ready(value) + } else { + lw.waker().wake_by_ref(); + std::task::Poll::Pending + } + } + } + #[cfg(feature = "futures-01")] impl futures::Future for PollN { type Item = T; @@ -238,6 +266,21 @@ mod tests { } } + #[cfg(feature = "std-future")] + fn block_on_future(task: &mut MockTask, future: F) -> F::Output + where + F: std::future::Future, + { + let mut future = Box::pin(future); + + loop { + match task.poll(&mut future) { + std::task::Poll::Ready(v) => break v, + _ => {}, + } + } + } + #[cfg(feature = "futures-01")] #[test] fn future_enter_exit_is_reasonable() { @@ -333,4 +376,44 @@ mod tests { }); handle.assert_finished(); } + + #[cfg(feature = "std-future")] + #[test] + fn std_future_enter_exit_is_reasonable() { + let (subscriber, handle) = subscriber::mock() + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .drop_span(span::mock().named("foo")) + .done() + .run_with_handle(); + let mut task = MockTask::new(); + with_default(subscriber, || { + let future = PollN::new_ok(2) + .instrument(span!(Level::TRACE, "foo")); + block_on_future(&mut task, future).unwrap(); + }); + handle.assert_finished(); + } + + #[cfg(feature = "std-future")] + #[test] + fn std_future_error_ends_span() { + let (subscriber, handle) = subscriber::mock() + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .drop_span(span::mock().named("foo")) + .done() + .run_with_handle(); + let mut task = MockTask::new(); + with_default(subscriber, || { + let future = PollN::new_err(2) + .instrument(span!(Level::TRACE, "foo")); + block_on_future(&mut task, future).unwrap_err(); + }); + handle.assert_finished(); + } } From a24b1b40b3dfc383a47cb9ca1b023ca9968c87b7 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Thu, 11 Jul 2019 01:33:05 +0000 Subject: [PATCH 06/12] futures: rustfmt --- tracing-futures/src/lib.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tracing-futures/src/lib.rs b/tracing-futures/src/lib.rs index 69b1e2d393..945e8bd344 100644 --- a/tracing-futures/src/lib.rs +++ b/tracing-futures/src/lib.rs @@ -218,9 +218,7 @@ mod tests { this.polls += 1; if this.polls == this.finish_at { - let value = this.and_return - .take() - .expect("polled after ready"); + let value = this.and_return.take().expect("polled after ready"); std::task::Poll::Ready(value) } else { @@ -276,7 +274,7 @@ mod tests { loop { match task.poll(&mut future) { std::task::Poll::Ready(v) => break v, - _ => {}, + _ => {} } } } @@ -390,8 +388,7 @@ mod tests { .run_with_handle(); let mut task = MockTask::new(); with_default(subscriber, || { - let future = PollN::new_ok(2) - .instrument(span!(Level::TRACE, "foo")); + let future = PollN::new_ok(2).instrument(span!(Level::TRACE, "foo")); block_on_future(&mut task, future).unwrap(); }); handle.assert_finished(); @@ -410,8 +407,7 @@ mod tests { .run_with_handle(); let mut task = MockTask::new(); with_default(subscriber, || { - let future = PollN::new_err(2) - .instrument(span!(Level::TRACE, "foo")); + let future = PollN::new_err(2).instrument(span!(Level::TRACE, "foo")); block_on_future(&mut task, future).unwrap_err(); }); handle.assert_finished(); From 5abf588caecff0ee38c94f6637f44ccc4ed5ee9d Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Thu, 11 Jul 2019 04:01:19 +0000 Subject: [PATCH 07/12] futures: remove futures_api conditional include --- tracing-futures/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tracing-futures/src/lib.rs b/tracing-futures/src/lib.rs index 945e8bd344..3a5d415d0c 100644 --- a/tracing-futures/src/lib.rs +++ b/tracing-futures/src/lib.rs @@ -1,5 +1,3 @@ -#![cfg_attr(all(feature = "std-future", test), feature(futures_api))] - //! Futures compatibility for `tracing` //! //! # Feature flags From 8097d08ea13698fe3c8e71750fb8522a2fee1678 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Sun, 14 Jul 2019 09:11:52 +0000 Subject: [PATCH 08/12] futures: add testing of all features under nightly --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index c339685c88..6e05bb8dac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,3 +28,6 @@ jobs: - script: cargo test --features=doctest-readme --all name: "doctest readme" rust: nightly + - script: (cd tracing-futures && cargo test --all-features) + name: "futures all features" + rust: nightly From 94a128c78091a2fd1aea2a2002d6b4cbefe5d866 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Sun, 14 Jul 2019 22:53:42 +0000 Subject: [PATCH 09/12] futures: separate std-future tests into submodule that is only run on the nightly toolchain --- .travis.yml | 4 +- tracing-futures/Cargo.toml | 1 - tracing-futures/src/lib.rs | 77 ------------ tracing-futures/test_std_future/Cargo.toml | 18 +++ tracing-futures/test_std_future/tests/test.rs | 111 ++++++++++++++++++ 5 files changed, 131 insertions(+), 80 deletions(-) create mode 100644 tracing-futures/test_std_future/Cargo.toml create mode 100644 tracing-futures/test_std_future/tests/test.rs diff --git a/.travis.yml b/.travis.yml index 6e05bb8dac..c07103531d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,6 @@ jobs: - script: cargo test --features=doctest-readme --all name: "doctest readme" rust: nightly - - script: (cd tracing-futures && cargo test --all-features) - name: "futures all features" + - script: (cd tracing-futures/test_std_futures && cargo test) + name: "futures nightly" rust: nightly diff --git a/tracing-futures/Cargo.toml b/tracing-futures/Cargo.toml index 499b514dc3..df5901000a 100644 --- a/tracing-futures/Cargo.toml +++ b/tracing-futures/Cargo.toml @@ -18,6 +18,5 @@ tokio-executor = { version = "0.1", optional = true } [dev-dependencies] tokio = "0.1.22" -tokio-test = { git = "https://github.com/tokio-rs/tokio.git" } tracing-fmt = { path = "../tracing-fmt" } tracing-core = "0.1.2" diff --git a/tracing-futures/src/lib.rs b/tracing-futures/src/lib.rs index 3a5d415d0c..05e0600e15 100644 --- a/tracing-futures/src/lib.rs +++ b/tracing-futures/src/lib.rs @@ -194,8 +194,6 @@ mod tests { #[cfg(feature = "futures-01")] use futures::{future, stream, task, Async, Future}; - #[cfg(feature = "std-future")] - use tokio_test::task::MockTask; use tracing::{subscriber::with_default, Level}; struct PollN { @@ -204,28 +202,6 @@ mod tests { polls: usize, } - #[cfg(feature = "std-future")] - impl std::future::Future for PollN - where - T: Unpin, - E: Unpin, - { - type Output = Result; - fn poll(self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll { - let this = self.get_mut(); - - this.polls += 1; - if this.polls == this.finish_at { - let value = this.and_return.take().expect("polled after ready"); - - std::task::Poll::Ready(value) - } else { - lw.waker().wake_by_ref(); - std::task::Poll::Pending - } - } - } - #[cfg(feature = "futures-01")] impl futures::Future for PollN { type Item = T; @@ -262,21 +238,6 @@ mod tests { } } - #[cfg(feature = "std-future")] - fn block_on_future(task: &mut MockTask, future: F) -> F::Output - where - F: std::future::Future, - { - let mut future = Box::pin(future); - - loop { - match task.poll(&mut future) { - std::task::Poll::Ready(v) => break v, - _ => {} - } - } - } - #[cfg(feature = "futures-01")] #[test] fn future_enter_exit_is_reasonable() { @@ -372,42 +333,4 @@ mod tests { }); handle.assert_finished(); } - - #[cfg(feature = "std-future")] - #[test] - fn std_future_enter_exit_is_reasonable() { - let (subscriber, handle) = subscriber::mock() - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - let mut task = MockTask::new(); - with_default(subscriber, || { - let future = PollN::new_ok(2).instrument(span!(Level::TRACE, "foo")); - block_on_future(&mut task, future).unwrap(); - }); - handle.assert_finished(); - } - - #[cfg(feature = "std-future")] - #[test] - fn std_future_error_ends_span() { - let (subscriber, handle) = subscriber::mock() - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - let mut task = MockTask::new(); - with_default(subscriber, || { - let future = PollN::new_err(2).instrument(span!(Level::TRACE, "foo")); - block_on_future(&mut task, future).unwrap_err(); - }); - handle.assert_finished(); - } } diff --git a/tracing-futures/test_std_future/Cargo.toml b/tracing-futures/test_std_future/Cargo.toml new file mode 100644 index 0000000000..7788cf5da4 --- /dev/null +++ b/tracing-futures/test_std_future/Cargo.toml @@ -0,0 +1,18 @@ +# Note: these tests depend on crates that use nightly features which do not +# run under stable and beta toolchains. +# +# Do not add these tests to the other tracing-futures tests unless the +# minimum Rust version is at least 1.36. +[workspace] + +[package] +name = "test_std_future" +version = "0.1.0" +publish = false +edition = "2018" + +[dependencies] +tokio-test = { git = "https://github.com/tokio-rs/tokio.git" } +tracing = "0.1" +tracing-core = "0.1.2" +tracing-futures = { path = "..", features = ["std-future"] } diff --git a/tracing-futures/test_std_future/tests/test.rs b/tracing-futures/test_std_future/tests/test.rs new file mode 100644 index 0000000000..650f67d8cd --- /dev/null +++ b/tracing-futures/test_std_future/tests/test.rs @@ -0,0 +1,111 @@ +#[macro_use] +extern crate tracing; +extern crate tracing_core; + +pub use self::support as test_support; +// This has to have the same name as the module in `tracing`. +#[path = "../../../tracing/tests/support/mod.rs"] +pub mod support; + +use std::pin::Pin; +use std::task::Context; + +use support::*; +use tokio_test::task::MockTask; +use tracing::{subscriber::with_default, Level}; +use tracing_futures::Instrument; + +struct PollN { + and_return: Option>, + finish_at: usize, + polls: usize, +} + +impl std::future::Future for PollN +where + T: Unpin, + E: Unpin, +{ + type Output = Result; + fn poll(self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll { + let this = self.get_mut(); + + this.polls += 1; + if this.polls == this.finish_at { + let value = this.and_return.take().expect("polled after ready"); + + std::task::Poll::Ready(value) + } else { + lw.waker().wake_by_ref(); + std::task::Poll::Pending + } + } +} + +impl PollN<(), ()> { + fn new_ok(finish_at: usize) -> Self { + Self { + and_return: Some(Ok(())), + finish_at, + polls: 0, + } + } + + fn new_err(finish_at: usize) -> Self { + Self { + and_return: Some(Err(())), + finish_at, + polls: 0, + } + } +} + +fn block_on_future(task: &mut MockTask, future: F) -> F::Output +where + F: std::future::Future, +{ + let mut future = Box::pin(future); + + loop { + match task.poll(&mut future) { + std::task::Poll::Ready(v) => break v, + _ => {} + } + } +} + +#[test] +fn std_future_enter_exit_is_reasonable() { + let (subscriber, handle) = subscriber::mock() + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .drop_span(span::mock().named("foo")) + .done() + .run_with_handle(); + let mut task = MockTask::new(); + with_default(subscriber, || { + let future = PollN::new_ok(2).instrument(span!(Level::TRACE, "foo")); + block_on_future(&mut task, future).unwrap(); + }); + handle.assert_finished(); +} + +#[test] +fn std_future_error_ends_span() { + let (subscriber, handle) = subscriber::mock() + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .drop_span(span::mock().named("foo")) + .done() + .run_with_handle(); + let mut task = MockTask::new(); + with_default(subscriber, || { + let future = PollN::new_err(2).instrument(span!(Level::TRACE, "foo")); + block_on_future(&mut task, future).unwrap_err(); + }); + handle.assert_finished(); +} From d21ef296eccba9d6959504847fd1e2944833e289 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Sun, 14 Jul 2019 23:28:28 +0000 Subject: [PATCH 10/12] futures: move futures-01 tests to submodule --- tracing-futures/src/lib.rs | 228 ++++++++++++++++++------------------- 1 file changed, 114 insertions(+), 114 deletions(-) diff --git a/tracing-futures/src/lib.rs b/tracing-futures/src/lib.rs index 05e0600e15..8ba527d771 100644 --- a/tracing-futures/src/lib.rs +++ b/tracing-futures/src/lib.rs @@ -188,38 +188,14 @@ pub mod support; #[cfg(test)] mod tests { - extern crate tokio; - use super::{test_support::*, *}; - #[cfg(feature = "futures-01")] - use futures::{future, stream, task, Async, Future}; - use tracing::{subscriber::with_default, Level}; - struct PollN { and_return: Option>, finish_at: usize, polls: usize, } - #[cfg(feature = "futures-01")] - impl futures::Future for PollN { - type Item = T; - type Error = E; - fn poll(&mut self) -> futures::Poll { - self.polls += 1; - if self.polls == self.finish_at { - self.and_return - .take() - .expect("polled after ready") - .map(Async::Ready) - } else { - task::current().notify(); - Ok(Async::NotReady) - } - } - } - impl PollN<(), ()> { fn new_ok(finish_at: usize) -> Self { Self { @@ -239,98 +215,122 @@ mod tests { } #[cfg(feature = "futures-01")] - #[test] - fn future_enter_exit_is_reasonable() { - let (subscriber, handle) = subscriber::mock() - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - with_default(subscriber, || { - PollN::new_ok(2) - .instrument(span!(Level::TRACE, "foo")) - .wait() - .unwrap(); - }); - handle.assert_finished(); - } + mod futures_tests { + extern crate tokio; + + use futures::{future, stream, task, Async, Future}; + use tracing::{subscriber::with_default, Level}; + + use super::*; + + impl futures::Future for PollN { + type Item = T; + type Error = E; + fn poll(&mut self) -> futures::Poll { + self.polls += 1; + if self.polls == self.finish_at { + self.and_return + .take() + .expect("polled after ready") + .map(Async::Ready) + } else { + task::current().notify(); + Ok(Async::NotReady) + } + } + } - #[cfg(feature = "futures-01")] - #[test] - fn future_error_ends_span() { - let (subscriber, handle) = subscriber::mock() - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .done() - .run_with_handle(); - with_default(subscriber, || { - PollN::new_err(2) - .instrument(span!(Level::TRACE, "foo")) - .wait() - .unwrap_err(); - }); - - handle.assert_finished(); - } + #[test] + fn future_enter_exit_is_reasonable() { + let (subscriber, handle) = subscriber::mock() + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .drop_span(span::mock().named("foo")) + .done() + .run_with_handle(); + with_default(subscriber, || { + PollN::new_ok(2) + .instrument(span!(Level::TRACE, "foo")) + .wait() + .unwrap(); + }); + handle.assert_finished(); + } - #[cfg(feature = "futures-01")] - #[test] - fn stream_enter_exit_is_reasonable() { - let (subscriber, handle) = subscriber::mock() - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .enter(span::mock().named("foo")) - .exit(span::mock().named("foo")) - .drop_span(span::mock().named("foo")) - .run_with_handle(); - with_default(subscriber, || { - stream::iter_ok::<_, ()>(&[1, 2, 3]) - .instrument(span!(Level::TRACE, "foo")) - .for_each(|_| future::ok(())) - .wait() - .unwrap(); - }); - handle.assert_finished(); - } + #[cfg(feature = "futures-01")] + #[test] + fn future_error_ends_span() { + let (subscriber, handle) = subscriber::mock() + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .drop_span(span::mock().named("foo")) + .done() + .run_with_handle(); + with_default(subscriber, || { + PollN::new_err(2) + .instrument(span!(Level::TRACE, "foo")) + .wait() + .unwrap_err(); + }); + + handle.assert_finished(); + } - #[cfg(feature = "futures-01")] - #[test] - fn span_follows_future_onto_threadpool() { - let (subscriber, handle) = subscriber::mock() - .enter(span::mock().named("a")) - .enter(span::mock().named("b")) - .exit(span::mock().named("b")) - .enter(span::mock().named("b")) - .exit(span::mock().named("b")) - .drop_span(span::mock().named("b")) - .exit(span::mock().named("a")) - .drop_span(span::mock().named("a")) - .done() - .run_with_handle(); - let mut runtime = tokio::runtime::Runtime::new().unwrap(); - with_default(subscriber, || { - span!(Level::TRACE, "a").in_scope(|| { - let future = PollN::new_ok(2) - .instrument(span!(Level::TRACE, "b")) - .map(|_| { - span!(Level::TRACE, "c").in_scope(|| { - // "c" happens _outside_ of the instrumented future's - // span, so we don't expect it. - }) - }); - runtime.block_on(Box::new(future)).unwrap(); - }) - }); - handle.assert_finished(); + #[test] + fn stream_enter_exit_is_reasonable() { + let (subscriber, handle) = subscriber::mock() + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .enter(span::mock().named("foo")) + .exit(span::mock().named("foo")) + .drop_span(span::mock().named("foo")) + .run_with_handle(); + with_default(subscriber, || { + stream::iter_ok::<_, ()>(&[1, 2, 3]) + .instrument(span!(Level::TRACE, "foo")) + .for_each(|_| future::ok(())) + .wait() + .unwrap(); + }); + handle.assert_finished(); + } + + #[test] + fn span_follows_future_onto_threadpool() { + let (subscriber, handle) = subscriber::mock() + .enter(span::mock().named("a")) + .enter(span::mock().named("b")) + .exit(span::mock().named("b")) + .enter(span::mock().named("b")) + .exit(span::mock().named("b")) + .drop_span(span::mock().named("b")) + .exit(span::mock().named("a")) + .drop_span(span::mock().named("a")) + .done() + .run_with_handle(); + let mut runtime = tokio::runtime::Runtime::new().unwrap(); + with_default(subscriber, || { + span!(Level::TRACE, "a").in_scope(|| { + let future = PollN::new_ok(2) + .instrument(span!(Level::TRACE, "b")) + .map(|_| { + span!(Level::TRACE, "c").in_scope(|| { + // "c" happens _outside_ of the instrumented future's + // span, so we don't expect it. + }) + }); + runtime.block_on(Box::new(future)).unwrap(); + }) + }); + handle.assert_finished(); + } } } From 3e9f57717334647c402457e859f19efce3259e60 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Sun, 14 Jul 2019 23:36:37 +0000 Subject: [PATCH 11/12] futures: fix travis build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c07103531d..8664450198 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,6 @@ jobs: - script: cargo test --features=doctest-readme --all name: "doctest readme" rust: nightly - - script: (cd tracing-futures/test_std_futures && cargo test) + - script: (cd tracing-futures/test_std_future && cargo test) name: "futures nightly" rust: nightly From 385cbca83ba4c0c476bb2e29692b04f9c8cd3cf8 Mon Sep 17 00:00:00 2001 From: Matt Bilker Date: Mon, 15 Jul 2019 21:03:30 +0000 Subject: [PATCH 12/12] future: remove extraneous part of function names - test_std_future is part of the namespace so having std_future as part of the test function name is not needed --- tracing-futures/test_std_future/tests/test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tracing-futures/test_std_future/tests/test.rs b/tracing-futures/test_std_future/tests/test.rs index 650f67d8cd..e02c16fd32 100644 --- a/tracing-futures/test_std_future/tests/test.rs +++ b/tracing-futures/test_std_future/tests/test.rs @@ -75,7 +75,7 @@ where } #[test] -fn std_future_enter_exit_is_reasonable() { +fn enter_exit_is_reasonable() { let (subscriber, handle) = subscriber::mock() .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) @@ -93,7 +93,7 @@ fn std_future_enter_exit_is_reasonable() { } #[test] -fn std_future_error_ends_span() { +fn error_ends_span() { let (subscriber, handle) = subscriber::mock() .enter(span::mock().named("foo")) .exit(span::mock().named("foo"))