Skip to content

Commit

Permalink
Merge pull request #645 from TimNN/telemetry-huge
Browse files Browse the repository at this point in the history
Support Telemetry with lots of output
  • Loading branch information
brson authored Aug 10, 2016
2 parents 5a9553a + 9e1f219 commit 388d1d5
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 18 deletions.
22 changes: 22 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ term = "0.4.4"
itertools = "0.4.1"
time = "0.1.34"
tempdir = "0.3.4"
tempfile = "2.1.4"
libc = "0.2.0"
rand = "0.3.11"
scopeguard = "0.1.2"
Expand Down
1 change: 1 addition & 0 deletions src/rustup-mock/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ tar = "0.4.0"
toml = "0.1.27"
rustup-utils = { path = "../rustup-utils", version = "0.5.0" }
sha2 = "0.1.2"
wait-timeout = "0.1.3"

[target."cfg(windows)".dependencies]
winapi = "0.2.8"
Expand Down
38 changes: 25 additions & 13 deletions src/rustup-mock/src/clitools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@
use std::path::{PathBuf, Path};
use std::env;
use std::process::Command;
use std::process::{Command, Stdio};
use std::env::consts::EXE_SUFFIX;
use std::fs::{self, File};
use std::io::{self, Read, Write};
use std::sync::Mutex;
use std::time::Duration;
use tempdir::TempDir;
use {MockInstallerBuilder, MockCommand};
use dist::{MockDistServer, MockChannel, MockPackage,
MockTargettedPackage, MockComponent, change_channel_date,
ManifestVersion};
use url::Url;
use scopeguard;
use wait_timeout::ChildExt;

/// The configuration used by the tests in this module
pub struct Config {
Expand Down Expand Up @@ -218,6 +220,24 @@ pub fn expect_err_ex(config: &Config, args: &[&str],
assert!(out.stderr == stderr, format!("err {:?}", args));
}

pub fn expect_timeout_ok(config: &Config, timeout: Duration, args: &[&str]) {
let mut child = cmd(config, args[0], &args[1..])
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn().unwrap();

match child.wait_timeout(timeout).unwrap() {
Some(status) => {
assert!(status.success(), "not ok {:?}", args);
}
None => {
// child hasn't exited yet
child.kill().unwrap();
panic!("command timed out: {:?}", args);
}
}
}

#[derive(Debug)]
pub struct SanitizedOutput {
pub ok: bool,
Expand Down Expand Up @@ -545,18 +565,10 @@ fn mock_bin(_name: &str, version: &str, version_hash: &str) -> Vec<u8> {
let ref dest_path = tempdir.path().join(&format!("out{}", EXE_SUFFIX));

// Write the source
let ref source = format!(r#"
fn main() {{
let args: Vec<_> = ::std::env::args().collect();
if args.get(1) == Some(&"--version".to_string()) {{
println!("{} ({})");
}} else if args.get(1) == Some(&"--empty-arg-test".to_string()) {{
assert!(args.get(2) == Some(&"".to_string()));
}} else {{
panic!("bad mock proxy commandline");
}}
}}
"#, EXAMPLE_VERSION, EXAMPLE_VERSION_HASH);
let source = include_str!("mock_bin_src.rs")
.replace("%EXAMPLE_VERSION%", EXAMPLE_VERSION)
.replace("%EXAMPLE_VERSION_HASH%", EXAMPLE_VERSION_HASH);

File::create(source_path).and_then(|mut f| f.write_all(source.as_bytes())).unwrap();

// Create the executable
Expand Down
1 change: 1 addition & 0 deletions src/rustup-mock/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extern crate tar;
extern crate toml;
extern crate rustup_utils;
extern crate sha2;
extern crate wait_timeout;

#[cfg(windows)]
extern crate winapi;
Expand Down
19 changes: 19 additions & 0 deletions src/rustup-mock/src/mock_bin_src.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use std::io::{self, BufWriter, Write};

fn main() {
let args: Vec<_> = ::std::env::args().collect();
if args.get(1) == Some(&"--version".to_string()) {
println!("%EXAMPLE_VERSION% (%EXAMPLE_VERSION_HASH%)");
} else if args.get(1) == Some(&"--empty-arg-test".to_string()) {
assert!(args.get(2) == Some(&"".to_string()));
} else if args.get(1) == Some(&"--huge-output".to_string()) {
let out = io::stderr();
let lock = out.lock();
let mut buf = BufWriter::new(lock);
for _ in 0 .. 10000 {
buf.write_all(b"error: a value named `fail` has already been defined in this module [E0428]\n").unwrap();
}
} else {
panic!("bad mock proxy commandline");
}
}
26 changes: 23 additions & 3 deletions src/rustup/command.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use std::env;
use std::ffi::OsStr;
use std::io::{self, Write, BufRead, BufReader};
use std::fs::File;
use std::io::{self, Write, BufRead, BufReader, Seek, SeekFrom};
use std::path::PathBuf;
use std::process::{self, Command, Stdio};
use std::time::Instant;
use regex::Regex;
use tempfile::tempfile;

use Cfg;
use errors::*;
Expand All @@ -29,6 +31,18 @@ pub fn run_command_for_dir<S: AsRef<OsStr>>(cmd: Command,
}

fn telemetry_rustc<S: AsRef<OsStr>>(mut cmd: Command, args: &[S], cfg: &Cfg) -> Result<()> {
#[cfg(unix)]
fn file_as_stdio(file: &File) -> Stdio {
use std::os::unix::io::{AsRawFd, FromRawFd};
unsafe { Stdio::from_raw_fd(file.as_raw_fd()) }
}

#[cfg(windows)]
fn file_as_stdio(file: &File) -> Stdio {
use std::os::windows::io::{AsRawHandle, FromRawHandle};
unsafe { Stdio::from_raw_handle(file.as_raw_handle()) }
}

let now = Instant::now();

cmd.args(&args[1..]);
Expand All @@ -44,15 +58,17 @@ fn telemetry_rustc<S: AsRef<OsStr>>(mut cmd: Command, args: &[S], cfg: &Cfg) ->
cmd.arg("always");
}

let mut cmd_err_file = tempfile().unwrap();
let cmd_err_stdio = file_as_stdio(&cmd_err_file);

// FIXME rust-lang/rust#32254. It's not clear to me
// when and why this is needed.
let mut cmd = cmd.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::piped())
.stderr(cmd_err_stdio)
.spawn()
.unwrap();

let mut buffered_stderr = BufReader::new(cmd.stderr.take().unwrap());
let status = cmd.wait();

let duration = now.elapsed();
Expand All @@ -75,6 +91,10 @@ fn telemetry_rustc<S: AsRef<OsStr>>(mut cmd: Command, args: &[S], cfg: &Cfg) ->
let stderr = io::stderr();
let mut handle = stderr.lock();

cmd_err_file.seek(SeekFrom::Start(0)).unwrap();

let mut buffered_stderr = BufReader::new(cmd_err_file);

while buffered_stderr.read_line(&mut buffer).unwrap() > 0 {
let b = buffer.to_owned();
buffer.clear();
Expand Down
1 change: 1 addition & 0 deletions src/rustup/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extern crate url;
extern crate regex;
extern crate itertools;
extern crate rustc_serialize;
extern crate tempfile;
extern crate time;
extern crate toml;
#[cfg(unix)]
Expand Down
15 changes: 13 additions & 2 deletions tests/cli-misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ extern crate rustup_mock;
extern crate time;
use rustup_mock::clitools::{self, Config, Scenario,
expect_stdout_ok, expect_stderr_ok,
expect_ok, expect_err, run,
this_host_triple};
expect_ok, expect_err, expect_timeout_ok,
run, this_host_triple};
use rustup_utils::{raw, utils};

use time::Duration;
use std::ops::Sub;
use std::ops::Add;
use std::time::Duration as StdDuration;

macro_rules! for_host { ($s: expr) => (&format!($s, this_host_triple())) }

Expand Down Expand Up @@ -334,6 +335,16 @@ fn enabling_telemetry_and_compiling_creates_log() {
});
}

#[test]
fn telemetry_supports_huge_output() {
setup(&|config| {
expect_ok(config, &["rustup", "default", "stable"]);
expect_ok(config, &["rustup", "telemetry", "enable"]);
expect_timeout_ok(&config, StdDuration::from_secs(5), &["rustc", "--huge-output"]);
expect_stdout_ok(config, &["rustup", "telemetry", "analyze"], "'E0428': 10000")
})
}

#[test]
fn telemetry_cleanup_removes_old_files() {
setup(&|config| {
Expand Down

0 comments on commit 388d1d5

Please sign in to comment.