Skip to content

Commit 88c8db4

Browse files
authored
Listen only to stdout for test-proxy errors (#2897)
Resolves #2715. On Windows, listening on stderr was keeping the test-proxy process alive and it wasn't shutting down after all tests completed. There may be a better solution using PTY, but stock support in std or okio for PTY isn't adequate in Windows and this narrow use case doesn't currently warrant the amount of effort I put into heaths/akv-cli-rs to fix a similar problem.
1 parent 372686a commit 88c8db4

File tree

3 files changed

+24
-23
lines changed

3 files changed

+24
-23
lines changed

CONTRIBUTING.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,12 @@ Similarly, if running on the command line pass `PROXY_MANUAL_START=true`.
207207
To log tracing information to the terminal, you can add the `RUST_LOG` environment variable as shown above using the [same format supported by `env_logger`](https://docs.rs/env_logger/latest/env_logger/#enabling-logging).
208208
The targets are the crate names if you want to trace more or less for specific targets e.g., `RUST_LOG=info,azure_core=trace` to trace information messages by default but detailed traces for the `azure_core` crate.
209209

210+
To log traces from the [Test Proxy] itself, pass `test-proxy=trace` to `RUST_LOG` e.g.,
211+
212+
```sh
213+
RUST_LOG=info,azure_core=debug,test-proxy=trace cargo test -p azure_security_keyvault_secrets --test secret_client
214+
```
215+
210216
#### Debugging in Windows
211217

212218
Using the recommended [CodeLLDB] Visual Studio Code extension on Windows will stop at breakpoints but may not pretty print variables e.g.,

sdk/core/azure_core_test/src/proxy/bootstrap.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ pub async fn start(
7272
.to_str()
7373
.ok_or_else(|| ErrorKind::Other.into_error())?
7474
.into(),
75+
// Write exceptions to stdout; otherwise,
76+
// reading from stderr on a separate thread hangs the process on Windows.
77+
"--universal".into(),
7578
]);
7679
options.unwrap_or_default().copy_to(&mut args);
7780
tracing::debug!(

sdk/core/azure_core_test/src/proxy/mod.rs

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use serde::Serializer;
2929
use std::process::ExitStatus;
3030
use std::{fmt, str::FromStr, sync::Arc};
3131
#[cfg(not(target_arch = "wasm32"))]
32-
use tokio::process::Child;
32+
use tokio::{io::Lines, process::Child};
3333

3434
const ABSTRACTION_IDENTIFIER: HeaderName = HeaderName::from_static("x-abstraction-identifier");
3535
const RECORDING_ID: HeaderName = HeaderName::from_static("x-recording-id");
@@ -76,36 +76,26 @@ impl Proxy {
7676
)
7777
})?;
7878

79-
let mut stdout = command
80-
.stdout
81-
.take()
82-
.ok_or_else(|| azure_core::Error::message(ErrorKind::Io, "no stdout pipe"))?;
83-
// Take stderr now but we won't listen until after start up, such that messages should buffer.
84-
let mut stderr = command
85-
.stderr
86-
.take()
87-
.ok_or_else(|| azure_core::Error::message(ErrorKind::Io, "no stderr pipe"))?;
79+
let mut stdout = BufReader::new(
80+
command
81+
.stdout
82+
.take()
83+
.ok_or_else(|| azure_core::Error::message(ErrorKind::Io, "no stdout pipe"))?,
84+
)
85+
.lines();
8886
self.command = Some(command);
8987

9088
// Wait until the service is listening on a port.
9189
self.wait_till_listening(&mut stdout).await?;
9290

93-
// Then spawn a thread to keep pumping messages to stdout and stderr.
91+
// Then spawn a thread to keep pumping messages to stdout.
9492
// The pipe will be closed when the process is shut down, which will terminate the task.
9593
tokio::spawn(async move {
96-
let mut reader = BufReader::new(&mut stdout).lines();
97-
while let Some(line) = reader.next_line().await.unwrap_or(None) {
94+
while let Some(line) = stdout.next_line().await.unwrap_or(None) {
9895
// Trace useful lines that test-proxy writes to stdout.
9996
trace_line(Level::TRACE, &line);
10097
}
10198
});
102-
tokio::spawn(async move {
103-
let mut reader = BufReader::new(&mut stderr).lines();
104-
while let Some(line) = reader.next_line().await.unwrap_or(None) {
105-
// Trace useful lines that test-proxy writes to stdout.
106-
trace_line(Level::ERROR, &line);
107-
}
108-
});
10999

110100
if let Some(endpoint) = &self.endpoint {
111101
self.client = Some(Client::new(endpoint.clone())?);
@@ -153,10 +143,12 @@ impl Proxy {
153143
Ok(ExitStatus::default())
154144
}
155145

156-
async fn wait_till_listening(&mut self, stdout: &mut ChildStdout) -> Result<()> {
146+
async fn wait_till_listening(
147+
&mut self,
148+
stdout: &mut Lines<BufReader<ChildStdout>>,
149+
) -> Result<()> {
157150
let pid = self.command.as_ref().and_then(Child::id);
158-
let mut reader = BufReader::new(stdout).lines();
159-
while let Some(line) = reader.next_line().await? {
151+
while let Some(line) = stdout.next_line().await? {
160152
const RUNNING_PATTERN: &str = "Running proxy version is Azure.Sdk.Tools.TestProxy ";
161153
const LISTENING_PATTERN: &str = "Now listening on: ";
162154

0 commit comments

Comments
 (0)