<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(rustc_attrs)]

// no-pretty-expanded FIXME #15189
// ignore-android FIXME #17520
// compile-flags:-g

use std::env;
use std::process::{Command, Stdio};
use std::str;

// FIXME #31005 MIR missing debuginfo currently.
#[cfg_attr(target_env = "msvc", rustc_no_mir)]
#[inline(never)]
fn foo() {
    let _v = vec![1, 2, 3];
    if env::var_os("IS_TEST").is_some() {
        panic!()
    }
}

// FIXME #31005 MIR missing debuginfo currently.
#[cfg_attr(target_env = "msvc", rustc_no_mir)]
#[inline(never)]
fn double() {
    struct Double;

    impl Drop for Double {
        fn drop(&mut self) { panic!("twice") }
    }

    let _d = Double;

    panic!("once");
}

fn template(me: &str) -> Command {
    let mut m = Command::new(me);
    m.env("IS_TEST", "1")
     .stdout(Stdio::piped())
     .stderr(Stdio::piped());
    return m;
}

fn runtest(me: &str) {
    // Make sure that the stack trace is printed
    let p = template(me).arg("fail").env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    assert!(s.contains("stack backtrace") && s.contains(" - backtrace::foo"),
            "bad output: {}", s);

    // Make sure the stack trace is *not* printed
    // (Remove RUST_BACKTRACE from our own environment, in case developer
    // is running `make check` with it on.)
    let p = template(me).arg("fail").env_remove("RUST_BACKTRACE").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    assert!(!s.contains("stack backtrace") && !s.contains(" - backtrace::foo"),
            "bad output2: {}", s);

    // Make sure a stack trace is printed
    let p = template(me).arg("double-fail").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    // loosened the following from double::h to double:: due to
    // spurious failures on mac, 32bit, optimized
    assert!(s.contains("stack backtrace") && s.contains(" - backtrace::double"),
            "bad output3: {}", s);

    // Make sure a stack trace isn't printed too many times
    let p = template(me).arg("double-fail")
                                .env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    let mut i = 0;
    for _ in 0..2 {
        i += s[i + 10..].find("stack backtrace").unwrap() + 10;
    }
    assert!(s[i + 10..].find("stack backtrace").is_none(),
            "bad output4: {}", s);
}

fn main() {
    if cfg!(windows) && cfg!(target_arch = "x86") && cfg!(target_env = "gnu") {
        return
    }

    let args: Vec<String> = env::args().collect();
    if args.len() >= 2 && args[1] == "fail" {
        foo();
    } else if args.len() >= 2 && args[1] == "double-fail" {
        double();
    } else {
        runtest(&args[0]);
    }
}
<commit_msg>Update backtrace test for FIXME on windows<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(rustc_attrs)]

// no-pretty-expanded FIXME #15189
// ignore-android FIXME #17520
// compile-flags:-g

use std::env;
use std::process::{Command, Stdio};
use std::str;

// FIXME #31005 MIR missing debuginfo currently.
#[cfg_attr(target_env = "msvc", rustc_no_mir)]
#[inline(never)]
fn foo() {
    let _v = vec![1, 2, 3];
    if env::var_os("IS_TEST").is_some() {
        panic!()
    }
}

// FIXME #31005 MIR missing debuginfo currently.
#[cfg_attr(target_env = "msvc", rustc_no_mir)]
#[inline(never)]
fn double() {
    struct Double;

    impl Drop for Double {
        fn drop(&mut self) { panic!("twice") }
    }

    let _d = Double;

    panic!("once");
}

fn template(me: &str) -> Command {
    let mut m = Command::new(me);
    m.env("IS_TEST", "1")
     .stdout(Stdio::piped())
     .stderr(Stdio::piped());
    return m;
}

fn expected(fn_name: &str) -> String {
    // FIXME(#32481)
    //
    // On windows, we read the function name from debuginfo using some
    // system APIs. For whatever reason, these APIs seem to use the
    // "name" field, which is only the "relative" name, not the full
    // name with namespace info, so we just see `foo` and not
    // `backtrace::foo` as we see on linux (which uses the linkage
    // name).

    if cfg!(windows) {
        format!(" - {}", fn_name)
    } else {
        format!(" - backtrace::{}", fn_name)
    }
}

fn runtest(me: &str) {
    // Make sure that the stack trace is printed
    let p = template(me).arg("fail").env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    assert!(s.contains("stack backtrace") && s.contains(&expected("foo")),
            "bad output: {}", s);

    // Make sure the stack trace is *not* printed
    // (Remove RUST_BACKTRACE from our own environment, in case developer
    // is running `make check` with it on.)
    let p = template(me).arg("fail").env_remove("RUST_BACKTRACE").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    assert!(!s.contains("stack backtrace") && !s.contains(&expected("foo")),
            "bad output2: {}", s);

    // Make sure a stack trace is printed
    let p = template(me).arg("double-fail").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    // loosened the following from double::h to double:: due to
    // spurious failures on mac, 32bit, optimized
    assert!(s.contains("stack backtrace") && s.contains(&expected("double")),
            "bad output3: {}", s);

    // Make sure a stack trace isn't printed too many times
    let p = template(me).arg("double-fail")
                                .env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    let mut i = 0;
    for _ in 0..2 {
        i += s[i + 10..].find("stack backtrace").unwrap() + 10;
    }
    assert!(s[i + 10..].find("stack backtrace").is_none(),
            "bad output4: {}", s);
}

fn main() {
    if cfg!(windows) && cfg!(target_arch = "x86") && cfg!(target_env = "gnu") {
        return
    }

    let args: Vec<String> = env::args().collect();
    if args.len() >= 2 && args[1] == "fail" {
        foo();
    } else if args.len() >= 2 && args[1] == "double-fail" {
        double();
    } else {
        runtest(&args[0]);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Jason White
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::io::{self, Write};
use std::sync::Arc;
use std::time::Instant;

use crate::detect::Detected;
use crate::res;
use crate::task;

use crate::error::{BuildError, Error};

use super::traits::{EventLogger, LogResult, TaskLogger};

use termcolor::{self as tc, WriteColor};

pub struct ConsoleTask {
    verbose: bool,
    bufwriter: Arc<tc::BufferWriter>,
    thread: usize,
    task_name: String,
    body: Vec<u8>,
    start_time: Instant,
}

impl ConsoleTask {
    pub fn new(
        verbose: bool,
        thread: usize,
        task: &task::Any,
        bufwriter: Arc<tc::BufferWriter>,
    ) -> Result<ConsoleTask, Error> {
        Ok(ConsoleTask {
            verbose,
            bufwriter,
            thread,
            task_name: task.to_string(),
            body: Vec::new(),
            start_time: Instant::now(),
        })
    }
}

impl io::Write for ConsoleTask {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.body.write(buf)
    }

    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.body.write_all(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl TaskLogger for ConsoleTask {
    fn finish(self, result: &Result<Detected, Error>) -> LogResult<()> {
        let ConsoleTask {
            verbose,
            bufwriter,
            thread,
            task_name,
            body,
            start_time,
        } = self;

        let mut buf = bufwriter.buffer();

        let mut color = tc::ColorSpec::new();
        let color = if result.is_ok() {
            color.set_fg(Some(tc::Color::Green)).set_bold(true)
        } else {
            // Make errors highly-visible.
            color
                .set_fg(Some(tc::Color::White))
                .set_bold(true)
                .set_bg(Some(tc::Color::Red))
                .set_intense(true)
        };

        buf.set_color(color)?;
        write!(buf, "[{}] {}", thread, task_name)?;
        buf.reset()?;
        buf.write_all(b"\n")?;
        buf.write_all(&body)?;

        let duration = start_time.elapsed();

        // TODO: Convert \r\n to \n on Windows.
        // TODO: Convert ASCII color codes to real colors on Windows.

        // Add a new line to the end if there isn't one.
        if !buf.as_slice().ends_with(b"\n") {
            buf.write_all(b"\n")?;
        }

        if verbose {
            buf.set_color(tc::ColorSpec::new().set_fg(Some(tc::Color::Blue)))?;
            write!(&mut buf, "Task duration")?;
            buf.reset()?;
            writeln!(&mut buf, ": {:.4?}", duration)?;
        }

        if let Err(err) = result {
            let mut red_fg = tc::ColorSpec::new();
            red_fg.set_fg(Some(tc::Color::Red));

            // Print out the chain of errors.
            let mut errors = err.iter_chain();

            if let Some(err) = errors.next() {
                buf.set_color(&red_fg)?;
                write!(&mut buf, "    Error")?;
                buf.reset()?;
                writeln!(&mut buf, ": {}", err)?;
            }

            for err in errors {
                buf.set_color(&red_fg)?;
                write!(&mut buf, "Caused by")?;
                buf.reset()?;
                writeln!(&mut buf, ": {}", err)?;
            }
        }

        bufwriter.print(&buf)?;

        Ok(())
    }
}

/// Log text to the console.
///
/// This buffers task output and prints out the task once it has finished.
pub struct Console {
    verbose: bool,
    start_time: Instant,
    bufwriter: Arc<tc::BufferWriter>,
}

impl Console {
    pub fn new(verbose: bool, color: tc::ColorChoice) -> Console {
        Console {
            verbose,
            bufwriter: Arc::new(tc::BufferWriter::stdout(color)),
            start_time: Instant::now(),
        }
    }
}

impl EventLogger for Console {
    type TaskLogger = ConsoleTask;

    fn begin_build(&mut self, _threads: usize) -> LogResult<()> {
        self.start_time = Instant::now();

        Ok(())
    }

    fn end_build(&mut self, _result: &Result<(), BuildError>) -> LogResult<()> {
        println!("---");
        println!("Build complete. Took {:.4?}", self.start_time.elapsed());

        Ok(())
    }

    fn start_task(
        &self,
        thread: usize,
        task: &task::Any,
    ) -> LogResult<ConsoleTask> {
        ConsoleTask::new(self.verbose, thread, task, self.bufwriter.clone())
    }

    fn delete(
        &self,
        thread: usize,
        resource: &res::Any,
        result: &Result<(), Error>,
    ) -> LogResult<()> {
        if let Err(err) = result {
            println!("[{}] Failed to delete: {} ({})", thread, resource, err);
        } else {
            println!("[{}] Deleted: {}", thread, resource);
        }

        Ok(())
    }

    fn checksum_error(
        &self,
        thread: usize,
        resource: &res::Any,
        error: &Error,
    ) -> LogResult<()> {
        println!(
            "[{}] Failed computing checksum for: {} ({})",
            thread, resource, error
        );
        Ok(())
    }
}
<commit_msg>Fix display of file names that contain a \r<commit_after>// Copyright (c) 2018 Jason White
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::io::{self, Write};
use std::sync::Arc;
use std::time::Instant;

use crate::detect::Detected;
use crate::res;
use crate::task;

use crate::error::{BuildError, Error};

use super::traits::{EventLogger, LogResult, TaskLogger};

use termcolor::{self as tc, WriteColor};

pub struct ConsoleTask {
    verbose: bool,
    bufwriter: Arc<tc::BufferWriter>,
    thread: usize,
    task_name: String,
    body: Vec<u8>,
    start_time: Instant,
}

impl ConsoleTask {
    pub fn new(
        verbose: bool,
        thread: usize,
        task: &task::Any,
        bufwriter: Arc<tc::BufferWriter>,
    ) -> Result<ConsoleTask, Error> {
        Ok(ConsoleTask {
            verbose,
            bufwriter,
            thread,
            task_name: task.to_string(),
            body: Vec::new(),
            start_time: Instant::now(),
        })
    }
}

impl io::Write for ConsoleTask {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.body.write(buf)
    }

    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.body.write_all(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl TaskLogger for ConsoleTask {
    fn finish(self, result: &Result<Detected, Error>) -> LogResult<()> {
        let ConsoleTask {
            verbose,
            bufwriter,
            thread,
            task_name,
            body,
            start_time,
        } = self;

        let mut buf = bufwriter.buffer();

        let mut color = tc::ColorSpec::new();
        let color = if result.is_ok() {
            color.set_fg(Some(tc::Color::Green)).set_bold(true)
        } else {
            // Make errors highly-visible.
            color
                .set_fg(Some(tc::Color::White))
                .set_bold(true)
                .set_bg(Some(tc::Color::Red))
                .set_intense(true)
        };

        buf.set_color(color)?;
        write!(buf, "[{}] {}", thread, task_name)?;
        buf.reset()?;
        buf.write_all(b"\n")?;
        buf.write_all(&body)?;

        let duration = start_time.elapsed();

        // TODO: Convert \r\n to \n on Windows.
        // TODO: Convert ASCII color codes to real colors on Windows.

        // Add a new line to the end if there isn't one.
        if !buf.as_slice().ends_with(b"\n") {
            buf.write_all(b"\n")?;
        }

        if verbose {
            buf.set_color(tc::ColorSpec::new().set_fg(Some(tc::Color::Blue)))?;
            write!(&mut buf, "Task duration")?;
            buf.reset()?;
            writeln!(&mut buf, ": {:.4?}", duration)?;
        }

        if let Err(err) = result {
            let mut red_fg = tc::ColorSpec::new();
            red_fg.set_fg(Some(tc::Color::Red));

            // Print out the chain of errors.
            let mut errors = err.iter_chain();

            if let Some(err) = errors.next() {
                buf.set_color(&red_fg)?;
                write!(&mut buf, "    Error")?;
                buf.reset()?;
                writeln!(&mut buf, ": {}", err)?;
            }

            for err in errors {
                buf.set_color(&red_fg)?;
                write!(&mut buf, "Caused by")?;
                buf.reset()?;
                writeln!(&mut buf, ": {}", err)?;
            }
        }

        bufwriter.print(&buf)?;

        Ok(())
    }
}

/// Log text to the console.
///
/// This buffers task output and prints out the task once it has finished.
pub struct Console {
    verbose: bool,
    start_time: Instant,
    bufwriter: Arc<tc::BufferWriter>,
}

impl Console {
    pub fn new(verbose: bool, color: tc::ColorChoice) -> Console {
        Console {
            verbose,
            bufwriter: Arc::new(tc::BufferWriter::stdout(color)),
            start_time: Instant::now(),
        }
    }
}

impl EventLogger for Console {
    type TaskLogger = ConsoleTask;

    fn begin_build(&mut self, _threads: usize) -> LogResult<()> {
        self.start_time = Instant::now();

        Ok(())
    }

    fn end_build(&mut self, _result: &Result<(), BuildError>) -> LogResult<()> {
        println!("---");
        println!("Build complete. Took {:.4?}", self.start_time.elapsed());

        Ok(())
    }

    fn start_task(
        &self,
        thread: usize,
        task: &task::Any,
    ) -> LogResult<ConsoleTask> {
        ConsoleTask::new(self.verbose, thread, task, self.bufwriter.clone())
    }

    fn delete(
        &self,
        thread: usize,
        resource: &res::Any,
        result: &Result<(), Error>,
    ) -> LogResult<()> {
        if let Err(err) = result {
            println!("[{}] Failed to delete: {} ({})", thread, resource, err);
        } else {
            println!("[{}] Deleted: {}", thread, resource);
        }

        Ok(())
    }

    fn checksum_error(
        &self,
        thread: usize,
        resource: &res::Any,
        error: &Error,
    ) -> LogResult<()> {
        println!(
            "[{}] Failed computing checksum for: {:?} ({})",
            thread, resource, error
        );
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::hash::Hasher;
use std::hash::sip::SipHasher;
use std::io::{File, IoError};
use std::io;
use std::os::args;
use std::str;
use term::color::YELLOW;

use core::{Package, PackageSet, Target};
use util;
use util::{CargoResult, ChainError, ProcessBuilder, internal, human, CargoError};
use util::{Config, TaskPool, DependencyQueue, Fresh, Dirty, Freshness};

type Args = Vec<String>;

struct Context<'a, 'b> {
    dest: &'a Path,
    deps_dir: &'a Path,
    primary: bool,
    rustc_version: &'a str,
    config: &'b mut Config<'b>
}

type Job = proc():Send -> CargoResult<()>;

// This is a temporary assert that ensures the consistency of the arguments
// given the current limitations of Cargo. The long term fix is to have each
// Target know the absolute path to the build location.
fn uniq_target_dest<'a>(targets: &[&'a Target]) -> Option<&'a str> {
    let mut curr: Option<Option<&str>> = None;

    for t in targets.iter() {
        let dest = t.get_profile().get_dest();

        match curr {
            Some(curr) => assert!(curr == dest),
            None => curr = Some(dest)
        }
    }

    curr.unwrap()
}

pub fn compile_targets<'a>(env: &str, targets: &[&Target], pkg: &Package,
                           deps: &PackageSet,
                           config: &'a mut Config<'a>) -> CargoResult<()> {

    if targets.is_empty() {
        return Ok(());
    }

    debug!("compile_targets; targets={}; pkg={}; deps={}", targets, pkg, deps);

    let path_fragment = uniq_target_dest(targets);
    let target_dir = pkg.get_absolute_target_dir().join(path_fragment.unwrap_or(""));
    let deps_target_dir = target_dir.join("deps");

    let output = try!(util::process("rustc").arg("-v").exec_with_output());
    let rustc_version = str::from_utf8(output.output.as_slice()).unwrap();

    // First ensure that the destination directory exists
    debug!("creating target dir; path={}", target_dir.display());

    try!(mk_target(&target_dir).chain_error(||
        internal(format!("Couldn't create the target directory for {} at {}",
                 pkg.get_name(), target_dir.display()))));

    try!(mk_target(&deps_target_dir).chain_error(||
        internal(format!("Couldn't create the directory for dependencies for {} at {}",
                 pkg.get_name(), deps_target_dir.display()))));

    let mut cx = Context {
        dest: &deps_target_dir,
        deps_dir: &deps_target_dir,
        primary: false,
        rustc_version: rustc_version.as_slice(),
        config: config
    };

    // Build up a list of pending jobs, each of which represent compiling a
    // particular package. No actual work is executed as part of this, that's
    // all done later as part of the `execute` function which will run
    // everything in order with proper parallelism.
    let mut jobs = Vec::new();
    for dep in deps.iter() {
        // Only compile lib targets for dependencies
        let targets = dep.get_targets().iter().filter(|target| {
            target.is_lib() && target.get_profile().get_env() == env
        }).collect::<Vec<&Target>>();

        jobs.push((dep, try!(compile(targets.as_slice(), dep, &mut cx))));
    }

    cx.primary = true;
    cx.dest = &target_dir;
    jobs.push((pkg, try!(compile(targets, pkg, &mut cx))));

    // Now that we've figured out everything that we're going to do, do it!
    execute(cx.config, jobs)
}

fn compile(targets: &[&Target], pkg: &Package,
           cx: &mut Context) -> CargoResult<(Freshness, Job)> {
    debug!("compile_pkg; pkg={}; targets={}", pkg, pkg.get_targets());

    if targets.is_empty() {
        return Ok((Fresh, proc() Ok(())))
    }

    // First check to see if this package is fresh.
    //
    // Note that we're compiling things in topological order, so if nothing has
    // been built up to this point and we're fresh, then we can safely skip
    // recompilation. If anything has previously been rebuilt, it may have been
    // a dependency of ours, so just go ahead and rebuild ourselves.
    //
    // This is not quite accurate, we should only trigger forceful
    // recompilations for downstream dependencies of ourselves, not everyone
    // compiled afterwards.a
    //
    // TODO: Figure out how this works with targets
    let fingerprint_loc = cx.dest.join(format!(".{}.fingerprint",
                                               pkg.get_name()));

    let (is_fresh, fingerprint) = try!(is_fresh(pkg, &fingerprint_loc, cx,
                                                targets));

    let mut cmds = Vec::new();

    // TODO: Should this be on the target or the package?
    for build_cmd in pkg.get_manifest().get_build().iter() {
        cmds.push(compile_custom(pkg, build_cmd.as_slice(), cx));
    }

    // After the custom command has run, execute rustc for all targets of our
    // package.
    for &target in targets.iter() {
        cmds.push(rustc(&pkg.get_root(), target, cx));
    }

    cmds.push(proc() {
        // If this job runs, then everything has successfully compiled, so write
        // our new fingerprint to the relevant location to prevent
        // recompilations in the future.
        try!(File::create(&fingerprint_loc).write_str(fingerprint.as_slice()));
        Ok(())
    });

    // TODO: this job itself may internally be parallel, but we're hiding that
    //       currently. How to expose the parallelism among a single target?
    Ok((if is_fresh {Fresh} else {Dirty}, proc() {
        for cmd in cmds.move_iter() {
            try!(cmd());
        }
        Ok(())
    }))
}

fn is_fresh(dep: &Package, loc: &Path,
            cx: &mut Context, targets: &[&Target]) -> CargoResult<(bool, String)>
{
    let new_pkg_fingerprint = format!("{}{}", cx.rustc_version,
                                  try!(dep.get_fingerprint(cx.config)));

    let new_fingerprint = fingerprint(new_pkg_fingerprint, hash_targets(targets));

    let mut file = match File::open(loc) {
        Ok(file) => file,
        Err(..) => return Ok((false, new_fingerprint)),
    };

    let old_fingerprint = try!(file.read_to_str());

    log!(5, "old fingerprint: {}", old_fingerprint);
    log!(5, "new fingerprint: {}", new_fingerprint);

    Ok((old_fingerprint == new_fingerprint, new_fingerprint))
}

fn hash_targets(targets: &[&Target]) -> u64 {
    let hasher = SipHasher::new_with_keys(0,0);
    let targets = targets.iter().map(|t| (*t).clone()).collect::<Vec<Target>>();
    hasher.hash(&targets)
}

fn fingerprint(package: String, profiles: u64) -> String {
    let hasher = SipHasher::new_with_keys(0,0);
    util::to_hex(hasher.hash(&(package, profiles)))
}

fn mk_target(target: &Path) -> Result<(), IoError> {
    io::fs::mkdir_recursive(target, io::UserRWX)
}

fn compile_custom(pkg: &Package, cmd: &str,
                  cx: &Context) -> Job {
    // FIXME: this needs to be smarter about splitting
    let mut cmd = cmd.split(' ');
    let mut p = util::process(cmd.next().unwrap())
                     .cwd(pkg.get_root())
                     .env("OUT_DIR", Some(cx.dest.as_str().expect("non-UTF8 dest path")))
                     .env("DEPS_DIR", Some(cx.dest.join(cx.deps_dir)
                                             .as_str().expect("non-UTF8 deps path")));
    for arg in cmd {
        p = p.arg(arg);
    }
    proc() p.exec_with_output().map(|_| ()).map_err(|e| e.mark_human())
}

fn rustc(root: &Path, target: &Target, cx: &mut Context) -> Job {
    let crate_types = target.rustc_crate_types();

    log!(5, "root={}; target={}; crate_types={}; dest={}; deps={}; verbose={}",
         root.display(), target, crate_types, cx.dest.display(),
         cx.deps_dir.display(), cx.primary);

    let primary = cx.primary;
    let rustc = prepare_rustc(root, target, crate_types, cx);

    log!(5, "command={}", rustc);

    let _ = cx.config.shell().verbose(|shell| shell.status("Running", rustc.to_str()));

    proc() {
        if primary {
            rustc.exec().map_err(|err| human(err.to_str()))
        } else {
            rustc.exec_with_output().and(Ok(())).map_err(|err| {
                human(err.to_str())
            })
        }
    }
}

fn prepare_rustc(root: &Path, target: &Target, crate_types: Vec<&str>,
                 cx: &Context) -> ProcessBuilder {
    let mut args = Vec::new();

    build_base_args(&mut args, target, crate_types, cx);
    build_deps_args(&mut args, cx);

    util::process("rustc")
        .cwd(root.clone())
        .args(args.as_slice())
        .env("RUST_LOG", None) // rustc is way too noisy
}

fn build_base_args(into: &mut Args,
                   target: &Target,
                   crate_types: Vec<&str>,
                   cx: &Context)
{
    let metadata = target.get_metadata();

    // TODO: Handle errors in converting paths into args
    into.push(target.get_src_path().display().to_str());

    into.push("--crate-name".to_str());
    into.push(target.get_name().to_str());

    for crate_type in crate_types.iter() {
        into.push("--crate-type".to_str());
        into.push(crate_type.to_str());
    }

    let out = cx.dest.clone();
    let profile = target.get_profile();

    if profile.get_opt_level() != 0 {
        into.push("--opt-level".to_str());
        into.push(profile.get_opt_level().to_str());
    }

    if profile.get_debug() {
        into.push("-g".to_str());
    }

    if profile.is_test() {
        into.push("--test".to_str());
    }

    match metadata {
        Some(m) => {
            into.push("-C".to_str());
            into.push(format!("metadata={}", m.metadata));

            into.push("-C".to_str());
            into.push(format!("extra-filename=-{}", m.extra_filename));
        }
        None => {}
    }

    if target.is_lib() {
        into.push("--out-dir".to_str());
        into.push(out.display().to_str());
    } else {
        into.push("-o".to_str());
        into.push(out.join(target.get_name()).display().to_str());
    }
}

fn build_deps_args(dst: &mut Args, cx: &Context) {
    dst.push("-L".to_str());
    dst.push(cx.dest.display().to_str());
    dst.push("-L".to_str());
    dst.push(cx.deps_dir.display().to_str());
}

/// Execute all jobs necessary to build the dependency graph.
///
/// This function will spawn off `config.jobs()` workers to build all of the
/// necessary dependencies, in order. Freshness is propagated as far as possible
/// along each dependency chain.
fn execute(config: &mut Config,
           jobs: Vec<(&Package, (Freshness, Job))>) -> CargoResult<()> {
    let pool = TaskPool::new(config.jobs());
    let (tx, rx) = channel();
    let mut queue = DependencyQueue::new();
    for &(pkg, _) in jobs.iter() {
        queue.register(pkg);
    }
    for (pkg, (fresh, job)) in jobs.move_iter() {
        queue.enqueue(pkg, fresh, (pkg, job));
    }

    // Iteratively execute the dependency graph. Each turn of this loop will
    // schedule as much work as possible and then wait for one job to finish,
    // possibly scheduling more work afterwards.
    let mut active = 0i;
    while queue.len() > 0 {
        loop {
            match queue.dequeue() {
                Some((name, Fresh, (pkg, _))) => {
                    try!(config.shell().status("Fresh", pkg));
                    tx.send((name, Fresh, Ok(())));
                }
                Some((name, Dirty, (pkg, job))) => {
                    try!(config.shell().status("Compiling", pkg));
                    let my_tx = tx.clone();
                    pool.execute(proc() my_tx.send((name, Dirty, job())));
                }
                None => break,
            }
        }

        // Now that all possible work has been scheduled, wait for a piece of
        // work to finish. If any package fails to build then we stop scheduling
        // work as quickly as possibly.
        active -= 1;
        match rx.recv() {
            (name, fresh, Ok(())) => queue.finish(&name, fresh),
            (_, _, Err(e)) => {
                if active > 0 && config.jobs() > 1 {
                    try!(config.shell().say("Build failed, waiting for other \
                                             jobs to finish...", YELLOW));
                    for _ in rx.iter() {}
                }
                return Err(e)
            }
        }
    }

    log!(5, "rustc jobs completed");

    Ok(())
}
<commit_msg>Disable passing -g for now<commit_after>use std::hash::Hasher;
use std::hash::sip::SipHasher;
use std::io::{File, IoError};
use std::io;
use std::os::args;
use std::str;
use term::color::YELLOW;

use core::{Package, PackageSet, Target};
use util;
use util::{CargoResult, ChainError, ProcessBuilder, internal, human, CargoError};
use util::{Config, TaskPool, DependencyQueue, Fresh, Dirty, Freshness};

type Args = Vec<String>;

struct Context<'a, 'b> {
    dest: &'a Path,
    deps_dir: &'a Path,
    primary: bool,
    rustc_version: &'a str,
    config: &'b mut Config<'b>
}

type Job = proc():Send -> CargoResult<()>;

// This is a temporary assert that ensures the consistency of the arguments
// given the current limitations of Cargo. The long term fix is to have each
// Target know the absolute path to the build location.
fn uniq_target_dest<'a>(targets: &[&'a Target]) -> Option<&'a str> {
    let mut curr: Option<Option<&str>> = None;

    for t in targets.iter() {
        let dest = t.get_profile().get_dest();

        match curr {
            Some(curr) => assert!(curr == dest),
            None => curr = Some(dest)
        }
    }

    curr.unwrap()
}

pub fn compile_targets<'a>(env: &str, targets: &[&Target], pkg: &Package,
                           deps: &PackageSet,
                           config: &'a mut Config<'a>) -> CargoResult<()> {

    if targets.is_empty() {
        return Ok(());
    }

    debug!("compile_targets; targets={}; pkg={}; deps={}", targets, pkg, deps);

    let path_fragment = uniq_target_dest(targets);
    let target_dir = pkg.get_absolute_target_dir().join(path_fragment.unwrap_or(""));
    let deps_target_dir = target_dir.join("deps");

    let output = try!(util::process("rustc").arg("-v").exec_with_output());
    let rustc_version = str::from_utf8(output.output.as_slice()).unwrap();

    // First ensure that the destination directory exists
    debug!("creating target dir; path={}", target_dir.display());

    try!(mk_target(&target_dir).chain_error(||
        internal(format!("Couldn't create the target directory for {} at {}",
                 pkg.get_name(), target_dir.display()))));

    try!(mk_target(&deps_target_dir).chain_error(||
        internal(format!("Couldn't create the directory for dependencies for {} at {}",
                 pkg.get_name(), deps_target_dir.display()))));

    let mut cx = Context {
        dest: &deps_target_dir,
        deps_dir: &deps_target_dir,
        primary: false,
        rustc_version: rustc_version.as_slice(),
        config: config
    };

    // Build up a list of pending jobs, each of which represent compiling a
    // particular package. No actual work is executed as part of this, that's
    // all done later as part of the `execute` function which will run
    // everything in order with proper parallelism.
    let mut jobs = Vec::new();
    for dep in deps.iter() {
        // Only compile lib targets for dependencies
        let targets = dep.get_targets().iter().filter(|target| {
            target.is_lib() && target.get_profile().get_env() == env
        }).collect::<Vec<&Target>>();

        jobs.push((dep, try!(compile(targets.as_slice(), dep, &mut cx))));
    }

    cx.primary = true;
    cx.dest = &target_dir;
    jobs.push((pkg, try!(compile(targets, pkg, &mut cx))));

    // Now that we've figured out everything that we're going to do, do it!
    execute(cx.config, jobs)
}

fn compile(targets: &[&Target], pkg: &Package,
           cx: &mut Context) -> CargoResult<(Freshness, Job)> {
    debug!("compile_pkg; pkg={}; targets={}", pkg, pkg.get_targets());

    if targets.is_empty() {
        return Ok((Fresh, proc() Ok(())))
    }

    // First check to see if this package is fresh.
    //
    // Note that we're compiling things in topological order, so if nothing has
    // been built up to this point and we're fresh, then we can safely skip
    // recompilation. If anything has previously been rebuilt, it may have been
    // a dependency of ours, so just go ahead and rebuild ourselves.
    //
    // This is not quite accurate, we should only trigger forceful
    // recompilations for downstream dependencies of ourselves, not everyone
    // compiled afterwards.a
    //
    // TODO: Figure out how this works with targets
    let fingerprint_loc = cx.dest.join(format!(".{}.fingerprint",
                                               pkg.get_name()));

    let (is_fresh, fingerprint) = try!(is_fresh(pkg, &fingerprint_loc, cx,
                                                targets));

    let mut cmds = Vec::new();

    // TODO: Should this be on the target or the package?
    for build_cmd in pkg.get_manifest().get_build().iter() {
        cmds.push(compile_custom(pkg, build_cmd.as_slice(), cx));
    }

    // After the custom command has run, execute rustc for all targets of our
    // package.
    for &target in targets.iter() {
        cmds.push(rustc(&pkg.get_root(), target, cx));
    }

    cmds.push(proc() {
        // If this job runs, then everything has successfully compiled, so write
        // our new fingerprint to the relevant location to prevent
        // recompilations in the future.
        try!(File::create(&fingerprint_loc).write_str(fingerprint.as_slice()));
        Ok(())
    });

    // TODO: this job itself may internally be parallel, but we're hiding that
    //       currently. How to expose the parallelism among a single target?
    Ok((if is_fresh {Fresh} else {Dirty}, proc() {
        for cmd in cmds.move_iter() {
            try!(cmd());
        }
        Ok(())
    }))
}

fn is_fresh(dep: &Package, loc: &Path,
            cx: &mut Context, targets: &[&Target]) -> CargoResult<(bool, String)>
{
    let new_pkg_fingerprint = format!("{}{}", cx.rustc_version,
                                  try!(dep.get_fingerprint(cx.config)));

    let new_fingerprint = fingerprint(new_pkg_fingerprint, hash_targets(targets));

    let mut file = match File::open(loc) {
        Ok(file) => file,
        Err(..) => return Ok((false, new_fingerprint)),
    };

    let old_fingerprint = try!(file.read_to_str());

    log!(5, "old fingerprint: {}", old_fingerprint);
    log!(5, "new fingerprint: {}", new_fingerprint);

    Ok((old_fingerprint == new_fingerprint, new_fingerprint))
}

fn hash_targets(targets: &[&Target]) -> u64 {
    let hasher = SipHasher::new_with_keys(0,0);
    let targets = targets.iter().map(|t| (*t).clone()).collect::<Vec<Target>>();
    hasher.hash(&targets)
}

fn fingerprint(package: String, profiles: u64) -> String {
    let hasher = SipHasher::new_with_keys(0,0);
    util::to_hex(hasher.hash(&(package, profiles)))
}

fn mk_target(target: &Path) -> Result<(), IoError> {
    io::fs::mkdir_recursive(target, io::UserRWX)
}

fn compile_custom(pkg: &Package, cmd: &str,
                  cx: &Context) -> Job {
    // FIXME: this needs to be smarter about splitting
    let mut cmd = cmd.split(' ');
    let mut p = util::process(cmd.next().unwrap())
                     .cwd(pkg.get_root())
                     .env("OUT_DIR", Some(cx.dest.as_str().expect("non-UTF8 dest path")))
                     .env("DEPS_DIR", Some(cx.dest.join(cx.deps_dir)
                                             .as_str().expect("non-UTF8 deps path")));
    for arg in cmd {
        p = p.arg(arg);
    }
    proc() p.exec_with_output().map(|_| ()).map_err(|e| e.mark_human())
}

fn rustc(root: &Path, target: &Target, cx: &mut Context) -> Job {
    let crate_types = target.rustc_crate_types();

    log!(5, "root={}; target={}; crate_types={}; dest={}; deps={}; verbose={}",
         root.display(), target, crate_types, cx.dest.display(),
         cx.deps_dir.display(), cx.primary);

    let primary = cx.primary;
    let rustc = prepare_rustc(root, target, crate_types, cx);

    log!(5, "command={}", rustc);

    let _ = cx.config.shell().verbose(|shell| shell.status("Running", rustc.to_str()));

    proc() {
        if primary {
            rustc.exec().map_err(|err| human(err.to_str()))
        } else {
            rustc.exec_with_output().and(Ok(())).map_err(|err| {
                human(err.to_str())
            })
        }
    }
}

fn prepare_rustc(root: &Path, target: &Target, crate_types: Vec<&str>,
                 cx: &Context) -> ProcessBuilder {
    let mut args = Vec::new();

    build_base_args(&mut args, target, crate_types, cx);
    build_deps_args(&mut args, cx);

    util::process("rustc")
        .cwd(root.clone())
        .args(args.as_slice())
        .env("RUST_LOG", None) // rustc is way too noisy
}

fn build_base_args(into: &mut Args,
                   target: &Target,
                   crate_types: Vec<&str>,
                   cx: &Context)
{
    let metadata = target.get_metadata();

    // TODO: Handle errors in converting paths into args
    into.push(target.get_src_path().display().to_str());

    into.push("--crate-name".to_str());
    into.push(target.get_name().to_str());

    for crate_type in crate_types.iter() {
        into.push("--crate-type".to_str());
        into.push(crate_type.to_str());
    }

    let out = cx.dest.clone();
    let profile = target.get_profile();

    if profile.get_opt_level() != 0 {
        into.push("--opt-level".to_str());
        into.push(profile.get_opt_level().to_str());
    }

    // Right now -g is a little buggy, so we're not passing -g just yet
    // if profile.get_debug() {
    //     into.push("-g".to_str());
    // }

    if profile.is_test() {
        into.push("--test".to_str());
    }

    match metadata {
        Some(m) => {
            into.push("-C".to_str());
            into.push(format!("metadata={}", m.metadata));

            into.push("-C".to_str());
            into.push(format!("extra-filename=-{}", m.extra_filename));
        }
        None => {}
    }

    if target.is_lib() {
        into.push("--out-dir".to_str());
        into.push(out.display().to_str());
    } else {
        into.push("-o".to_str());
        into.push(out.join(target.get_name()).display().to_str());
    }
}

fn build_deps_args(dst: &mut Args, cx: &Context) {
    dst.push("-L".to_str());
    dst.push(cx.dest.display().to_str());
    dst.push("-L".to_str());
    dst.push(cx.deps_dir.display().to_str());
}

/// Execute all jobs necessary to build the dependency graph.
///
/// This function will spawn off `config.jobs()` workers to build all of the
/// necessary dependencies, in order. Freshness is propagated as far as possible
/// along each dependency chain.
fn execute(config: &mut Config,
           jobs: Vec<(&Package, (Freshness, Job))>) -> CargoResult<()> {
    let pool = TaskPool::new(config.jobs());
    let (tx, rx) = channel();
    let mut queue = DependencyQueue::new();
    for &(pkg, _) in jobs.iter() {
        queue.register(pkg);
    }
    for (pkg, (fresh, job)) in jobs.move_iter() {
        queue.enqueue(pkg, fresh, (pkg, job));
    }

    // Iteratively execute the dependency graph. Each turn of this loop will
    // schedule as much work as possible and then wait for one job to finish,
    // possibly scheduling more work afterwards.
    let mut active = 0i;
    while queue.len() > 0 {
        loop {
            match queue.dequeue() {
                Some((name, Fresh, (pkg, _))) => {
                    try!(config.shell().status("Fresh", pkg));
                    tx.send((name, Fresh, Ok(())));
                }
                Some((name, Dirty, (pkg, job))) => {
                    try!(config.shell().status("Compiling", pkg));
                    let my_tx = tx.clone();
                    pool.execute(proc() my_tx.send((name, Dirty, job())));
                }
                None => break,
            }
        }

        // Now that all possible work has been scheduled, wait for a piece of
        // work to finish. If any package fails to build then we stop scheduling
        // work as quickly as possibly.
        active -= 1;
        match rx.recv() {
            (name, fresh, Ok(())) => queue.finish(&name, fresh),
            (_, _, Err(e)) => {
                if active > 0 && config.jobs() > 1 {
                    try!(config.shell().say("Build failed, waiting for other \
                                             jobs to finish...", YELLOW));
                    for _ in rx.iter() {}
                }
                return Err(e)
            }
        }
    }

    log!(5, "rustc jobs completed");

    Ok(())
}
<|endoftext|>


<commit_before>extern crate itertools;

use itertools::{EitherOrBoth, Itertools};

use std::fmt::Debug;
use std::ops::BitXor;

struct Unspecialized<I>(I);
impl<I> Iterator for Unspecialized<I>
where
    I: Iterator,
{
    type Item = I::Item;

    #[inline(always)]
    fn next(&mut self) -> Option<I::Item> {
        self.0.next()
    }

    #[inline(always)]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

fn check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F)
where
    V: Eq + Debug,
    IterItem: 'a,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
    F: Fn(Box<Iterator<Item = IterItem> + 'a>) -> V,
{
    assert_eq!(
        mapper(Box::new(Unspecialized(iterator.clone()))),
        mapper(Box::new(iterator.clone()))
    )
}

fn check_specialized_count_last_nth_sizeh<'a, IterItem, Iter>(it: &Iter, expected_size: usize)
where
    IterItem: 'a + Eq + Debug,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
{
    let size = it.clone().count();
    assert_eq!(size, expected_size);
    check_specialized(it, |i| i.count());
    check_specialized(it, |i| i.last());
    for n in 0..size + 2 {
        check_specialized(it, |mut i| i.nth(n));
    }
    let mut it_sh = it.clone();
    for n in 0..size + 2 {
        let len = it_sh.clone().count();
        let (min, max) = it_sh.size_hint();
        assert_eq!((size - n.min(size)), len);
        assert!(min <= len);
        if let Some(max) = max {
            assert!(len <= max);
        }
        it_sh.next();
    }
}

fn check_specialized_fold_xor<'a, IterItem, Iter>(it: &Iter)
where
    IterItem: 'a
        + BitXor
        + Eq
        + Debug
        + BitXor<<IterItem as BitXor>::Output, Output = <IterItem as BitXor>::Output>
        + Clone,
    <IterItem as BitXor>::Output:
        BitXor<Output = <IterItem as BitXor>::Output> + Eq + Debug + Clone,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
{
    check_specialized(it, |mut i| {
        let first = i.next().map(|f| f.clone() ^ (f.clone() ^ f));
        i.fold(first, |acc, v: IterItem| acc.map(move |a| v ^ a))
    });
}

#[test]
fn put_back() {
    let test_vec = vec![7, 4, 1];
    {
        // Lexical lifetimes support
        let pb = itertools::put_back(test_vec.iter());
        check_specialized_count_last_nth_sizeh(&pb, 3);
        check_specialized_fold_xor(&pb);
    }

    let mut pb = itertools::put_back(test_vec.into_iter());
    pb.put_back(1);
    check_specialized_count_last_nth_sizeh(&pb, 4);
    check_specialized_fold_xor(&pb);
}

#[test]
fn merge_join_by() {
    let i1 = vec![1, 3, 5, 7, 8, 9].into_iter();
    let i2 = vec![0, 3, 4, 5].into_iter();
    let mjb = i1.clone().merge_join_by(i2.clone(), std::cmp::Ord::cmp);
    check_specialized_count_last_nth_sizeh(&mjb, 8);
    // Rust 1.24 compatibility:
    fn eob_left_z(eob: EitherOrBoth<usize, usize>) -> usize {
        eob.left().unwrap_or(0)
    }
    fn eob_right_z(eob: EitherOrBoth<usize, usize>) -> usize {
        eob.left().unwrap_or(0)
    }
    fn eob_both_z(eob: EitherOrBoth<usize, usize>) -> usize {
        let (a, b) = eob.both().unwrap_or((0, 0));
        assert_eq!(a, b);
        a
    }
    check_specialized_fold_xor(&mjb.clone().map(eob_left_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_right_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_both_z));

	// And the other way around
    let mjb = i2.merge_join_by(i1, std::cmp::Ord::cmp);
    check_specialized_count_last_nth_sizeh(&mjb, 8);
    check_specialized_fold_xor(&mjb.clone().map(eob_left_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_right_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_both_z));
}
<commit_msg>Added quickchecks<commit_after>extern crate itertools;

#[macro_use]
extern crate quickcheck;

use itertools::{EitherOrBoth, Itertools};

use std::fmt::Debug;
use std::ops::BitXor;

struct Unspecialized<I>(I);
impl<I> Iterator for Unspecialized<I>
where
    I: Iterator,
{
    type Item = I::Item;

    #[inline(always)]
    fn next(&mut self) -> Option<I::Item> {
        self.0.next()
    }

    #[inline(always)]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

fn check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F)
where
    V: Eq + Debug,
    IterItem: 'a,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
    F: Fn(Box<Iterator<Item = IterItem> + 'a>) -> V,
{
    assert_eq!(
        mapper(Box::new(Unspecialized(iterator.clone()))),
        mapper(Box::new(iterator.clone()))
    )
}

fn check_specialized_count_last_nth_sizeh<'a, IterItem, Iter>(
    it: &Iter,
    known_expected_size: Option<usize>,
) where
    IterItem: 'a + Eq + Debug,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
{
    let size = it.clone().count();
    if let Some(expected_size) = known_expected_size {
        assert_eq!(size, expected_size);
    }
    check_specialized(it, |i| i.count());
    check_specialized(it, |i| i.last());
    for n in 0..size + 2 {
        check_specialized(it, |mut i| i.nth(n));
    }
    let mut it_sh = it.clone();
    for n in 0..size + 2 {
        let len = it_sh.clone().count();
        let (min, max) = it_sh.size_hint();
        assert_eq!((size - n.min(size)), len);
        assert!(min <= len);
        if let Some(max) = max {
            assert!(len <= max);
        }
        it_sh.next();
    }
}

fn check_specialized_fold_xor<'a, IterItem, Iter>(it: &Iter)
where
    IterItem: 'a
        + BitXor
        + Eq
        + Debug
        + BitXor<<IterItem as BitXor>::Output, Output = <IterItem as BitXor>::Output>
        + Clone,
    <IterItem as BitXor>::Output:
        BitXor<Output = <IterItem as BitXor>::Output> + Eq + Debug + Clone,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
{
    check_specialized(it, |mut i| {
        let first = i.next().map(|f| f.clone() ^ (f.clone() ^ f));
        i.fold(first, |acc, v: IterItem| acc.map(move |a| v ^ a))
    });
}

fn put_back_test(test_vec: Vec<i32>, known_expected_size: Option<usize>) {
    {
        // Lexical lifetimes support
        let pb = itertools::put_back(test_vec.iter());
        check_specialized_count_last_nth_sizeh(&pb, known_expected_size);
        check_specialized_fold_xor(&pb);
    }

    let mut pb = itertools::put_back(test_vec.into_iter());
    pb.put_back(1);
    check_specialized_count_last_nth_sizeh(&pb, known_expected_size.map(|x| x + 1));
    check_specialized_fold_xor(&pb)
}

#[test]
fn put_back() {
    put_back_test(vec![7, 4, 1], Some(3));
}

quickcheck! {
    fn put_back_qc(test_vec: Vec<i32>) -> () {
        put_back_test(test_vec, None)
    }
}

fn merge_join_by_test(i1: Vec<usize>, i2: Vec<usize>, known_expected_size: Option<usize>) {
    let i1 = i1.into_iter();
    let i2 = i2.into_iter();
    let mjb = i1.clone().merge_join_by(i2.clone(), std::cmp::Ord::cmp);
    check_specialized_count_last_nth_sizeh(&mjb, known_expected_size);
    // Rust 1.24 compatibility:
    fn eob_left_z(eob: EitherOrBoth<usize, usize>) -> usize {
        eob.left().unwrap_or(0)
    }
    fn eob_right_z(eob: EitherOrBoth<usize, usize>) -> usize {
        eob.left().unwrap_or(0)
    }
    fn eob_both_z(eob: EitherOrBoth<usize, usize>) -> usize {
        let (a, b) = eob.both().unwrap_or((0, 0));
        assert_eq!(a, b);
        a
    }
    check_specialized_fold_xor(&mjb.clone().map(eob_left_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_right_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_both_z));

    // And the other way around
    let mjb = i2.merge_join_by(i1, std::cmp::Ord::cmp);
    check_specialized_count_last_nth_sizeh(&mjb, known_expected_size);
    check_specialized_fold_xor(&mjb.clone().map(eob_left_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_right_z));
    check_specialized_fold_xor(&mjb.clone().map(eob_both_z));
}

#[test]
fn merge_join_by() {
    let i1 = vec![1, 3, 5, 7, 8, 9];
    let i2 = vec![0, 3, 4, 5];
    merge_join_by_test(i1, i2, Some(8));
}

quickcheck! {
    fn merge_join_by_qc(i1: Vec<usize>, i2: Vec<usize>) -> () {
        merge_join_by_test(i1, i2, None)
    }
}
<|endoftext|>


<commit_before>use std::io;
use super::{Deserialize, Serialize, Error, GlobalType, InitExpr};

/// Global entry in the module.
pub struct GlobalEntry {
    global_type: GlobalType,
    init_expr: InitExpr,
}

impl GlobalEntry {
    /// Global type.
    pub fn global_type(&self) -> &GlobalType { &self.global_type }
    /// Initialization expression (opcodes) for global.
    pub fn init_expr(&self) -> &InitExpr { &self.init_expr }
}

impl Deserialize for GlobalEntry {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let global_type = GlobalType::deserialize(reader)?;
        let init_expr = InitExpr::deserialize(reader)?;

        Ok(GlobalEntry {
            global_type: global_type,
            init_expr: init_expr,
        })
    }
}

impl Serialize for GlobalEntry {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        self.global_type.serialize(writer)?;
        self.init_expr.serialize(writer)
    }
}<commit_msg>add mutable refs<commit_after>use std::io;
use super::{Deserialize, Serialize, Error, GlobalType, InitExpr};

/// Global entry in the module.
pub struct GlobalEntry {
    global_type: GlobalType,
    init_expr: InitExpr,
}

impl GlobalEntry {
    /// Global type.
    pub fn global_type(&self) -> &GlobalType { &self.global_type }
    /// Initialization expression (opcodes) for global.
    pub fn init_expr(&self) -> &InitExpr { &self.init_expr }
    /// Global type (mutable)
    pub fn global_type_mut(&mut self) -> &mut GlobalType { &mut self.global_type }
    /// Initialization expression (opcodes) for global (mutable)
    pub fn init_expr_mut(&mut self) -> &mut InitExpr { &mut self.init_expr }
}

impl Deserialize for GlobalEntry {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let global_type = GlobalType::deserialize(reader)?;
        let init_expr = InitExpr::deserialize(reader)?;

        Ok(GlobalEntry {
            global_type: global_type,
            init_expr: init_expr,
        })
    }
}

impl Serialize for GlobalEntry {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        self.global_type.serialize(writer)?;
        self.init_expr.serialize(writer)
    }
}<|endoftext|>


<commit_before>use rusqlite::Connection;
use std::result;
use log;

#[derive(Debug)]
pub struct VariableName {
    pub id: i32,
    pub name: String,
}

pub fn table_create_variable_name(conn: &Connection) -> &Connection {
    conn.execute(
        "CREATE TABLE VARIABLE_NAME (
                  id            INTEGER PRIMARY KEY ASC,
                  name      TEXT NOT NULL UNIQUE
                  )",
        &[],
    ).unwrap();
    return conn;
}

pub fn insert_variable_name(conn: &Connection, name: &String) -> Result<i32, &'static str> {
    let me = VariableName {
        id: 0,
        name: name.clone(),
    };
    let variable_name_instance = conn.execute(
        "INSERT INTO VARIABLE_NAME (name)
                  VALUES (?1)",
        &[&me.name],
    );
    if variable_name_instance.is_err() {
        return Err("Insert failed");
    }
    variable_name_instance.unwrap();
    return Ok(0);
}

pub fn list_variable_name(conn: &Connection) -> Vec<VariableName> {
    let mut stmt = conn.prepare("SELECT id, name  FROM VARIABLE_NAME").unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        VariableName {
            id: row.get(0),
            name: row.get(1),
        }
    });
    let mut items = Vec::<VariableName>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn variable_name_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, name, fk_provider, sq_order FROM VARIABLE_NAME")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        VariableName {
            id: row.get(0),
            name: row.get(1),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found variable_name {:?}", person.unwrap());
    }
}

pub fn pk_variable_name_by_name(conn: &Connection, name: &str) -> Result<i32, &'static str> {
    let mut output = 0;
    let bill = String::from(name);
    let mut stmt = conn.prepare("SELECT id, name  FROM VARIABLE_NAME WHERE name = ?1")
        .unwrap();
    let variable_name_iter = stmt.query_map(&[&name], |row| {
        VariableName {
            id: row.get(0),
            name: row.get(1),
        }
    });
    if variable_name_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = variable_name_iter.unwrap();
    let mut found = 0;
    for person in result {
        let bill = person.unwrap();
        output = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(output);
    }
    return Err("None found");
}
<commit_msg>Remoive unused 'use'<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub struct VariableName {
    pub id: i32,
    pub name: String,
}

pub fn table_create_variable_name(conn: &Connection) -> &Connection {
    conn.execute(
        "CREATE TABLE VARIABLE_NAME (
                  id            INTEGER PRIMARY KEY ASC,
                  name      TEXT NOT NULL UNIQUE
                  )",
        &[],
    ).unwrap();
    return conn;
}

pub fn insert_variable_name(conn: &Connection, name: &String) -> Result<i32, &'static str> {
    let me = VariableName {
        id: 0,
        name: name.clone(),
    };
    let variable_name_instance = conn.execute(
        "INSERT INTO VARIABLE_NAME (name)
                  VALUES (?1)",
        &[&me.name],
    );
    if variable_name_instance.is_err() {
        return Err("Insert failed");
    }
    variable_name_instance.unwrap();
    return Ok(0);
}

pub fn list_variable_name(conn: &Connection) -> Vec<VariableName> {
    let mut stmt = conn.prepare("SELECT id, name  FROM VARIABLE_NAME").unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        VariableName {
            id: row.get(0),
            name: row.get(1),
        }
    });
    let mut items = Vec::<VariableName>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn variable_name_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, name, fk_provider, sq_order FROM VARIABLE_NAME")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        VariableName {
            id: row.get(0),
            name: row.get(1),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found variable_name {:?}", person.unwrap());
    }
}

pub fn pk_variable_name_by_name(conn: &Connection, name: &str) -> Result<i32, &'static str> {
    let mut output = 0;
    let bill = String::from(name);
    let mut stmt = conn.prepare("SELECT id, name  FROM VARIABLE_NAME WHERE name = ?1")
        .unwrap();
    let variable_name_iter = stmt.query_map(&[&name], |row| {
        VariableName {
            id: row.get(0),
            name: row.get(1),
        }
    });
    if variable_name_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = variable_name_iter.unwrap();
    let mut found = 0;
    for person in result {
        let bill = person.unwrap();
        output = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(output);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>// Checks if the correct annotation for the efiapi ABI is passed to llvm.

// revisions:x86_64 i686 aarch64 arm riscv

// min-llvm-version 9.0

//[x86_64] compile-flags: --target x86_64-unknown-uefi
//[i686] compile-flags: --target i686-unknown-linux-musl
//[aarch64] compile-flags: --target aarch64-unknown-none
//[arm] compile-flags: --target armv7r-none-eabi
//[riscv] compile-flags: --target riscv64gc-unknown-none-elf
// compile-flags: -C no-prepopulate-passes

#![crate_type = "lib"]
#![feature(no_core, lang_items, abi_efiapi)]
#![no_core]

#[lang="sized"]
trait Sized { }
#[lang="freeze"]
trait Freeze { }
#[lang="copy"]
trait Copy { }

//x86_64: define win64cc void @has_efiapi
//i686: define void @has_efiapi
//aarch64: define void @has_efiapi
//arm: define void @has_efiapi
//riscv: define void @has_efiapi
#[no_mangle]
pub extern "efiapi" fn has_efiapi() {}
<commit_msg>Rollup merge of #66084 - petrochenkov:x86arm, r=alexcrichton<commit_after>// Checks if the correct annotation for the efiapi ABI is passed to llvm.

// revisions:x86_64 i686 arm

// min-llvm-version 9.0

//[x86_64] compile-flags: --target x86_64-unknown-uefi
//[i686] compile-flags: --target i686-unknown-linux-musl
//[arm] compile-flags: --target armv7r-none-eabi
// compile-flags: -C no-prepopulate-passes

#![crate_type = "lib"]
#![feature(no_core, lang_items, abi_efiapi)]
#![no_core]

#[lang="sized"]
trait Sized { }
#[lang="freeze"]
trait Freeze { }
#[lang="copy"]
trait Copy { }

//x86_64: define win64cc void @has_efiapi
//i686: define void @has_efiapi
//arm: define void @has_efiapi
#[no_mangle]
pub extern "efiapi" fn has_efiapi() {}
<|endoftext|>


<commit_before>fn foo<'a: 'b, 'b: 'a>() {}
fn main() {
    foo::<'static>();//~ ERROR E0090
                     //~^ too few lifetime parameters
}
<commit_msg>Fix tidy warning<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn foo<'a: 'b, 'b: 'a>() {}
fn main() {
    foo::<'static>();//~ ERROR E0090
                     //~^ too few lifetime parameters
}
<|endoftext|>


<commit_before>use hyper::Url;
use hyper::header::{Headers, Header, HeaderFormat};
use hyper::method::Method;
use hyper;
use std::io::{Read, Write, BufReader, BufWriter};

use datatype::Error;

#[derive(Clone, Debug)]
pub struct HttpRequest<'a> {
    pub url: Url,
    pub method: Method,
    pub headers: Headers,
    pub body: Option<&'a str>
}

impl<'a> ToString for HttpRequest<'a> {
    fn to_string(&self) -> String {
        return format!("{} {}", self.method, self.url.serialize())
    }
}

impl<'a> HttpRequest<'a> {
    pub fn new(url: Url, method: Method) -> HttpRequest<'a> {
        HttpRequest { url: url, method: method, headers: Headers::new(), body: None }
    }

    pub fn get(url: Url) -> HttpRequest<'a> {
        HttpRequest::new(url, Method::Get)
    }

    pub fn post(url: Url) -> HttpRequest<'a> {
        HttpRequest::new(url, Method::Post)
    }

    pub fn with_body(&self, body: &'a str) -> HttpRequest<'a> {
        HttpRequest { body: Some(body), ..self.clone() }
    }

    pub fn with_header<H: Header + HeaderFormat>(&self, header: H) -> HttpRequest<'a> {
        let mut hs = self.headers.clone();
        hs.set(header);
        HttpRequest { headers: hs, ..self.clone() }
    }
}

pub trait HttpClient {
    fn new() -> Self;
    fn send_request(&self, req: &HttpRequest) -> Result<String, Error>;
    fn send_request_to<W: Write>(&self, req: &HttpRequest, to: W) -> Result<(), Error>;
}

impl HttpClient for hyper::Client {
    fn new() -> hyper::Client {
        let mut client = hyper::Client::new();
        client.set_redirect_policy(hyper::client::RedirectPolicy::FollowAll);
        client
    }

    fn send_request(&self, req: &HttpRequest) -> Result<String, Error> {
        self.request(req.method.clone(), req.url.clone())
            .headers(req.headers.clone())
            .body(if let Some(body) = req.body { body } else { "" })
            .send()
            .map_err(|e| {
                Error::ClientError(format!("{}", e))
            })
            .and_then(|mut resp| {
                let mut rbody = String::new();
                let status = resp.status;
                if status.is_success() {
                    resp.read_to_string(&mut rbody)
                        .map_err(|e| Error::ParseError(format!("Cannot read response: {}", e)))
                        .map(|_| rbody)
                } else {
                    Err(Error::ClientError(format!("Request failed with status {}", status)))
                }
            })
    }

    fn send_request_to<W: Write>(&self, req: &HttpRequest, to: W) -> Result<(), Error> {
        self.request(req.method.clone(), req.url.clone())
            .headers(req.headers.clone())
            .body(if let Some(body) = req.body { body } else { "" })
            .send()
            .map_err(|e| {
                Error::ClientError(format!("Cannot send request: {}", e))
            })
            .and_then(|resp| {
                let status = resp.status;
                if status.is_server_error() || status.is_client_error() {
                    Err(Error::ClientError(format!("Request errored with status {}", status)))
                } else {
                    tee(resp, to)
                        .map_err(|e| Error::ParseError(format!("Cannot read response: {}", e)))
                        .map(|_| ())
                }
            })
    }
}

pub fn tee<R: Read, W: Write>(from: R, to: W) -> Result<(), Error> {
    let mb = 1024 * 1024;
    let rbuf = BufReader::with_capacity(5 * mb, from);
    let mut wbuf = BufWriter::with_capacity(5 * mb, to);
    for b in rbuf.bytes() {
        try!(wbuf.write(&[try!(b)]));
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs::File;
    use std::io::{Read, repeat};

    #[test]
    fn test_tee() {
        let values = repeat(b'a').take(9000);
        let sink = File::create("/tmp/otaplus_tee_test").unwrap();

        assert!(tee(values, sink).is_ok());

        let mut values2 = repeat(b'a').take(9000);
        let mut expected = Vec::new();
        let _ = values2.read_to_end(&mut expected);

        let mut f = File::open("/tmp/otaplus_tee_test").unwrap();
        let mut result = Vec::new();
        let _ = f.read_to_end(&mut result);

        assert_eq!(result, expected);
    }

}
<commit_msg>Strip Authorization Header on redirect<commit_after>use hyper::Url;
use hyper::header::{Headers, Header, HeaderFormat, Location, Authorization, Bearer};
use hyper::method::Method;
use hyper::client::response::Response;
use hyper;
use std::io::{Read, Write, BufReader, BufWriter};

use datatype::Error;

#[derive(Clone, Debug)]
pub struct HttpRequest<'a> {
    pub url: Url,
    pub method: Method,
    pub headers: Headers,
    pub body: Option<&'a str>,
}

impl<'a> ToString for HttpRequest<'a> {
    fn to_string(&self) -> String {
        format!("{} {}", self.method, self.url.serialize())
    }
}

impl<'a> HttpRequest<'a> {
    pub fn new(url: Url, method: Method) -> HttpRequest<'a> {
        HttpRequest {
            url: url,
            method: method,
            headers: Headers::new(),
            body: None,
        }
    }

    pub fn get(url: Url) -> HttpRequest<'a> {
        HttpRequest::new(url, Method::Get)
    }

    pub fn post(url: Url) -> HttpRequest<'a> {
        HttpRequest::new(url, Method::Post)
    }

    pub fn with_body(&self, body: &'a str) -> HttpRequest<'a> {
        HttpRequest { body: Some(body), ..self.clone() }
    }

    pub fn with_header<H: Header + HeaderFormat>(&self, header: H) -> HttpRequest<'a> {
        let mut hs = self.headers.clone();
        hs.set(header);
        HttpRequest { headers: hs, ..self.clone() }
    }
}

pub trait HttpClient {
    fn new() -> Self;
    fn send_request(&self, req: &HttpRequest) -> Result<String, Error>;
    fn send_request_to<W: Write>(&self, req: &HttpRequest, to: W) -> Result<(), Error>;
}

impl HttpClient for hyper::Client {
    fn new() -> hyper::Client {
        let mut client = hyper::Client::new();
        client.set_redirect_policy(hyper::client::RedirectPolicy::FollowNone);
        client
    }

    fn send_request(&self, req: &HttpRequest) -> Result<String, Error> {
        self.request(req.method.clone(), req.url.clone())
            .headers(req.headers.clone())
            .body(req.body.unwrap_or(""))
            .send()
            .map_err(|e| Error::ClientError(format!("{}", e)))
            .and_then(|mut resp| {
                match resp.status.class() {
                    hyper::status::StatusClass::Success => {
                        let mut rbody = String::new();
                        resp.read_to_string(&mut rbody)
                            .map_err(|e| Error::ParseError(format!("Cannot read response: {}", e)))
                            .map(|_| rbody)
                    }
                    hyper::status::StatusClass::Redirection => {
                        relocate_request(req, &resp).and_then(|ref r| self.send_request(r))
                    }
                    _ => {
                        Err(Error::ClientError(format!("Request failed with status {}",
                                                       resp.status)))
                    }
                }
            })
    }

    fn send_request_to<W: Write>(&self, req: &HttpRequest, to: W) -> Result<(), Error> {
        self.request(req.method.clone(), req.url.clone())
            .headers(req.headers.clone())
            .body(req.body.unwrap_or(""))
            .send()
            .map_err(|e| Error::ClientError(format!("{}", e)))
            .and_then(|resp| {
                match resp.status.class() {
                    hyper::status::StatusClass::Success => {
                        tee(resp, to)
                            .map_err(|e| Error::ParseError(format!("Cannot read response: {}", e)))
                            .map(|_| ())
                    }
                    hyper::status::StatusClass::Redirection => {
                        relocate_request(req, &resp).and_then(|ref r| self.send_request_to(r, to))
                    }
                    _ => {
                        Err(Error::ClientError(format!("Request failed with status {}",
                                                       resp.status)))
                    }
                }
            })
    }
}

fn relocate_request<'a>(req: &'a HttpRequest, resp: &Response) -> Result<HttpRequest<'a>, Error> {
    match resp.headers.get::<Location>() {
        Some(&Location(ref loc)) => {
            req.url
               .join(loc)
               .map_err(|e| Error::ParseError(format!("Cannot read location: {}", e)))
               .and_then(|url| {
                   let mut headers = req.headers.clone();
                   headers.remove::<Authorization<Bearer>>();
                   Ok(HttpRequest {
                       url: url,
                       method: req.method.clone(),
                       headers: headers,
                       body: req.body,
                   })
               })
        }
        None => Err(Error::ClientError("Redirect with no Location header".to_string())),
    }
}

pub fn tee<R: Read, W: Write>(from: R, to: W) -> Result<(), Error> {
    let mb = 1024 * 1024;
    let rbuf = BufReader::with_capacity(5 * mb, from);
    let mut wbuf = BufWriter::with_capacity(5 * mb, to);
    for b in rbuf.bytes() {
        try!(wbuf.write(&[try!(b)]));
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs::File;
    use std::io::{Read, repeat};

    #[test]
    fn test_tee() {
        let values = repeat(b'a').take(9000);
        let sink = File::create("/tmp/otaplus_tee_test").unwrap();

        assert!(tee(values, sink).is_ok());

        let mut values2 = repeat(b'a').take(9000);
        let mut expected = Vec::new();
        let _ = values2.read_to_end(&mut expected);

        let mut f = File::open("/tmp/otaplus_tee_test").unwrap();
        let mut result = Vec::new();
        let _ = f.read_to_end(&mut result);

        assert_eq!(result, expected);
    }

}
<|endoftext|>