<commit_before>#[doc = "A type representing either success or failure"];

import either::either;

#[doc = "The result type"]
enum result<T, U> {
    #[doc = "Contains the successful result value"]
    ok(T),
    #[doc = "Contains the error value"]
    err(U)
}

#[doc = "
Get the value out of a successful result

# Failure

If the result is an error
"]
pure fn get<T: copy, U>(res: result<T, U>) -> T {
    alt res {
      ok(t) { t }
      err(the_err) {
        unchecked{ fail #fmt("get called on error result: %?", the_err); }
      }
    }
}

#[doc = "
Get the value out of an error result

# Failure

If the result is not an error
"]
pure fn get_err<T, U: copy>(res: result<T, U>) -> U {
    alt res {
      err(u) { u }
      ok(_) {
        fail "get_error called on ok result";
      }
    }
}

#[doc = "Returns true if the result is `ok`"]
pure fn is_success<T, U>(res: result<T, U>) -> bool {
    alt res {
      ok(_) { true }
      err(_) { false }
    }
}

#[doc = "Returns true if the result is `error`"]
pure fn is_failure<T, U>(res: result<T, U>) -> bool {
    !is_success(res)
}

#[doc = "
Convert to the `either` type

`ok` result variants are converted to `either::right` variants, `err`
result variants are converted to `either::left`.
"]
pure fn to_either<T: copy, U: copy>(res: result<U, T>) -> either<T, U> {
    alt res {
      ok(res) { either::right(res) }
      err(fail_) { either::left(fail_) }
    }
}

#[doc = "
Call a function based on a previous result

If `res` is `ok` then the value is extracted and passed to `op` whereupon
`op`s result is returned. if `res` is `err` then it is immediately returned.
This function can be used to compose the results of two functions.

Example:

    let res = chain(read_file(file)) { |buf|
        ok(parse_buf(buf))
    }
"]
fn chain<T, U: copy, V: copy>(res: result<T, V>, op: fn(T) -> result<U, V>)
    -> result<U, V> {
    alt res {
      ok(t) { op(t) }
      err(e) { err(e) }
    }
}

#[doc = "
Call a function based on a previous result

If `res` is `err` then the value is extracted and passed to `op`
whereupon `op`s result is returned. if `res` is `ok` then it is
immediately returned.  This function can be used to pass through a
successful result while handling an error.
"]
fn chain_err<T: copy, U: copy, V: copy>(
    res: result<T, V>,
    op: fn(V) -> result<T, U>)
    -> result<T, U> {
    alt res {
      ok(t) { ok(t) }
      err(v) { op(v) }
    }
}

impl extensions<T:copy, E:copy> for result<T,E> {
    fn get() -> T { get(self) }

    fn get_err() -> E { get_err(self) }

    fn is_success() -> bool { is_success(self) }

    fn is_failure() -> bool { is_failure(self) }

    fn chain<U:copy>(op: fn(T) -> result<U,E>) -> result<U,E> {
        chain(self, op)
    }

    fn chain_err<F:copy>(op: fn(E) -> result<T,F>) -> result<T,F> {
        chain_err(self, op)
    }
}

#[doc = "
Maps each element in the vector `ts` using the operation `op`.  Should an
error occur, no further mappings are performed and the error is returned.
Should no error occur, a vector containing the result of each map is
returned.

Here is an example which increments every integer in a vector,
checking for overflow:

    fn inc_conditionally(x: uint) -> result<uint,str> {
        if x == uint::max_value { ret err(\"overflow\"); }
        else { ret ok(x+1u); }
    }
    map([1u, 2u, 3u], inc_conditionally).chain {|incd|
        assert incd == [2u, 3u, 4u];
    }
"]
fn map<T,U:copy,V:copy>(
    ts: [T], op: fn(T) -> result<V,U>) -> result<[V],U> {

    let mut vs: [V] = [];
    vec::reserve(vs, vec::len(ts));
    for vec::each(ts) {|t|
        alt op(t) {
          ok(v) { vs += [v]; }
          err(u) { ret err(u); }
        }
    }
    ret ok(vs);
}

fn map_opt<T,U:copy,V:copy>(
    o_t: option<T>, op: fn(T) -> result<V,U>) -> result<option<V>,U> {

    alt o_t {
      none { ok(none) }
      some(t) {
        alt op(t) {
          ok(v) { ok(some(v)) }
          err(e) { err(e) }
        }
      }
    }
}

#[doc = "Same as map, but it operates over two parallel vectors.

A precondition is used here to ensure that the vectors are the same
length.  While we do not often use preconditions in the standard
library, a precondition is used here because result::t is generally
used in 'careful' code contexts where it is both appropriate and easy
to accommodate an error like the vectors being of different lengths."]
fn map2<S,T,U:copy,V:copy>(ss: [S], ts: [T], op: fn(S,T) -> result<V,U>)
    : vec::same_length(ss, ts) -> result<[V],U> {

    let n = vec::len(ts);
    let mut vs = [];
    vec::reserve(vs, n);
    let mut i = 0u;
    while i < n {
        alt op(ss[i],ts[i]) {
          ok(v) { vs += [v]; }
          err(u) { ret err(u); }
        }
        i += 1u;
    }
    ret ok(vs);
}

#[doc = "
Applies op to the pairwise elements from `ss` and `ts`, aborting on
error.  This could be implemented using `map2()` but it is more efficient
on its own as no result vector is built.
"]
fn iter2<S,T,U:copy>(ss: [S], ts: [T],
                     op: fn(S,T) -> result<(),U>)
    : vec::same_length(ss, ts)
    -> result<(),U> {

    let n = vec::len(ts);
    let mut i = 0u;
    while i < n {
        alt op(ss[i],ts[i]) {
          ok(()) { }
          err(u) { ret err(u); }
        }
        i += 1u;
    }
    ret ok(());
}

#[cfg(test)]
mod tests {
    fn op1() -> result::result<int, str> { result::ok(666) }

    fn op2(&&i: int) -> result::result<uint, str> {
        result::ok(i as uint + 1u)
    }

    fn op3() -> result::result<int, str> { result::err("sadface") }

    #[test]
    fn chain_success() {
        assert get(chain(op1(), op2)) == 667u;
    }

    #[test]
    fn chain_failure() {
        assert get_err(chain(op3(), op2)) == "sadface";
    }
}
<commit_msg>core: add result::unwrap() .. patch from @nmatsakis<commit_after>#[doc = "A type representing either success or failure"];

import either::either;

#[doc = "The result type"]
enum result<T, U> {
    #[doc = "Contains the successful result value"]
    ok(T),
    #[doc = "Contains the error value"]
    err(U)
}

#[doc = "
Get the value out of a successful result

# Failure

If the result is an error
"]
pure fn get<T: copy, U>(res: result<T, U>) -> T {
    alt res {
      ok(t) { t }
      err(the_err) {
        unchecked{ fail #fmt("get called on error result: %?", the_err); }
      }
    }
}

#[doc = "
Get the value out of an error result

# Failure

If the result is not an error
"]
pure fn get_err<T, U: copy>(res: result<T, U>) -> U {
    alt res {
      err(u) { u }
      ok(_) {
        fail "get_error called on ok result";
      }
    }
}

#[doc = "Returns true if the result is `ok`"]
pure fn is_success<T, U>(res: result<T, U>) -> bool {
    alt res {
      ok(_) { true }
      err(_) { false }
    }
}

#[doc = "Returns true if the result is `error`"]
pure fn is_failure<T, U>(res: result<T, U>) -> bool {
    !is_success(res)
}

#[doc = "
Convert to the `either` type

`ok` result variants are converted to `either::right` variants, `err`
result variants are converted to `either::left`.
"]
pure fn to_either<T: copy, U: copy>(res: result<U, T>) -> either<T, U> {
    alt res {
      ok(res) { either::right(res) }
      err(fail_) { either::left(fail_) }
    }
}

#[doc = "
Call a function based on a previous result

If `res` is `ok` then the value is extracted and passed to `op` whereupon
`op`s result is returned. if `res` is `err` then it is immediately returned.
This function can be used to compose the results of two functions.

Example:

    let res = chain(read_file(file)) { |buf|
        ok(parse_buf(buf))
    }
"]
fn chain<T, U: copy, V: copy>(res: result<T, V>, op: fn(T) -> result<U, V>)
    -> result<U, V> {
    alt res {
      ok(t) { op(t) }
      err(e) { err(e) }
    }
}

#[doc = "
Call a function based on a previous result

If `res` is `err` then the value is extracted and passed to `op`
whereupon `op`s result is returned. if `res` is `ok` then it is
immediately returned.  This function can be used to pass through a
successful result while handling an error.
"]
fn chain_err<T: copy, U: copy, V: copy>(
    res: result<T, V>,
    op: fn(V) -> result<T, U>)
    -> result<T, U> {
    alt res {
      ok(t) { ok(t) }
      err(v) { op(v) }
    }
}

impl extensions<T:copy, E:copy> for result<T,E> {
    fn get() -> T { get(self) }

    fn get_err() -> E { get_err(self) }

    fn is_success() -> bool { is_success(self) }

    fn is_failure() -> bool { is_failure(self) }

    fn chain<U:copy>(op: fn(T) -> result<U,E>) -> result<U,E> {
        chain(self, op)
    }

    fn chain_err<F:copy>(op: fn(E) -> result<T,F>) -> result<T,F> {
        chain_err(self, op)
    }
}

#[doc = "
Maps each element in the vector `ts` using the operation `op`.  Should an
error occur, no further mappings are performed and the error is returned.
Should no error occur, a vector containing the result of each map is
returned.

Here is an example which increments every integer in a vector,
checking for overflow:

    fn inc_conditionally(x: uint) -> result<uint,str> {
        if x == uint::max_value { ret err(\"overflow\"); }
        else { ret ok(x+1u); }
    }
    map([1u, 2u, 3u], inc_conditionally).chain {|incd|
        assert incd == [2u, 3u, 4u];
    }
"]
fn map<T,U:copy,V:copy>(
    ts: [T], op: fn(T) -> result<V,U>) -> result<[V],U> {

    let mut vs: [V] = [];
    vec::reserve(vs, vec::len(ts));
    for vec::each(ts) {|t|
        alt op(t) {
          ok(v) { vs += [v]; }
          err(u) { ret err(u); }
        }
    }
    ret ok(vs);
}

fn map_opt<T,U:copy,V:copy>(
    o_t: option<T>, op: fn(T) -> result<V,U>) -> result<option<V>,U> {

    alt o_t {
      none { ok(none) }
      some(t) {
        alt op(t) {
          ok(v) { ok(some(v)) }
          err(e) { err(e) }
        }
      }
    }
}

#[doc = "Same as map, but it operates over two parallel vectors.

A precondition is used here to ensure that the vectors are the same
length.  While we do not often use preconditions in the standard
library, a precondition is used here because result::t is generally
used in 'careful' code contexts where it is both appropriate and easy
to accommodate an error like the vectors being of different lengths."]
fn map2<S,T,U:copy,V:copy>(ss: [S], ts: [T], op: fn(S,T) -> result<V,U>)
    : vec::same_length(ss, ts) -> result<[V],U> {

    let n = vec::len(ts);
    let mut vs = [];
    vec::reserve(vs, n);
    let mut i = 0u;
    while i < n {
        alt op(ss[i],ts[i]) {
          ok(v) { vs += [v]; }
          err(u) { ret err(u); }
        }
        i += 1u;
    }
    ret ok(vs);
}

#[doc = "
Applies op to the pairwise elements from `ss` and `ts`, aborting on
error.  This could be implemented using `map2()` but it is more efficient
on its own as no result vector is built.
"]
fn iter2<S,T,U:copy>(ss: [S], ts: [T],
                     op: fn(S,T) -> result<(),U>)
    : vec::same_length(ss, ts)
    -> result<(),U> {

    let n = vec::len(ts);
    let mut i = 0u;
    while i < n {
        alt op(ss[i],ts[i]) {
          ok(()) { }
          err(u) { ret err(u); }
        }
        i += 1u;
    }
    ret ok(());
}

#[doc="
Unwraps a result, assuming it is an `ok(T)`

This operation is unsafe.
"]
fn unwrap<T, U>(-res: result<T, U>) -> T unsafe {
    let addr = alt res {
      ok(x) { ptr::addr_of(x) }
      err(_) { fail "option none" }
    };
    let liberated_value = unsafe::reinterpret_cast(*addr);
    unsafe::forget(res);
    ret liberated_value;
}

#[cfg(test)]
mod tests {
    fn op1() -> result::result<int, str> { result::ok(666) }

    fn op2(&&i: int) -> result::result<uint, str> {
        result::ok(i as uint + 1u)
    }

    fn op3() -> result::result<int, str> { result::err("sadface") }

    #[test]
    fn chain_success() {
        assert get(chain(op1(), op2)) == 667u;
    }

    #[test]
    fn chain_failure() {
        assert get_err(chain(op3(), op2)) == "sadface";
    }
}
<|endoftext|>


<commit_before>#![allow(missing_copy_implementations)]

use crate::fmt;
use crate::io::{self, Read, Initializer, Write, ErrorKind, BufRead, IoSlice, IoSliceMut};
use crate::mem;

/// Copies the entire contents of a reader into a writer.
///
/// This function will continuously read data from `reader` and then
/// write it into `writer` in a streaming fashion until `reader`
/// returns EOF.
///
/// On success, the total number of bytes that were copied from
/// `reader` to `writer` is returned.
///
/// If you’re wanting to copy the contents of one file to another and you’re
/// working with filesystem paths, see the [`fs::copy`] function.
///
/// [`fs::copy`]: ../fs/fn.copy.html
///
/// # Errors
///
/// This function will return an error immediately if any call to `read` or
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
/// handled by this function and the underlying operation is retried.
///
/// # Examples
///
/// ```
/// use std::io;
///
/// fn main() -> io::Result<()> {
///     let mut reader: &[u8] = b"hello";
///     let mut writer: Vec<u8> = vec![];
///
///     io::copy(&mut reader, &mut writer)?;
///
///     assert_eq!(&b"hello"[..], &writer[..]);
///     Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
    where R: Read, W: Write
{
    let mut buf = unsafe {
        #[allow(deprecated)]
        let mut buf: [u8; super::DEFAULT_BUF_SIZE] = mem::uninitialized();
        reader.initializer().initialize(&mut buf);
        buf
    };

    let mut written = 0;
    loop {
        let len = match reader.read(&mut buf) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write_all(&buf[..len])?;
        written += len as u64;
    }
}

/// A reader which is always at EOF.
///
/// This struct is generally created by calling [`empty`]. Please see
/// the documentation of [`empty()`][`empty`] for more details.
///
/// [`empty`]: fn.empty.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () }

/// Constructs a new handle to an empty reader.
///
/// All reads from the returned reader will return [`Ok`]`(0)`.
///
/// [`Ok`]: ../result/enum.Result.html#variant.Ok
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
///
/// ```
/// use std::io::{self, Read};
///
/// let mut buffer = String::new();
/// io::empty().read_to_string(&mut buffer).unwrap();
/// assert!(buffer.is_empty());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Empty {
    #[inline]
    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for Empty {
    #[inline]
    fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
    #[inline]
    fn consume(&mut self, _n: usize) {}
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Empty {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Empty { .. }")
    }
}

/// A reader which yields one byte over and over and over and over and over and...
///
/// This struct is generally created by calling [`repeat`][repeat]. Please
/// see the documentation of `repeat()` for more details.
///
/// [repeat]: fn.repeat.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat { byte: u8 }

/// Creates an instance of a reader that infinitely repeats one byte.
///
/// All reads from this reader will succeed by filling the specified buffer with
/// the given byte.
///
/// # Examples
///
/// ```
/// use std::io::{self, Read};
///
/// let mut buffer = [0; 3];
/// io::repeat(0b101).read_exact(&mut buffer).unwrap();
/// assert_eq!(buffer, [0b101, 0b101, 0b101]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat(byte: u8) -> Repeat { Repeat { byte } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Repeat {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        for slot in &mut *buf {
            *slot = self.byte;
        }
        Ok(buf.len())
    }

    #[inline]
    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        let mut nwritten = 0;
        for buf in bufs {
            nwritten += self.read(buf)?;
        }
        Ok(nwritten)
    }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Repeat {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Repeat { .. }")
    }
}

/// A writer which will move data into the void.
///
/// This struct is generally created by calling [`sink`][sink]. Please
/// see the documentation of `sink()` for more details.
///
/// [sink]: fn.sink.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink { _priv: () }

/// Creates an instance of a writer which will successfully consume all data.
///
/// All calls to `write` on the returned instance will return `Ok(buf.len())`
/// and the contents of the buffer will not be inspected.
///
/// # Examples
///
/// ```rust
/// use std::io::{self, Write};
///
/// let buffer = vec![1, 2, 3, 5, 8];
/// let num_bytes = io::sink().write(&buffer).unwrap();
/// assert_eq!(num_bytes, 5);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sink() -> Sink { Sink { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Sink {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }

    #[inline]
    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        let total_len = bufs.iter().map(|b| b.len()).sum();
        Ok(total_len)
    }

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

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Sink {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Sink { .. }")
    }
}

#[cfg(test)]
mod tests {
    use crate::io::prelude::*;
    use crate::io::{copy, sink, empty, repeat};

    #[test]
    fn copy_copies() {
        let mut r = repeat(0).take(4);
        let mut w = sink();
        assert_eq!(copy(&mut r, &mut w).unwrap(), 4);

        let mut r = repeat(0).take(1 << 17);
        assert_eq!(copy(&mut r as &mut dyn Read, &mut w as &mut dyn Write).unwrap(), 1 << 17);
    }

    #[test]
    fn sink_sinks() {
        let mut s = sink();
        assert_eq!(s.write(&[]).unwrap(), 0);
        assert_eq!(s.write(&[0]).unwrap(), 1);
        assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
        assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
    }

    #[test]
    fn empty_reads() {
        let mut e = empty();
        assert_eq!(e.read(&mut []).unwrap(), 0);
        assert_eq!(e.read(&mut [0]).unwrap(), 0);
        assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
        assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
    }

    #[test]
    fn repeat_repeats() {
        let mut r = repeat(4);
        let mut b = [0; 1024];
        assert_eq!(r.read(&mut b).unwrap(), 1024);
        assert!(b.iter().all(|b| *b == 4));
    }

    #[test]
    fn take_some_bytes() {
        assert_eq!(repeat(4).take(100).bytes().count(), 100);
        assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
        assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
    }
}
<commit_msg>Rollup merge of #62732 - nathanwhit:fix_mem_uninit, r=Amanieu<commit_after>#![allow(missing_copy_implementations)]

use crate::fmt;
use crate::io::{self, Read, Initializer, Write, ErrorKind, BufRead, IoSlice, IoSliceMut};
use crate::mem;

/// Copies the entire contents of a reader into a writer.
///
/// This function will continuously read data from `reader` and then
/// write it into `writer` in a streaming fashion until `reader`
/// returns EOF.
///
/// On success, the total number of bytes that were copied from
/// `reader` to `writer` is returned.
///
/// If you’re wanting to copy the contents of one file to another and you’re
/// working with filesystem paths, see the [`fs::copy`] function.
///
/// [`fs::copy`]: ../fs/fn.copy.html
///
/// # Errors
///
/// This function will return an error immediately if any call to `read` or
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
/// handled by this function and the underlying operation is retried.
///
/// # Examples
///
/// ```
/// use std::io;
///
/// fn main() -> io::Result<()> {
///     let mut reader: &[u8] = b"hello";
///     let mut writer: Vec<u8> = vec![];
///
///     io::copy(&mut reader, &mut writer)?;
///
///     assert_eq!(&b"hello"[..], &writer[..]);
///     Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
    where R: Read, W: Write
{
    let mut buf = unsafe {
        // This is still technically undefined behavior due to creating a reference
        // to uninitialized data, but within libstd we can rely on more guarantees
        // than if this code were in an external lib

        // FIXME: This should probably be changed to an array of `MaybeUninit<u8>`
        // once the `mem::MaybeUninit` slice APIs stabilize
        let mut buf: mem::MaybeUninit<[u8; super::DEFAULT_BUF_SIZE]> = mem::MaybeUninit::uninit();
        reader.initializer().initialize(&mut *buf.as_mut_ptr());
        buf.assume_init()
    };

    let mut written = 0;
    loop {
        let len = match reader.read(&mut buf) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write_all(&buf[..len])?;
        written += len as u64;
    }
}

/// A reader which is always at EOF.
///
/// This struct is generally created by calling [`empty`]. Please see
/// the documentation of [`empty()`][`empty`] for more details.
///
/// [`empty`]: fn.empty.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () }

/// Constructs a new handle to an empty reader.
///
/// All reads from the returned reader will return [`Ok`]`(0)`.
///
/// [`Ok`]: ../result/enum.Result.html#variant.Ok
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
///
/// ```
/// use std::io::{self, Read};
///
/// let mut buffer = String::new();
/// io::empty().read_to_string(&mut buffer).unwrap();
/// assert!(buffer.is_empty());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Empty {
    #[inline]
    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for Empty {
    #[inline]
    fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
    #[inline]
    fn consume(&mut self, _n: usize) {}
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Empty {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Empty { .. }")
    }
}

/// A reader which yields one byte over and over and over and over and over and...
///
/// This struct is generally created by calling [`repeat`][repeat]. Please
/// see the documentation of `repeat()` for more details.
///
/// [repeat]: fn.repeat.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat { byte: u8 }

/// Creates an instance of a reader that infinitely repeats one byte.
///
/// All reads from this reader will succeed by filling the specified buffer with
/// the given byte.
///
/// # Examples
///
/// ```
/// use std::io::{self, Read};
///
/// let mut buffer = [0; 3];
/// io::repeat(0b101).read_exact(&mut buffer).unwrap();
/// assert_eq!(buffer, [0b101, 0b101, 0b101]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat(byte: u8) -> Repeat { Repeat { byte } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Repeat {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        for slot in &mut *buf {
            *slot = self.byte;
        }
        Ok(buf.len())
    }

    #[inline]
    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        let mut nwritten = 0;
        for buf in bufs {
            nwritten += self.read(buf)?;
        }
        Ok(nwritten)
    }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Repeat {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Repeat { .. }")
    }
}

/// A writer which will move data into the void.
///
/// This struct is generally created by calling [`sink`][sink]. Please
/// see the documentation of `sink()` for more details.
///
/// [sink]: fn.sink.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink { _priv: () }

/// Creates an instance of a writer which will successfully consume all data.
///
/// All calls to `write` on the returned instance will return `Ok(buf.len())`
/// and the contents of the buffer will not be inspected.
///
/// # Examples
///
/// ```rust
/// use std::io::{self, Write};
///
/// let buffer = vec![1, 2, 3, 5, 8];
/// let num_bytes = io::sink().write(&buffer).unwrap();
/// assert_eq!(num_bytes, 5);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sink() -> Sink { Sink { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Sink {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }

    #[inline]
    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        let total_len = bufs.iter().map(|b| b.len()).sum();
        Ok(total_len)
    }

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

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Sink {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Sink { .. }")
    }
}

#[cfg(test)]
mod tests {
    use crate::io::prelude::*;
    use crate::io::{copy, sink, empty, repeat};

    #[test]
    fn copy_copies() {
        let mut r = repeat(0).take(4);
        let mut w = sink();
        assert_eq!(copy(&mut r, &mut w).unwrap(), 4);

        let mut r = repeat(0).take(1 << 17);
        assert_eq!(copy(&mut r as &mut dyn Read, &mut w as &mut dyn Write).unwrap(), 1 << 17);
    }

    #[test]
    fn sink_sinks() {
        let mut s = sink();
        assert_eq!(s.write(&[]).unwrap(), 0);
        assert_eq!(s.write(&[0]).unwrap(), 1);
        assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
        assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
    }

    #[test]
    fn empty_reads() {
        let mut e = empty();
        assert_eq!(e.read(&mut []).unwrap(), 0);
        assert_eq!(e.read(&mut [0]).unwrap(), 0);
        assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
        assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
    }

    #[test]
    fn repeat_repeats() {
        let mut r = repeat(4);
        let mut b = [0; 1024];
        assert_eq!(r.read(&mut b).unwrap(), 1024);
        assert!(b.iter().all(|b| *b == 4));
    }

    #[test]
    fn take_some_bytes() {
        assert_eq!(repeat(4).take(100).bytes().count(), 100);
        assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
        assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 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.

use libc;
use uint;
use option::{Some, None};
use cell::Cell;
use clone::Clone;
use container::Container;
use iterator::IteratorUtil;
use vec::{OwnedVector, MutableVector};
use super::io::net::ip::{IpAddr, Ipv4, Ipv6};
use rt::sched::Scheduler;
use rt::local::Local;
use unstable::run_in_bare_thread;
use rt::thread::Thread;
use rt::task::Task;
use rt::uv::uvio::UvEventLoop;
use rt::work_queue::WorkQueue;
use rt::sleeper_list::SleeperList;
use rt::task::{Sched};
use rt::comm::oneshot;
use result::{Result, Ok, Err};

pub fn new_test_uv_sched() -> Scheduler {

    let mut sched = Scheduler::new(~UvEventLoop::new(),
                                   WorkQueue::new(),
                                   SleeperList::new());
    // Don't wait for the Shutdown message
    sched.no_sleep = true;
    return sched;
}

/// Creates a new scheduler in a new thread and runs a task in it,
/// then waits for the scheduler to exit. Failure of the task
/// will abort the process.
pub fn run_in_newsched_task(f: ~fn()) {
    let f = Cell::new(f);

    do run_in_bare_thread {
        let mut sched = ~new_test_uv_sched();
        let on_exit: ~fn(bool) = |exit_status| rtassert!(exit_status);
        let mut task = ~Task::new_root(&mut sched.stack_pool,
                                       f.take());
        rtdebug!("newsched_task: %x", to_uint(task));
        task.on_exit = Some(on_exit);
        sched.enqueue_task(task);
        sched.run();
    }
}

/// Create more than one scheduler and run a function in a task
/// in one of the schedulers. The schedulers will stay alive
/// until the function `f` returns.
pub fn run_in_mt_newsched_task(f: ~fn()) {
    use os;
    use from_str::FromStr;
    use rt::sched::Shutdown;
    use rt::util;

    let f_cell = Cell::new(f);

    do run_in_bare_thread {
        let nthreads = match os::getenv("RUST_RT_TEST_THREADS") {
            Some(nstr) => FromStr::from_str(nstr).get(),
            None => {
                // Using more threads than cores in test code
                // to force the OS to preempt them frequently.
                // Assuming that this help stress test concurrent types.
                util::num_cpus() * 2
            }
        };

        let sleepers = SleeperList::new();
        let work_queue = WorkQueue::new();

        let mut handles = ~[];
        let mut scheds = ~[];

        for uint::range(0, nthreads) |_| {
            let loop_ = ~UvEventLoop::new();
            let mut sched = ~Scheduler::new(loop_,
                                            work_queue.clone(),
                                            sleepers.clone());
            let handle = sched.make_handle();

            handles.push(handle);
            scheds.push(sched);
        }

        let f_cell = Cell::new(f_cell.take());
        let handles = Cell::new(handles);
        let on_exit: ~fn(bool) = |exit_status| {
            let mut handles = handles.take();
            // Tell schedulers to exit
            for handles.mut_iter().advance |handle| {
                handle.send(Shutdown);
            }

            rtassert!(exit_status);
        };
        let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool,
                                        f_cell.take());
        main_task.on_exit = Some(on_exit);
        scheds[0].enqueue_task(main_task);

        let mut threads = ~[];

        while !scheds.is_empty() {
            let sched = scheds.pop();
            let sched_cell = Cell::new(sched);
            let thread = do Thread::start {
                let sched = sched_cell.take();
                sched.run();
            };

            threads.push(thread);
        }

        // Wait for schedulers
        let _threads = threads;
    }

}

/// Test tasks will abort on failure instead of unwinding
pub fn spawntask(f: ~fn()) {
    use super::sched::*;
    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        rtdebug!("spawntask taking the scheduler from TLS");

        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool, f.take())
        }
    };

    rtdebug!("new task pointer: %x", to_uint(task));

    let sched = Local::take::<Scheduler>();
    rtdebug!("spawntask scheduling the new task");
    sched.schedule_task(task);
}

/// Create a new task and run it right now. Aborts on failure
pub fn spawntask_immediately(f: ~fn()) {
    use super::sched::*;

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())
        }
    };

    let sched = Local::take::<Scheduler>();
    do sched.switch_running_tasks_and_then(task) |sched, task| {
        sched.enqueue_task(task);
    }
}

/// Create a new task and run it right now. Aborts on failure
pub fn spawntask_later(f: ~fn()) {
    use super::sched::*;
    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool, f.take())
        }
    };

    let mut sched = Local::take::<Scheduler>();
    sched.enqueue_task(task);
    Local::put(sched);
}

/// Spawn a task and either run it immediately or run it later
pub fn spawntask_random(f: ~fn()) {
    use super::sched::*;
    use rand::{Rand, rng};

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())

        }
    };

    let mut sched = Local::take::<Scheduler>();

    let mut rng = rng();
    let run_now: bool = Rand::rand(&mut rng);

    if run_now {
        do sched.switch_running_tasks_and_then(task) |sched, task| {
            sched.enqueue_task(task);
        }
    } else {
        sched.enqueue_task(task);
        Local::put(sched);
    }
}

/// Spawn a task, with the current scheduler as home, and queue it to
/// run later.
pub fn spawntask_homed(scheds: &mut ~[~Scheduler], f: ~fn()) {
    use super::sched::*;
    use rand::{rng, RngUtil};
    let mut rng = rng();

    let task = {
        let sched = &mut scheds[rng.gen_int_range(0,scheds.len() as int)];
        let handle = sched.make_handle();
        let home_id = handle.sched_id;

        // now that we know where this is going, build a new function
        // that can assert it is in the right place
        let af: ~fn() = || {
            do Local::borrow::<Scheduler,()>() |sched| {
                rtdebug!("home_id: %u, runtime loc: %u",
                         home_id,
                         sched.sched_id());
                assert!(home_id == sched.sched_id());
            };
            f()
        };

        ~Task::new_root_homed(&mut sched.stack_pool,
                              Sched(handle),
                              af)
    };
    let dest_sched = &mut scheds[rng.gen_int_range(0,scheds.len() as int)];
    // enqueue it for future execution
    dest_sched.enqueue_task(task);
}

/// Spawn a task and wait for it to finish, returning whether it
/// completed successfully or failed
pub fn spawntask_try(f: ~fn()) -> Result<(), ()> {
    use cell::Cell;
    use super::sched::*;

    let f = Cell::new(f);

    let (port, chan) = oneshot();
    let chan = Cell::new(chan);
    let on_exit: ~fn(bool) = |exit_status| chan.take().send(exit_status);
    let mut new_task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task> |_running_task| {

            // I don't understand why using a child task here fails. I
            // think the fail status is propogating back up the task
            // tree and triggering a fail for the parent, which we
            // aren't correctly expecting.

            // ~running_task.new_child(&mut (*sched).stack_pool,
            ~Task::new_root(&mut (*sched).stack_pool,
                           f.take())
        }
    };
    new_task.on_exit = Some(on_exit);

    let sched = Local::take::<Scheduler>();
    do sched.switch_running_tasks_and_then(new_task) |sched, old_task| {
        sched.enqueue_task(old_task);
    }

    rtdebug!("enqueued the new task, now waiting on exit_status");

    let exit_status = port.recv();
    if exit_status { Ok(()) } else { Err(()) }
}

// Spawn a new task in a new scheduler and return a thread handle.
pub fn spawntask_thread(f: ~fn()) -> Thread {
    use rt::sched::*;

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())
        }
    };

    let task = Cell::new(task);

    let thread = do Thread::start {
        let mut sched = ~new_test_uv_sched();
        sched.enqueue_task(task.take());
        sched.run();
    };
    return thread;
}

/// Get a port number, starting at 9600, for use in tests
pub fn next_test_port() -> u16 {
    unsafe {
        return rust_dbg_next_port(base_port() as libc::uintptr_t) as u16;
    }
    extern {
        fn rust_dbg_next_port(base: libc::uintptr_t) -> libc::uintptr_t;
    }
}

/// Get a unique IPv4 localhost:port pair starting at 9600
pub fn next_test_ip4() -> IpAddr {
    Ipv4(127, 0, 0, 1, next_test_port())
}

/// Get a unique IPv6 localhost:port pair starting at 9600
pub fn next_test_ip6() -> IpAddr {
    Ipv6(0, 0, 0, 0, 0, 0, 0, 1, next_test_port())
}

/*
XXX: Welcome to MegaHack City.

The bots run multiple builds at the same time, and these builds
all want to use ports. This function figures out which workspace
it is running in and assigns a port range based on it.
*/
fn base_port() -> uint {
    use os;
    use str::StrSlice;
    use to_str::ToStr;
    use vec::ImmutableVector;

    let base = 9600u;
    let range = 1000;

    let bases = [
        ("32-opt", base + range * 1),
        ("32-noopt", base + range * 2),
        ("64-opt", base + range * 3),
        ("64-noopt", base + range * 4),
        ("64-opt-vg", base + range * 5),
        ("all-opt", base + range * 6),
        ("snap3", base + range * 7),
        ("dist", base + range * 8)
    ];

    let path = os::getcwd().to_str();

    let mut final_base = base;

    for bases.iter().advance |&(dir, base)| {
        if path.contains(dir) {
            final_base = base;
            break;
        }
    }

    return final_base;
}

/// Get a constant that represents the number of times to repeat
/// stress tests. Default 1.
pub fn stress_factor() -> uint {
    use os::getenv;

    match getenv("RUST_RT_STRESS") {
        Some(val) => uint::from_str(val).get(),
        None => 1
    }
}
<commit_msg>auto merge of #7855 : brson/rust/rt-overcommit, r=pcwalton<commit_after>// Copyright 2013 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.

use libc;
use uint;
use option::{Some, None};
use cell::Cell;
use clone::Clone;
use container::Container;
use iterator::IteratorUtil;
use vec::{OwnedVector, MutableVector};
use super::io::net::ip::{IpAddr, Ipv4, Ipv6};
use rt::sched::Scheduler;
use rt::local::Local;
use unstable::run_in_bare_thread;
use rt::thread::Thread;
use rt::task::Task;
use rt::uv::uvio::UvEventLoop;
use rt::work_queue::WorkQueue;
use rt::sleeper_list::SleeperList;
use rt::task::{Sched};
use rt::comm::oneshot;
use result::{Result, Ok, Err};

pub fn new_test_uv_sched() -> Scheduler {

    let mut sched = Scheduler::new(~UvEventLoop::new(),
                                   WorkQueue::new(),
                                   SleeperList::new());
    // Don't wait for the Shutdown message
    sched.no_sleep = true;
    return sched;
}

/// Creates a new scheduler in a new thread and runs a task in it,
/// then waits for the scheduler to exit. Failure of the task
/// will abort the process.
pub fn run_in_newsched_task(f: ~fn()) {
    let f = Cell::new(f);

    do run_in_bare_thread {
        let mut sched = ~new_test_uv_sched();
        let on_exit: ~fn(bool) = |exit_status| rtassert!(exit_status);
        let mut task = ~Task::new_root(&mut sched.stack_pool,
                                       f.take());
        rtdebug!("newsched_task: %x", to_uint(task));
        task.on_exit = Some(on_exit);
        sched.enqueue_task(task);
        sched.run();
    }
}

/// Create more than one scheduler and run a function in a task
/// in one of the schedulers. The schedulers will stay alive
/// until the function `f` returns.
pub fn run_in_mt_newsched_task(f: ~fn()) {
    use os;
    use from_str::FromStr;
    use rt::sched::Shutdown;

    let f_cell = Cell::new(f);

    do run_in_bare_thread {
        let nthreads = match os::getenv("RUST_RT_TEST_THREADS") {
            Some(nstr) => FromStr::from_str(nstr).get(),
            None => {
                // A reasonable number of threads for testing
                // multithreading. NB: It's easy to exhaust OS X's
                // low maximum fd limit by setting this too high (#7772)
                4
            }
        };

        let sleepers = SleeperList::new();
        let work_queue = WorkQueue::new();

        let mut handles = ~[];
        let mut scheds = ~[];

        for uint::range(0, nthreads) |_| {
            let loop_ = ~UvEventLoop::new();
            let mut sched = ~Scheduler::new(loop_,
                                            work_queue.clone(),
                                            sleepers.clone());
            let handle = sched.make_handle();

            handles.push(handle);
            scheds.push(sched);
        }

        let f_cell = Cell::new(f_cell.take());
        let handles = Cell::new(handles);
        let on_exit: ~fn(bool) = |exit_status| {
            let mut handles = handles.take();
            // Tell schedulers to exit
            for handles.mut_iter().advance |handle| {
                handle.send(Shutdown);
            }

            rtassert!(exit_status);
        };
        let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool,
                                        f_cell.take());
        main_task.on_exit = Some(on_exit);
        scheds[0].enqueue_task(main_task);

        let mut threads = ~[];

        while !scheds.is_empty() {
            let sched = scheds.pop();
            let sched_cell = Cell::new(sched);
            let thread = do Thread::start {
                let sched = sched_cell.take();
                sched.run();
            };

            threads.push(thread);
        }

        // Wait for schedulers
        let _threads = threads;
    }

}

/// Test tasks will abort on failure instead of unwinding
pub fn spawntask(f: ~fn()) {
    use super::sched::*;
    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        rtdebug!("spawntask taking the scheduler from TLS");

        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool, f.take())
        }
    };

    rtdebug!("new task pointer: %x", to_uint(task));

    let sched = Local::take::<Scheduler>();
    rtdebug!("spawntask scheduling the new task");
    sched.schedule_task(task);
}

/// Create a new task and run it right now. Aborts on failure
pub fn spawntask_immediately(f: ~fn()) {
    use super::sched::*;

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())
        }
    };

    let sched = Local::take::<Scheduler>();
    do sched.switch_running_tasks_and_then(task) |sched, task| {
        sched.enqueue_task(task);
    }
}

/// Create a new task and run it right now. Aborts on failure
pub fn spawntask_later(f: ~fn()) {
    use super::sched::*;
    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool, f.take())
        }
    };

    let mut sched = Local::take::<Scheduler>();
    sched.enqueue_task(task);
    Local::put(sched);
}

/// Spawn a task and either run it immediately or run it later
pub fn spawntask_random(f: ~fn()) {
    use super::sched::*;
    use rand::{Rand, rng};

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())

        }
    };

    let mut sched = Local::take::<Scheduler>();

    let mut rng = rng();
    let run_now: bool = Rand::rand(&mut rng);

    if run_now {
        do sched.switch_running_tasks_and_then(task) |sched, task| {
            sched.enqueue_task(task);
        }
    } else {
        sched.enqueue_task(task);
        Local::put(sched);
    }
}

/// Spawn a task, with the current scheduler as home, and queue it to
/// run later.
pub fn spawntask_homed(scheds: &mut ~[~Scheduler], f: ~fn()) {
    use super::sched::*;
    use rand::{rng, RngUtil};
    let mut rng = rng();

    let task = {
        let sched = &mut scheds[rng.gen_int_range(0,scheds.len() as int)];
        let handle = sched.make_handle();
        let home_id = handle.sched_id;

        // now that we know where this is going, build a new function
        // that can assert it is in the right place
        let af: ~fn() = || {
            do Local::borrow::<Scheduler,()>() |sched| {
                rtdebug!("home_id: %u, runtime loc: %u",
                         home_id,
                         sched.sched_id());
                assert!(home_id == sched.sched_id());
            };
            f()
        };

        ~Task::new_root_homed(&mut sched.stack_pool,
                              Sched(handle),
                              af)
    };
    let dest_sched = &mut scheds[rng.gen_int_range(0,scheds.len() as int)];
    // enqueue it for future execution
    dest_sched.enqueue_task(task);
}

/// Spawn a task and wait for it to finish, returning whether it
/// completed successfully or failed
pub fn spawntask_try(f: ~fn()) -> Result<(), ()> {
    use cell::Cell;
    use super::sched::*;

    let f = Cell::new(f);

    let (port, chan) = oneshot();
    let chan = Cell::new(chan);
    let on_exit: ~fn(bool) = |exit_status| chan.take().send(exit_status);
    let mut new_task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task> |_running_task| {

            // I don't understand why using a child task here fails. I
            // think the fail status is propogating back up the task
            // tree and triggering a fail for the parent, which we
            // aren't correctly expecting.

            // ~running_task.new_child(&mut (*sched).stack_pool,
            ~Task::new_root(&mut (*sched).stack_pool,
                           f.take())
        }
    };
    new_task.on_exit = Some(on_exit);

    let sched = Local::take::<Scheduler>();
    do sched.switch_running_tasks_and_then(new_task) |sched, old_task| {
        sched.enqueue_task(old_task);
    }

    rtdebug!("enqueued the new task, now waiting on exit_status");

    let exit_status = port.recv();
    if exit_status { Ok(()) } else { Err(()) }
}

// Spawn a new task in a new scheduler and return a thread handle.
pub fn spawntask_thread(f: ~fn()) -> Thread {
    use rt::sched::*;

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())
        }
    };

    let task = Cell::new(task);

    let thread = do Thread::start {
        let mut sched = ~new_test_uv_sched();
        sched.enqueue_task(task.take());
        sched.run();
    };
    return thread;
}

/// Get a port number, starting at 9600, for use in tests
pub fn next_test_port() -> u16 {
    unsafe {
        return rust_dbg_next_port(base_port() as libc::uintptr_t) as u16;
    }
    extern {
        fn rust_dbg_next_port(base: libc::uintptr_t) -> libc::uintptr_t;
    }
}

/// Get a unique IPv4 localhost:port pair starting at 9600
pub fn next_test_ip4() -> IpAddr {
    Ipv4(127, 0, 0, 1, next_test_port())
}

/// Get a unique IPv6 localhost:port pair starting at 9600
pub fn next_test_ip6() -> IpAddr {
    Ipv6(0, 0, 0, 0, 0, 0, 0, 1, next_test_port())
}

/*
XXX: Welcome to MegaHack City.

The bots run multiple builds at the same time, and these builds
all want to use ports. This function figures out which workspace
it is running in and assigns a port range based on it.
*/
fn base_port() -> uint {
    use os;
    use str::StrSlice;
    use to_str::ToStr;
    use vec::ImmutableVector;

    let base = 9600u;
    let range = 1000;

    let bases = [
        ("32-opt", base + range * 1),
        ("32-noopt", base + range * 2),
        ("64-opt", base + range * 3),
        ("64-noopt", base + range * 4),
        ("64-opt-vg", base + range * 5),
        ("all-opt", base + range * 6),
        ("snap3", base + range * 7),
        ("dist", base + range * 8)
    ];

    let path = os::getcwd().to_str();

    let mut final_base = base;

    for bases.iter().advance |&(dir, base)| {
        if path.contains(dir) {
            final_base = base;
            break;
        }
    }

    return final_base;
}

/// Get a constant that represents the number of times to repeat
/// stress tests. Default 1.
pub fn stress_factor() -> uint {
    use os::getenv;

    match getenv("RUST_RT_STRESS") {
        Some(val) => uint::from_str(val).get(),
        None => 1
    }
}
<|endoftext|>


<commit_before>
extern crate ndarray;

use ndarray::{Array, Dimension};

#[test]
fn broadcast_1()
{
    let a_dim = (2, 4, 2, 2);
    let b_dim = (2, 1, 2, 1);
    let a = Array::range(0.0, a_dim.size() as f32).reshape(a_dim);
    let b = Array::range(0.0, b_dim.size() as f32).reshape(b_dim);
    assert!(b.broadcast_iter(a.dim()).is_some());

    let c_dim = (2, 1);
    let c = Array::range(0.0, c_dim.size() as f32).reshape(c_dim);
    assert!(c.broadcast_iter(1).is_none());
    assert!(c.broadcast_iter(()).is_none());
    assert!(c.broadcast_iter((2, 1)).is_some());
    assert!(c.broadcast_iter((2, 2)).is_some());
    assert!(c.broadcast_iter((32, 2, 1)).is_some());
    assert!(c.broadcast_iter((32, 1, 2)).is_none());

    /* () can be broadcast to anything */
    let z = Array::<f32,_>::zeros(());
    assert!(z.broadcast_iter(()).is_some());
    assert!(z.broadcast_iter(1).is_some());
    assert!(z.broadcast_iter(3).is_some());
    assert!(z.broadcast_iter((7,2,9)).is_some());
}

#[test]
fn test_add()
{
    let a_dim = (2, 4, 2, 2);
    let b_dim = (2, 1, 2, 1);
    let mut a = Array::range(0.0, a_dim.size() as f32).reshape(a_dim);
    let b = Array::range(0.0, b_dim.size() as f32).reshape(b_dim);
    a.iadd(&b);
    let t = Array::from_elem((), 1.0f32);
    a.iadd(&t);
}

#[test] #[should_fail]
fn test_add_incompat()
{
    let a_dim = (2, 4, 2, 2);
    let mut a = Array::range(0.0, a_dim.size() as f32).reshape(a_dim);
    let incompat = Array::from_elem(3, 1.0f32);
    a.iadd(&incompat);
}
<commit_msg>Fix should_fail → should_panic<commit_after>
extern crate ndarray;

use ndarray::{Array, Dimension};

#[test]
fn broadcast_1()
{
    let a_dim = (2, 4, 2, 2);
    let b_dim = (2, 1, 2, 1);
    let a = Array::range(0.0, a_dim.size() as f32).reshape(a_dim);
    let b = Array::range(0.0, b_dim.size() as f32).reshape(b_dim);
    assert!(b.broadcast_iter(a.dim()).is_some());

    let c_dim = (2, 1);
    let c = Array::range(0.0, c_dim.size() as f32).reshape(c_dim);
    assert!(c.broadcast_iter(1).is_none());
    assert!(c.broadcast_iter(()).is_none());
    assert!(c.broadcast_iter((2, 1)).is_some());
    assert!(c.broadcast_iter((2, 2)).is_some());
    assert!(c.broadcast_iter((32, 2, 1)).is_some());
    assert!(c.broadcast_iter((32, 1, 2)).is_none());

    /* () can be broadcast to anything */
    let z = Array::<f32,_>::zeros(());
    assert!(z.broadcast_iter(()).is_some());
    assert!(z.broadcast_iter(1).is_some());
    assert!(z.broadcast_iter(3).is_some());
    assert!(z.broadcast_iter((7,2,9)).is_some());
}

#[test]
fn test_add()
{
    let a_dim = (2, 4, 2, 2);
    let b_dim = (2, 1, 2, 1);
    let mut a = Array::range(0.0, a_dim.size() as f32).reshape(a_dim);
    let b = Array::range(0.0, b_dim.size() as f32).reshape(b_dim);
    a.iadd(&b);
    let t = Array::from_elem((), 1.0f32);
    a.iadd(&t);
}

#[test] #[should_panic]
fn test_add_incompat()
{
    let a_dim = (2, 4, 2, 2);
    let mut a = Array::range(0.0, a_dim.size() as f32).reshape(a_dim);
    let incompat = Array::from_elem(3, 1.0f32);
    a.iadd(&incompat);
}
<|endoftext|>


<commit_before>//! Yet more cli test cases. These are testing that the output
//! is exactly as expected.

extern crate rustup_dist;
extern crate rustup_mock;
extern crate tempdir;
extern crate rustup_utils;

use rustup_mock::clitools::{self, Config, Scenario,
                               expect_ok, expect_ok_ex,
                               expect_err_ex,
                               this_host_triple, change_dir};
use std::env;

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

fn setup(f: &Fn(&Config)) {
    clitools::setup(Scenario::SimpleV2, f);
}

#[test]
fn update() {
    setup(&|config| {
        expect_ok_ex(config, &["rustup", "update", "nightly"],
for_host!(r"
  nightly-{0} installed - 1.3.0 (hash-n-2)

"),
for_host!(r"info: syncing channel updates for 'nightly-{0}'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'cargo'
info: downloading component 'rust-docs'
info: installing component 'rust-std'
info: installing component 'rustc'
info: installing component 'cargo'
info: installing component 'rust-docs'
"));
    });
}

#[test]
fn update_again() {
    setup(&|config| {
        expect_ok(config, &["rustup", "update", "nightly"]);
        expect_ok_ex(config, &["rustup", "update", "nightly"],
for_host!(r"
  nightly-{0} unchanged - 1.3.0 (hash-n-2)

"),
for_host!(r"info: syncing channel updates for 'nightly-{0}'
"));
    });
}

#[test]
fn default() {
    setup(&|config| {
        expect_ok_ex(config, &["rustup", "default", "nightly"],
for_host!(r"
  nightly-{0} installed - 1.3.0 (hash-n-2)

"),
for_host!(r"info: syncing channel updates for 'nightly-{0}'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'cargo'
info: downloading component 'rust-docs'
info: installing component 'rust-std'
info: installing component 'rustc'
info: installing component 'cargo'
info: installing component 'rust-docs'
info: default toolchain set to 'nightly-{0}'
"));
    });
}

#[test]
fn override_again() {
    setup(&|config| {
        let cwd = env::current_dir().unwrap();
        expect_ok(config, &["rustup", "override", "add", "nightly"]);
        expect_ok_ex(config, &["rustup", "override", "add", "nightly"],
for_host!(r"
  nightly-{} unchanged - 1.3.0 (hash-n-2)

"),
&format!(
r"info: using existing install for 'nightly-{1}'
info: override toolchain for '{}' set to 'nightly-{1}'
", cwd.display(), &this_host_triple()));
    });
}

#[test]
fn remove_override() {
    for keyword in &["remove", "unset"] {
        setup(&|config| {
            let cwd = env::current_dir().unwrap();
            expect_ok(config, &["rustup", "override", "add", "nightly"]);
            expect_ok_ex(config, &["rustup", "override", keyword],
                         r"",
                         &format!("info: override toolchain for '{}' removed\n", cwd.display()));
        });

    }
}

#[test]
fn remove_override_none() {
    for keyword in &["remove", "unset"] {
        setup(&|config| {
            let cwd = env::current_dir().unwrap();
            expect_ok_ex(config, &["rustup", "override", keyword],
                         r"",
                         &format!("info: no override toolchain for '{}'
info: you may use `--path <path>` option to remove override toolchain for a specific path\n",
                                  cwd.display()));
        });
    }
}

#[test]
fn remove_override_with_path() {
    for keyword in &["remove", "unset"] {
        setup(&|config| {
            let dir = tempdir::TempDir::new("rustup-test").unwrap();
            change_dir(dir.path(), &|| {
                expect_ok(config, &["rustup", "override", "add", "nightly"]);
            });
            expect_ok_ex(config, &["rustup", "override", keyword, "--path", dir.path().to_str().unwrap()],
                         r"",
                         &format!("info: override toolchain for '{}' removed\n", dir.path().display()));
        });

    }
}

#[test]
fn remove_override_with_path_deleted() {
    for keyword in &["remove", "unset"] {
        setup(&|config| {
            let path = {
                let dir = tempdir::TempDir::new("rustup-test").unwrap();
                let path = std::fs::canonicalize(dir.path()).unwrap();
                change_dir(&path, &|| {
                  expect_ok(config, &["rustup", "override", "add", "nightly"]);
                });
              path
            };
            expect_ok_ex(config, &["rustup", "override", keyword, "--path", path.to_str().unwrap()],
                         r"",
                         &format!("info: override toolchain for '{}' removed\n", path.display()));
        });
    }
}

#[test]
fn remove_override_nonexistent() {
    for keyword in &["remove", "unset"] {
        setup(&|config| {
            let path = {
                let dir = tempdir::TempDir::new("rustup-test").unwrap();
                let path = std::fs::canonicalize(dir.path()).unwrap();
                change_dir(&path, &|| {
                  expect_ok(config, &["rustup", "override", "add", "nightly"]);
                });
                path
            };
            // FIXME TempDir seems to succumb to difficulties removing dirs on windows
            let _ = rustup_utils::raw::remove_dir(&path);
            assert!(!path.exists());
            expect_ok_ex(config, &["rustup", "override", keyword, "--nonexistent"],
                         r"",
                         &format!("info: override toolchain for '{}' removed\n", path.display()));
        });
    }
}

#[test]
fn list_overrides() {
    setup(&|config| {
        let cwd = std::fs::canonicalize(env::current_dir().unwrap()).unwrap();
        let mut cwd_formatted = format!("{}", cwd.display()).to_string();

        if cfg!(windows) {
            cwd_formatted = cwd_formatted[4..].to_owned();
        }

        let trip = this_host_triple();
        expect_ok(config, &["rustup", "override", "add", "nightly"]);
        expect_ok_ex(config, &["rustup", "override", "list"],
                     &format!("{:<40}\t{:<20}\n", cwd_formatted, &format!("nightly-{}", trip)), r"");
    });
}

#[test]
fn list_overrides_with_nonexistent() {
    setup(&|config| {

        let trip = this_host_triple();

        let nonexistent_path = {
            let dir = tempdir::TempDir::new("rustup-test").unwrap();
            change_dir(dir.path(), &|| {
                expect_ok(config, &["rustup", "override", "add", "nightly"]);
            });
            std::fs::canonicalize(dir.path()).unwrap()
        };
        // FIXME TempDir seems to succumb to difficulties removing dirs on windows
        let _ = rustup_utils::raw::remove_dir(&nonexistent_path);
        assert!(!nonexistent_path.exists());
        let mut path_formatted = format!("{}", nonexistent_path.display()).to_string();

        if cfg!(windows) {
            path_formatted = path_formatted[4..].to_owned();
        }

        expect_ok_ex(config, &["rustup", "override", "list"],
                     &format!("{:<40}\t{:<20}\n\n",
                              path_formatted + " (not a directory)",
                              &format!("nightly-{}", trip)),
                              "info: you may remove overrides for non-existent directories with
`rustup override unset --nonexistent`\n");
    });
}

#[test]
fn update_no_manifest() {
    setup(&|config| {
        expect_err_ex(config, &["rustup", "update", "nightly-2016-01-01"],
r"",
for_host!(r"info: syncing channel updates for 'nightly-2016-01-01-{0}'
error: no release found for 'nightly-2016-01-01'
"));
    });
}

// Issue #111
#[test]
fn update_invalid_toolchain() {
   setup(&|config| {
        expect_err_ex(config, &["rustup", "update", "nightly-2016-03-1"],
r"",
r"info: syncing channel updates for 'nightly-2016-03-1'
error: target not found: '2016-03-1'
");
   });
 }

#[test]
fn default_invalid_toolchain() {
   setup(&|config| {
        expect_err_ex(config, &["rustup", "default", "nightly-2016-03-1"],
r"",
r"info: syncing channel updates for 'nightly-2016-03-1'
error: target not found: '2016-03-1'
");
   });
}

#[test]
fn list_targets() {
    setup(&|config| {
        let trip = this_host_triple();
        let mut sorted = vec![format!("{} (default)", &*trip),
                              format!("{} (installed)", clitools::CROSS_ARCH1),
                              clitools::CROSS_ARCH2.to_string()];
        sorted.sort();

        let expected = format!("{}\n{}\n{}\n", sorted[0], sorted[1], sorted[2]);

        expect_ok(config, &["rustup", "default", "nightly"]);
        expect_ok(config, &["rustup", "target", "add",
                            clitools::CROSS_ARCH1]);
        expect_ok_ex(config, &["rustup", "target", "list"],
&expected,
r"");
    });
}

#[test]
fn cross_install_indicates_target() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "nightly"]);
        expect_ok_ex(config, &["rustup", "target", "add", clitools::CROSS_ARCH1],
r"",
&format!(r"info: downloading component 'rust-std' for '{0}'
info: installing component 'rust-std' for '{0}'
", clitools::CROSS_ARCH1));
    });
}

#[test]
fn enable_telemetry() {
    setup(&|config| {
        expect_ok_ex(config,
                     &["rustup", "telemetry", "enable"],
                     r"",
                     "info: telemetry set to 'on'\n");
    });
}

#[test]
fn disable_telemetry() {
    setup(&|config| {
        expect_ok_ex(config,
                     &["rustup", "telemetry", "disable"],
                     r"",
                     "info: telemetry set to 'off'\n");
    });
}

// issue #927
#[test]
fn undefined_linked_toolchain() {
    setup(&|config| {
        expect_err_ex(config,
                      &["cargo", "+bogus", "test"],
                      r"",
                      &format!("error: toolchain 'bogus' is not installed\n"));
    });
}
<commit_msg>Auto merge of #1105 - brson:ignore, r=Diggsey<commit_after>//! Yet more cli test cases. These are testing that the output
//! is exactly as expected.

extern crate rustup_dist;
extern crate rustup_mock;
extern crate tempdir;
extern crate rustup_utils;

use rustup_mock::clitools::{self, Config, Scenario,
                               expect_ok, expect_ok_ex,
                               expect_err_ex,
                               this_host_triple, change_dir};
use std::env;

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

fn setup(f: &Fn(&Config)) {
    clitools::setup(Scenario::SimpleV2, f);
}

#[test]
fn update() {
    setup(&|config| {
        expect_ok_ex(config, &["rustup", "update", "nightly"],
for_host!(r"
  nightly-{0} installed - 1.3.0 (hash-n-2)

"),
for_host!(r"info: syncing channel updates for 'nightly-{0}'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'cargo'
info: downloading component 'rust-docs'
info: installing component 'rust-std'
info: installing component 'rustc'
info: installing component 'cargo'
info: installing component 'rust-docs'
"));
    });
}

#[test]
fn update_again() {
    setup(&|config| {
        expect_ok(config, &["rustup", "update", "nightly"]);
        expect_ok_ex(config, &["rustup", "update", "nightly"],
for_host!(r"
  nightly-{0} unchanged - 1.3.0 (hash-n-2)

"),
for_host!(r"info: syncing channel updates for 'nightly-{0}'
"));
    });
}

#[test]
fn default() {
    setup(&|config| {
        expect_ok_ex(config, &["rustup", "default", "nightly"],
for_host!(r"
  nightly-{0} installed - 1.3.0 (hash-n-2)

"),
for_host!(r"info: syncing channel updates for 'nightly-{0}'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'cargo'
info: downloading component 'rust-docs'
info: installing component 'rust-std'
info: installing component 'rustc'
info: installing component 'cargo'
info: installing component 'rust-docs'
info: default toolchain set to 'nightly-{0}'
"));
    });
}

#[test]
fn override_again() {
    setup(&|config| {
        let cwd = env::current_dir().unwrap();
        expect_ok(config, &["rustup", "override", "add", "nightly"]);
        expect_ok_ex(config, &["rustup", "override", "add", "nightly"],
for_host!(r"
  nightly-{} unchanged - 1.3.0 (hash-n-2)

"),
&format!(
r"info: using existing install for 'nightly-{1}'
info: override toolchain for '{}' set to 'nightly-{1}'
", cwd.display(), &this_host_triple()));
    });
}

#[test]
fn remove_override() {
    for keyword in &["remove", "unset"] {
        setup(&|config| {
            let cwd = env::current_dir().unwrap();
            expect_ok(config, &["rustup", "override", "add", "nightly"]);
            expect_ok_ex(config, &["rustup", "override", keyword],
                         r"",
                         &format!("info: override toolchain for '{}' removed\n", cwd.display()));
        });

    }
}

#[test]
fn remove_override_none() {
    for keyword in &["remove", "unset"] {
        setup(&|config| {
            let cwd = env::current_dir().unwrap();
            expect_ok_ex(config, &["rustup", "override", keyword],
                         r"",
                         &format!("info: no override toolchain for '{}'
info: you may use `--path <path>` option to remove override toolchain for a specific path\n",
                                  cwd.display()));
        });
    }
}

#[test]
fn remove_override_with_path() {
    for keyword in &["remove", "unset"] {
        setup(&|config| {
            let dir = tempdir::TempDir::new("rustup-test").unwrap();
            change_dir(dir.path(), &|| {
                expect_ok(config, &["rustup", "override", "add", "nightly"]);
            });
            expect_ok_ex(config, &["rustup", "override", keyword, "--path", dir.path().to_str().unwrap()],
                         r"",
                         &format!("info: override toolchain for '{}' removed\n", dir.path().display()));
        });

    }
}

#[test]
fn remove_override_with_path_deleted() {
    for keyword in &["remove", "unset"] {
        setup(&|config| {
            let path = {
                let dir = tempdir::TempDir::new("rustup-test").unwrap();
                let path = std::fs::canonicalize(dir.path()).unwrap();
                change_dir(&path, &|| {
                  expect_ok(config, &["rustup", "override", "add", "nightly"]);
                });
              path
            };
            expect_ok_ex(config, &["rustup", "override", keyword, "--path", path.to_str().unwrap()],
                         r"",
                         &format!("info: override toolchain for '{}' removed\n", path.display()));
        });
    }
}

#[test]
#[cfg_attr(target_os = "windows", ignore)] // FIXME #1103
fn remove_override_nonexistent() {
    for keyword in &["remove", "unset"] {
        setup(&|config| {
            let path = {
                let dir = tempdir::TempDir::new("rustup-test").unwrap();
                let path = std::fs::canonicalize(dir.path()).unwrap();
                change_dir(&path, &|| {
                  expect_ok(config, &["rustup", "override", "add", "nightly"]);
                });
                path
            };
            // FIXME TempDir seems to succumb to difficulties removing dirs on windows
            let _ = rustup_utils::raw::remove_dir(&path);
            assert!(!path.exists());
            expect_ok_ex(config, &["rustup", "override", keyword, "--nonexistent"],
                         r"",
                         &format!("info: override toolchain for '{}' removed\n", path.display()));
        });
    }
}

#[test]
fn list_overrides() {
    setup(&|config| {
        let cwd = std::fs::canonicalize(env::current_dir().unwrap()).unwrap();
        let mut cwd_formatted = format!("{}", cwd.display()).to_string();

        if cfg!(windows) {
            cwd_formatted = cwd_formatted[4..].to_owned();
        }

        let trip = this_host_triple();
        expect_ok(config, &["rustup", "override", "add", "nightly"]);
        expect_ok_ex(config, &["rustup", "override", "list"],
                     &format!("{:<40}\t{:<20}\n", cwd_formatted, &format!("nightly-{}", trip)), r"");
    });
}

#[test]
fn list_overrides_with_nonexistent() {
    setup(&|config| {

        let trip = this_host_triple();

        let nonexistent_path = {
            let dir = tempdir::TempDir::new("rustup-test").unwrap();
            change_dir(dir.path(), &|| {
                expect_ok(config, &["rustup", "override", "add", "nightly"]);
            });
            std::fs::canonicalize(dir.path()).unwrap()
        };
        // FIXME TempDir seems to succumb to difficulties removing dirs on windows
        let _ = rustup_utils::raw::remove_dir(&nonexistent_path);
        assert!(!nonexistent_path.exists());
        let mut path_formatted = format!("{}", nonexistent_path.display()).to_string();

        if cfg!(windows) {
            path_formatted = path_formatted[4..].to_owned();
        }

        expect_ok_ex(config, &["rustup", "override", "list"],
                     &format!("{:<40}\t{:<20}\n\n",
                              path_formatted + " (not a directory)",
                              &format!("nightly-{}", trip)),
                              "info: you may remove overrides for non-existent directories with
`rustup override unset --nonexistent`\n");
    });
}

#[test]
fn update_no_manifest() {
    setup(&|config| {
        expect_err_ex(config, &["rustup", "update", "nightly-2016-01-01"],
r"",
for_host!(r"info: syncing channel updates for 'nightly-2016-01-01-{0}'
error: no release found for 'nightly-2016-01-01'
"));
    });
}

// Issue #111
#[test]
fn update_invalid_toolchain() {
   setup(&|config| {
        expect_err_ex(config, &["rustup", "update", "nightly-2016-03-1"],
r"",
r"info: syncing channel updates for 'nightly-2016-03-1'
error: target not found: '2016-03-1'
");
   });
 }

#[test]
fn default_invalid_toolchain() {
   setup(&|config| {
        expect_err_ex(config, &["rustup", "default", "nightly-2016-03-1"],
r"",
r"info: syncing channel updates for 'nightly-2016-03-1'
error: target not found: '2016-03-1'
");
   });
}

#[test]
fn list_targets() {
    setup(&|config| {
        let trip = this_host_triple();
        let mut sorted = vec![format!("{} (default)", &*trip),
                              format!("{} (installed)", clitools::CROSS_ARCH1),
                              clitools::CROSS_ARCH2.to_string()];
        sorted.sort();

        let expected = format!("{}\n{}\n{}\n", sorted[0], sorted[1], sorted[2]);

        expect_ok(config, &["rustup", "default", "nightly"]);
        expect_ok(config, &["rustup", "target", "add",
                            clitools::CROSS_ARCH1]);
        expect_ok_ex(config, &["rustup", "target", "list"],
&expected,
r"");
    });
}

#[test]
fn cross_install_indicates_target() {
    setup(&|config| {
        expect_ok(config, &["rustup", "default", "nightly"]);
        expect_ok_ex(config, &["rustup", "target", "add", clitools::CROSS_ARCH1],
r"",
&format!(r"info: downloading component 'rust-std' for '{0}'
info: installing component 'rust-std' for '{0}'
", clitools::CROSS_ARCH1));
    });
}

#[test]
fn enable_telemetry() {
    setup(&|config| {
        expect_ok_ex(config,
                     &["rustup", "telemetry", "enable"],
                     r"",
                     "info: telemetry set to 'on'\n");
    });
}

#[test]
fn disable_telemetry() {
    setup(&|config| {
        expect_ok_ex(config,
                     &["rustup", "telemetry", "disable"],
                     r"",
                     "info: telemetry set to 'off'\n");
    });
}

// issue #927
#[test]
fn undefined_linked_toolchain() {
    setup(&|config| {
        expect_err_ex(config,
                      &["cargo", "+bogus", "test"],
                      r"",
                      &format!("error: toolchain 'bogus' is not installed\n"));
    });
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt;

/// Data associated with a single metadata block.
#[derive(Debug)]
pub struct Metadata {
  /// Marks whether the current metadata block is the last.
  is_last: bool,
  /// The length, in bytes, of the block being parsed. This does not include
  /// the metadata block header.
  length: u32,
  /// Block data containing one of the eight different types of metadata.
  pub data: Data,
}

/// An enum that represents a metadata block type.
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Type {
  /// Represents the current block is stream information.
  StreamInfo,
  /// Represents the current block is padding.
  Padding,
  /// Represents the current block is application data.
  Application,
  /// Represents the current block is a seek table.
  SeekTable,
  /// Represents the current block is a vorbis comment.
  VorbisComment,
  /// Represents the current block is a cue sheet.
  CueSheet,
  /// Represents the current block is a picture.
  Picture,
  /// Represents the current block is unknow.
  Unknown,
}

macro_rules! is_block_type (
  ($name: ident, $block_type: ident) => (
    #[inline]
    pub fn $name(&self) -> bool {
      self.data_type() == Type::$block_type
    }
  );
);

impl Metadata {
  /// Constructs a new `Metadata` struct based on the arguments passed in.
  pub fn new(is_last: bool, length: u32, data: Data) -> Self {
    Metadata {
      is_last: is_last,
      length: length,
      data: data,
    }
  }

  /// Returns whether the current metadata block is the last.
  #[inline]
  pub fn is_last(&self) -> bool {
    self.is_last
  }

  /// Returns the metadata block's type.
  pub fn data_type(&self) -> Type {
    match self.data {
      Data::StreamInfo(_)    => Type::StreamInfo,
      Data::Padding(_)       => Type::Padding,
      Data::Application(_)   => Type::Application,
      Data::SeekTable(_)     => Type::SeekTable,
      Data::VorbisComment(_) => Type::VorbisComment,
      Data::CueSheet(_)      => Type::CueSheet,
      Data::Picture(_)       => Type::Picture,
      Data::Unknown(_)       => Type::Unknown,
    }
  }

  is_block_type!(is_stream_info, StreamInfo);
  is_block_type!(is_padding, Padding);
  is_block_type!(is_application, Application);
  is_block_type!(is_seek_table, SeekTable);
  is_block_type!(is_vorbis_comment, VorbisComment);
  is_block_type!(is_cue_sheet, CueSheet);
  is_block_type!(is_picture, Picture);
  is_block_type!(is_unknown, Unknown);
}

/// General enum that hold all the different metadata block data.
#[derive(Debug, PartialEq, Eq)]
pub enum Data {
  /// Information regarding the entire audio stream.
  StreamInfo(StreamInfo),
  /// Block that represents a number of padded bytes.
  Padding(u32),
  /// Data used by third-party applications.
  Application(Application),
  /// Table of multiple points to seek, or skip, to within the FLAC file.
  SeekTable(Vec<SeekPoint>),
  /// Stores human-readable name/value pairs.
  VorbisComment(VorbisComment),
  /// Stores cue information
  CueSheet(CueSheet),
  /// Stores pictures associated with the FLAC file.
  Picture(Picture),
  /// A type of block data that isn't know or doesn't match the type above.
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct StreamInfo {
  /// Minimum block size, in samples, used in the stream.
  pub min_block_size: u16,
  /// Maximum block size, in samples, used in the stream.
  pub max_block_size: u16,
  /// Minimum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub min_frame_size: u32,
  /// Maximum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub max_frame_size: u32,
  /// Sample rate in hertz (Hz).
  pub sample_rate: u32,
  /// Number of channels. FLAC supports one to eight channel.
  pub channels: u8,
  /// Bits per sample. FLAC supports four to thirty-two bits per sample.
  pub bits_per_sample: u8,
  /// Total samples in the stream. A value of zero means the number is
  /// unknown.
  pub total_samples: u64,
  /// MD5 signature of the unencoded audio data.
  pub md5_sum: [u8; 16],
}

impl StreamInfo {
  /// Constructs a zeroed out `StreamInfo` struct.
  pub fn new() -> StreamInfo {
    StreamInfo {
      min_block_size: 0,
      max_block_size: 0,
      min_frame_size: 0,
      max_frame_size: 0,
      sample_rate: 0,
      channels: 0,
      bits_per_sample: 0,
      total_samples: 0,
      md5_sum: [0; 16],
    }
  }

  /// Returns true if `min_block_size` and `max_block_size` are different,
  /// otherwise false.
  #[inline]
  pub fn is_varied_block_size(&self) -> bool {
    self.min_block_size != self.max_block_size
  }

  /// Returns true if `min_block_size` and `max_block_size` are equal,
  /// otherwise false.
  #[inline]
  pub fn is_fixed_block_size(&self) -> bool {
    self.min_block_size == self.max_block_size
  }
}

/// Data used by third-party applications.
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  /// Registered application ID.
  pub id: String,
  /// Data used by the third-party application.
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file.
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  /// Sample number of the first sample in the target frame.
  pub sample_number: u64,
  /// Byte offset of the target frame's header.
  pub stream_offset: u64,
  /// Number of samples in the target frame.
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs.
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  /// Vendor name.
  pub vendor_string: String,
  /// Comments associated with a name, or category, followed by it's
  /// contents.
  pub comments: HashMap<String, String>,
}

/// Stores cue information.
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  /// Media catalog number.
  pub media_catalog_number: String,
  /// Number of lead-in samples.
  pub lead_in: u64,
  /// Whether or not this `CueSheet` corresponds to a Compact Disc.
  pub is_cd: bool,
  /// One or more tracks.
  pub tracks: Vec<CueSheetTrack>,
}

/// Track information inside a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  /// Track offset, in samples, relative to the beginning of the FLAC audio
  /// stream.
  pub offset: u64,
  /// Track number.
  pub number: u8,
  /// Twelve digit alphanumeric code.
  pub isrc: String,
  /// Whether the cue sheet track is audio.
  pub is_audio: bool,
  /// Whether the cue sheet track is pre-emphasis.
  pub is_pre_emphasis: bool,
  /// For all tracks except the lead-out track.
  pub indices: Vec<CueSheetTrackIndex>,
}

/// An index point within a track, inside of a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  /// Offset, in samples, relative to the track offset of the index point.
  pub offset: u64,
  /// Index point number.
  pub number: u8,
}

/// Stores pictures associated with the FLAC file.
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  /// Picture type, based on the ID3v2 APIC frame.
  pub picture_type: PictureType,
  /// Multipurpose Internet Mail Extensions (MIME) type.
  pub mime_type: String,
  /// A string describing the picture.
  pub description: String,
  /// Width of the picture in pixels.
  pub width: u32,
  /// Height of the picture in pixels.
  pub height: u32,
  /// Color depth of the picture in bits-per-pixel.
  pub depth: u32,
  /// Number of colors used.
  pub colors: u32,
  /// Binary picture data.
  pub data: Vec<u8>,
}

/// The picture type according to the ID3v2 attached picture frame.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  /// Other picture type not categorized in this enum.
  Other,
  /// 32x32 pixels 'file icon'.
  FileIconStandard,
  /// Other, or non-standard, file icon.
  FileIcon,
  /// Cover (front).
  FrontCover,
  /// Cover (back).
  BackCover,
  /// Leaflet page.
  LeafletPage,
  /// Media, like label side of a CD.
  Media,
  /// Lead artist, lead performer, or soloist.
  LeadArtist,
  /// Artist or performer.
  Artist,
  /// Conductor.
  Conductor,
  /// Band or orchestra.
  Band,
  /// Composer.
  Composer,
  /// Lyricist or text writer.
  Lyricist,
  /// Recording location.
  RecordingLocation,
  /// During recording.
  DuringRecording,
  /// During performance.
  DuringPerformance,
  /// Movie, or video, screen capture.
  VideoScreenCapture,
  /// A bright colored fish.
  Fish,
  /// Illustration.
  Illustration,
  /// Band, or artist, logotype.
  BandLogo,
  /// Publisher, or studio, logotype.
  PublisherLogo,
}

impl fmt::Display for PictureType {
  fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    write!(formatter, "{}", match *self {
      PictureType::Other              => "Other",
      PictureType::FileIconStandard   => "File Icon (standard)",
      PictureType::FileIcon           => "File Icon",
      PictureType::FrontCover         => "Cover (front)",
      PictureType::BackCover          => "Cover (back)",
      PictureType::LeafletPage        => "Leaflet Page",
      PictureType::Media              => "Media",
      PictureType::LeadArtist         => "Lead Artist",
      PictureType::Artist             => "Arist",
      PictureType::Conductor          => "Conductor",
      PictureType::Band               => "Band",
      PictureType::Composer           => "Composer",
      PictureType::Lyricist           => "Lyricist",
      PictureType::RecordingLocation  => "Recoding Location",
      PictureType::DuringRecording    => "During Recording",
      PictureType::DuringPerformace   => "During Performace",
      PictureType::VideoScreenCapture => "Video Screen Capture",
      PictureType::Fish               => "Fish",
      PictureType::Illustration       => "Illustration",
      PictureType::BandLogo           => "Band Logo",
      PictureType::PublisherLogo      => "Publisher Logo",
    })
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn test_is_varied_block_size() {
    let mut info = StreamInfo::new();

    info.min_block_size = 512;
    info.max_block_size = 1024;

    assert!(info.is_varied_block_size());

    info.min_block_size = 2048;
    info.max_block_size = 2048;

    assert!(!info.is_varied_block_size());
  }

  #[test]
  fn test_is_fixed_block_size() {
    let mut info = StreamInfo::new();

    info.min_block_size = 512;
    info.max_block_size = 512;

    assert!(info.is_fixed_block_size());

    info.min_block_size = 1024;
    info.max_block_size = 2048;

    assert!(!info.is_fixed_block_size());
  }
}
<commit_msg>Update Display implementation with typo fix<commit_after>use std::collections::HashMap;
use std::fmt;

/// Data associated with a single metadata block.
#[derive(Debug)]
pub struct Metadata {
  /// Marks whether the current metadata block is the last.
  is_last: bool,
  /// The length, in bytes, of the block being parsed. This does not include
  /// the metadata block header.
  length: u32,
  /// Block data containing one of the eight different types of metadata.
  pub data: Data,
}

/// An enum that represents a metadata block type.
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Type {
  /// Represents the current block is stream information.
  StreamInfo,
  /// Represents the current block is padding.
  Padding,
  /// Represents the current block is application data.
  Application,
  /// Represents the current block is a seek table.
  SeekTable,
  /// Represents the current block is a vorbis comment.
  VorbisComment,
  /// Represents the current block is a cue sheet.
  CueSheet,
  /// Represents the current block is a picture.
  Picture,
  /// Represents the current block is unknow.
  Unknown,
}

macro_rules! is_block_type (
  ($name: ident, $block_type: ident) => (
    #[inline]
    pub fn $name(&self) -> bool {
      self.data_type() == Type::$block_type
    }
  );
);

impl Metadata {
  /// Constructs a new `Metadata` struct based on the arguments passed in.
  pub fn new(is_last: bool, length: u32, data: Data) -> Self {
    Metadata {
      is_last: is_last,
      length: length,
      data: data,
    }
  }

  /// Returns whether the current metadata block is the last.
  #[inline]
  pub fn is_last(&self) -> bool {
    self.is_last
  }

  /// Returns the metadata block's type.
  pub fn data_type(&self) -> Type {
    match self.data {
      Data::StreamInfo(_)    => Type::StreamInfo,
      Data::Padding(_)       => Type::Padding,
      Data::Application(_)   => Type::Application,
      Data::SeekTable(_)     => Type::SeekTable,
      Data::VorbisComment(_) => Type::VorbisComment,
      Data::CueSheet(_)      => Type::CueSheet,
      Data::Picture(_)       => Type::Picture,
      Data::Unknown(_)       => Type::Unknown,
    }
  }

  is_block_type!(is_stream_info, StreamInfo);
  is_block_type!(is_padding, Padding);
  is_block_type!(is_application, Application);
  is_block_type!(is_seek_table, SeekTable);
  is_block_type!(is_vorbis_comment, VorbisComment);
  is_block_type!(is_cue_sheet, CueSheet);
  is_block_type!(is_picture, Picture);
  is_block_type!(is_unknown, Unknown);
}

/// General enum that hold all the different metadata block data.
#[derive(Debug, PartialEq, Eq)]
pub enum Data {
  /// Information regarding the entire audio stream.
  StreamInfo(StreamInfo),
  /// Block that represents a number of padded bytes.
  Padding(u32),
  /// Data used by third-party applications.
  Application(Application),
  /// Table of multiple points to seek, or skip, to within the FLAC file.
  SeekTable(Vec<SeekPoint>),
  /// Stores human-readable name/value pairs.
  VorbisComment(VorbisComment),
  /// Stores cue information
  CueSheet(CueSheet),
  /// Stores pictures associated with the FLAC file.
  Picture(Picture),
  /// A type of block data that isn't know or doesn't match the type above.
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct StreamInfo {
  /// Minimum block size, in samples, used in the stream.
  pub min_block_size: u16,
  /// Maximum block size, in samples, used in the stream.
  pub max_block_size: u16,
  /// Minimum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub min_frame_size: u32,
  /// Maximum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub max_frame_size: u32,
  /// Sample rate in hertz (Hz).
  pub sample_rate: u32,
  /// Number of channels. FLAC supports one to eight channel.
  pub channels: u8,
  /// Bits per sample. FLAC supports four to thirty-two bits per sample.
  pub bits_per_sample: u8,
  /// Total samples in the stream. A value of zero means the number is
  /// unknown.
  pub total_samples: u64,
  /// MD5 signature of the unencoded audio data.
  pub md5_sum: [u8; 16],
}

impl StreamInfo {
  /// Constructs a zeroed out `StreamInfo` struct.
  pub fn new() -> StreamInfo {
    StreamInfo {
      min_block_size: 0,
      max_block_size: 0,
      min_frame_size: 0,
      max_frame_size: 0,
      sample_rate: 0,
      channels: 0,
      bits_per_sample: 0,
      total_samples: 0,
      md5_sum: [0; 16],
    }
  }

  /// Returns true if `min_block_size` and `max_block_size` are different,
  /// otherwise false.
  #[inline]
  pub fn is_varied_block_size(&self) -> bool {
    self.min_block_size != self.max_block_size
  }

  /// Returns true if `min_block_size` and `max_block_size` are equal,
  /// otherwise false.
  #[inline]
  pub fn is_fixed_block_size(&self) -> bool {
    self.min_block_size == self.max_block_size
  }
}

/// Data used by third-party applications.
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  /// Registered application ID.
  pub id: String,
  /// Data used by the third-party application.
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file.
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  /// Sample number of the first sample in the target frame.
  pub sample_number: u64,
  /// Byte offset of the target frame's header.
  pub stream_offset: u64,
  /// Number of samples in the target frame.
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs.
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  /// Vendor name.
  pub vendor_string: String,
  /// Comments associated with a name, or category, followed by it's
  /// contents.
  pub comments: HashMap<String, String>,
}

/// Stores cue information.
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  /// Media catalog number.
  pub media_catalog_number: String,
  /// Number of lead-in samples.
  pub lead_in: u64,
  /// Whether or not this `CueSheet` corresponds to a Compact Disc.
  pub is_cd: bool,
  /// One or more tracks.
  pub tracks: Vec<CueSheetTrack>,
}

/// Track information inside a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  /// Track offset, in samples, relative to the beginning of the FLAC audio
  /// stream.
  pub offset: u64,
  /// Track number.
  pub number: u8,
  /// Twelve digit alphanumeric code.
  pub isrc: String,
  /// Whether the cue sheet track is audio.
  pub is_audio: bool,
  /// Whether the cue sheet track is pre-emphasis.
  pub is_pre_emphasis: bool,
  /// For all tracks except the lead-out track.
  pub indices: Vec<CueSheetTrackIndex>,
}

/// An index point within a track, inside of a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  /// Offset, in samples, relative to the track offset of the index point.
  pub offset: u64,
  /// Index point number.
  pub number: u8,
}

/// Stores pictures associated with the FLAC file.
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  /// Picture type, based on the ID3v2 APIC frame.
  pub picture_type: PictureType,
  /// Multipurpose Internet Mail Extensions (MIME) type.
  pub mime_type: String,
  /// A string describing the picture.
  pub description: String,
  /// Width of the picture in pixels.
  pub width: u32,
  /// Height of the picture in pixels.
  pub height: u32,
  /// Color depth of the picture in bits-per-pixel.
  pub depth: u32,
  /// Number of colors used.
  pub colors: u32,
  /// Binary picture data.
  pub data: Vec<u8>,
}

/// The picture type according to the ID3v2 attached picture frame.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  /// Other picture type not categorized in this enum.
  Other,
  /// 32x32 pixels 'file icon'.
  FileIconStandard,
  /// Other, or non-standard, file icon.
  FileIcon,
  /// Cover (front).
  FrontCover,
  /// Cover (back).
  BackCover,
  /// Leaflet page.
  LeafletPage,
  /// Media, like label side of a CD.
  Media,
  /// Lead artist, lead performer, or soloist.
  LeadArtist,
  /// Artist or performer.
  Artist,
  /// Conductor.
  Conductor,
  /// Band or orchestra.
  Band,
  /// Composer.
  Composer,
  /// Lyricist or text writer.
  Lyricist,
  /// Recording location.
  RecordingLocation,
  /// During recording.
  DuringRecording,
  /// During performance.
  DuringPerformance,
  /// Movie, or video, screen capture.
  VideoScreenCapture,
  /// A bright colored fish.
  Fish,
  /// Illustration.
  Illustration,
  /// Band, or artist, logotype.
  BandLogo,
  /// Publisher, or studio, logotype.
  PublisherLogo,
}

impl fmt::Display for PictureType {
  fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    write!(formatter, "{}", match *self {
      PictureType::Other              => "Other",
      PictureType::FileIconStandard   => "File Icon (standard)",
      PictureType::FileIcon           => "File Icon",
      PictureType::FrontCover         => "Cover (front)",
      PictureType::BackCover          => "Cover (back)",
      PictureType::LeafletPage        => "Leaflet Page",
      PictureType::Media              => "Media",
      PictureType::LeadArtist         => "Lead Artist",
      PictureType::Artist             => "Arist",
      PictureType::Conductor          => "Conductor",
      PictureType::Band               => "Band",
      PictureType::Composer           => "Composer",
      PictureType::Lyricist           => "Lyricist",
      PictureType::RecordingLocation  => "Recoding Location",
      PictureType::DuringRecording    => "During Recording",
      PictureType::DuringPerformance  => "During Performance",
      PictureType::VideoScreenCapture => "Video Screen Capture",
      PictureType::Fish               => "Fish",
      PictureType::Illustration       => "Illustration",
      PictureType::BandLogo           => "Band Logo",
      PictureType::PublisherLogo      => "Publisher Logo",
    })
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn test_is_varied_block_size() {
    let mut info = StreamInfo::new();

    info.min_block_size = 512;
    info.max_block_size = 1024;

    assert!(info.is_varied_block_size());

    info.min_block_size = 2048;
    info.max_block_size = 2048;

    assert!(!info.is_varied_block_size());
  }

  #[test]
  fn test_is_fixed_block_size() {
    let mut info = StreamInfo::new();

    info.min_block_size = 512;
    info.max_block_size = 512;

    assert!(info.is_fixed_block_size());

    info.min_block_size = 1024;
    info.max_block_size = 2048;

    assert!(!info.is_fixed_block_size());
  }
}
<|endoftext|>