<commit_before>use context::GlVersion;
use gl;
use libc;
use std::c_vec::CVec;
use std::fmt;
use std::mem;
use std::sync::Arc;

/// A list of verices loaded in the graphics card's memory.
pub struct VertexBuffer<T> {
    display: Arc<super::DisplayImpl>,
    id: gl::types::GLuint,
    elements_size: uint,
    bindings: VertexBindings,
    elements_count: uint,
}

/// This public function is accessible from within `glium` but not for the user.
#[doc(hidden)]
pub fn get_clone<T>(vb: &VertexBuffer<T>) -> (gl::types::GLuint, uint, VertexBindings) {
    (vb.id.clone(), vb.elements_size.clone(), vb.bindings.clone())
}

impl<T: VertexFormat + 'static + Send> VertexBuffer<T> {
    /// Builds a new vertex buffer.
    ///
    /// # Example
    ///
    /// ```
    /// # #![feature(phase)]
    /// # #[phase(plugin)]
    /// # extern crate glium_macros;
    /// # extern crate glium;
    /// # extern crate glutin;
    /// # use glium::DisplayBuild;
    /// # fn main() {
    /// #[vertex_format]
    /// struct Vertex {
    ///     position: [f32, ..3],
    ///     texcoords: [f32, ..2],
    /// }
    ///
    /// # let display: glium::Display = glutin::HeadlessRendererBuilder::new(1024, 768)
    /// #   .build_glium().unwrap();
    /// let vertex_buffer = glium::VertexBuffer::new(&display, vec![
    ///     Vertex { position: [0.0,  0.0, 0.0], texcoords: [0.0, 1.0] },
    ///     Vertex { position: [5.0, -3.0, 2.0], texcoords: [1.0, 0.0] },
    /// ]);
    /// # }
    /// ```
    ///
    pub fn new(display: &super::Display, data: Vec<T>) -> VertexBuffer<T> {
        VertexBuffer::new_impl(display, data, false)
    }

    /// Builds a new vertex buffer.
    ///
    /// This function will create a buffer that has better performances when it is modified
    ///  frequently.
    pub fn new_dynamic(display: &super::Display, data: Vec<T>) -> VertexBuffer<T> {
        VertexBuffer::new_impl(display, data, true)
    }

    fn new_impl(display: &super::Display, data: Vec<T>, dynamic: bool) -> VertexBuffer<T> {
        let bindings = VertexFormat::build_bindings(None::<T>);

        let elements_size = { use std::mem; mem::size_of::<T>() };
        let elements_count = data.len();
        let buffer_size = elements_count * elements_size as uint;

        let usage = if dynamic { gl::DYNAMIC_DRAW } else { gl::STATIC_DRAW };

        let (tx, rx) = channel();

        display.context.context.exec(proc(gl, state, version, extensions) {
            unsafe {
                let mut id: gl::types::GLuint = mem::uninitialized();
                gl.GenBuffers(1, &mut id);

                if version >= &GlVersion(4, 5) {
                    gl.NamedBufferData(id, buffer_size as gl::types::GLsizei,
                        data.as_ptr() as *const libc::c_void, usage);

                } else if extensions.gl_ext_direct_state_access {
                    gl.NamedBufferDataEXT(id, buffer_size as gl::types::GLsizeiptr,
                        data.as_ptr() as *const libc::c_void, usage);

                } else {
                    gl.BindBuffer(gl::ARRAY_BUFFER, id);
                    state.array_buffer_binding = Some(id);
                    gl.BufferData(gl::ARRAY_BUFFER, buffer_size as gl::types::GLsizeiptr,
                        data.as_ptr() as *const libc::c_void, usage);
                }

                tx.send(id);
            }
        });

        VertexBuffer {
            display: display.context.clone(),
            id: rx.recv(),
            elements_size: elements_size,
            bindings: bindings,
            elements_count: elements_count,
        }
    }

    /// Maps the buffer to allow write access to it.
    pub fn map<'a>(&'a mut self) -> Mapping<'a, T> {
        let (tx, rx) = channel();
        let id = self.id.clone();
        let elements_count = self.elements_count.clone();

        self.display.context.exec(proc(gl, state, version, _) {
            let ptr = {
                if version >= &GlVersion(4, 5) {
                    gl.MapNamedBuffer(id, gl::READ_WRITE)

                } else {
                    if state.array_buffer_binding != Some(id) {
                        gl.BindBuffer(gl::ARRAY_BUFFER, id);
                        state.array_buffer_binding = Some(id);
                    }

                    gl.MapBuffer(gl::ARRAY_BUFFER, gl::READ_WRITE)
                }
            };

            if ptr.is_null() {
                tx.send(Err("glMapBuffer returned null"));
            } else {
                tx.send(Ok(ptr as *mut T));
            }
        });

        Mapping {
            buffer: self,
            data: unsafe { CVec::new(rx.recv().unwrap(), elements_count) },
        }
    }

    /// Reads the content of the buffer.
    ///
    /// This function is usually better if are just doing one punctual read, while `map` is better
    /// if you want to have multiple small reads.
    pub fn read(&self) -> Vec<T> {
        self.read_slice(0, self.elements_count)
    }

    /// Reads the content of the buffer.
    ///
    /// This function is usually better if are just doing one punctual read, while `map` is better
    /// if you want to have multiple small reads.
    ///
    /// The offset and size are expressed in number of elements.
    ///
    /// ## Panic
    ///
    /// Panics if `offset` or `offset + size` are greated than the size of the buffer.
    pub fn read_slice(&self, offset: uint, size: uint) -> Vec<T> {
        assert!(offset + size <= self.elements_count);

        let id = self.id.clone();
        let elements_size = self.elements_size.clone();
        let (tx, rx) = channel();

        self.display.context.exec(proc(gl, state, version, _) {
            unsafe {
                let mut data = Vec::with_capacity(size);
                data.set_len(size);

                if version >= &GlVersion(4, 5) {
                    gl.GetNamedBufferSubData(id, (offset * elements_size) as gl::types::GLintptr,
                        (size * elements_size) as gl::types::GLsizeiptr,
                        data.as_mut_ptr() as *mut libc::c_void);

                } else {
                    if state.array_buffer_binding != Some(id) {
                        gl.BindBuffer(gl::ARRAY_BUFFER, id);
                        state.array_buffer_binding = Some(id);
                    }

                    gl.GetBufferSubData(gl::ARRAY_BUFFER, (offset * elements_size)
                        as gl::types::GLintptr, (size * elements_size) as gl::types::GLsizeiptr,
                        data.as_mut_ptr() as *mut libc::c_void);
                }

                tx.send_opt(data).ok();
            }
        });

        rx.recv()
    }
}

impl<T> fmt::Show for VertexBuffer<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::FormatError> {
        (format!("VertexBuffer #{}", self.id)).fmt(formatter)
    }
}

#[unsafe_destructor]
impl<T> Drop for VertexBuffer<T> {
    fn drop(&mut self) {
        let id = self.id.clone();
        self.display.context.exec(proc(gl, state, _, _) {
            if state.array_buffer_binding == Some(id) {
                state.array_buffer_binding = None;
            }

            if state.element_array_buffer_binding == Some(id) {
                state.element_array_buffer_binding = None;
            }

            unsafe { gl.DeleteBuffers(1, [ id ].as_ptr()); }
        });
    }
}

/// Describes the attribute of a vertex.
///
/// When you create a vertex buffer, you need to pass some sort of array of data. In order for
/// OpenGL to use this data, we must tell it some informations about each field of each
/// element. This structure describes one such field.
#[deriving(Show, Clone)]
pub struct VertexAttrib {
    /// The offset, in bytes, between the start of each vertex and the attribute.
    pub offset: uint,

    /// Type of the field.
    pub data_type: gl::types::GLenum,

    /// Number of invidual elements in the attribute.
    ///
    /// For example if `data_type` is a f32 and `elements_count` is 2, then you have a `vec2`.
    pub elements_count: u32,
}

/// Describes the layout of each vertex in a vertex buffer.
pub type VertexBindings = Vec<(String, VertexAttrib)>;

/// Trait for structures that represent a vertex.
pub trait VertexFormat: Copy {
    /// Builds the `VertexBindings` representing the layout of this element.
    fn build_bindings(Option<Self>) -> VertexBindings;
}

/// A mapping of a buffer.
pub struct Mapping<'b, T> {
    buffer: &'b mut VertexBuffer<T>,
    data: CVec<T>,
}

#[unsafe_destructor]
impl<'a, T> Drop for Mapping<'a, T> {
    fn drop(&mut self) {
        let id = self.buffer.id.clone();
        self.buffer.display.context.exec(proc(gl, state, version, _) {
            if version >= &GlVersion(4, 5) {
                gl.UnmapNamedBuffer(id);

            } else {
                if state.array_buffer_binding != Some(id) {
                    gl.BindBuffer(gl::ARRAY_BUFFER, id);
                    state.array_buffer_binding = Some(id);
                }

                gl.UnmapBuffer(gl::ARRAY_BUFFER);
            }
        });
    }
}

impl<'a, T> Deref<[T]> for Mapping<'a, T> {
    fn deref<'b>(&'b self) -> &'b [T] {
        self.data.as_slice()
    }
}

impl<'a, T> DerefMut<[T]> for Mapping<'a, T> {
    fn deref_mut<'b>(&'b mut self) -> &'b mut [T] {
        self.data.as_mut_slice()
    }
}
<commit_msg>Add warning for VertexBuffer::map<commit_after>use context::GlVersion;
use gl;
use libc;
use std::c_vec::CVec;
use std::fmt;
use std::mem;
use std::sync::Arc;

/// A list of verices loaded in the graphics card's memory.
pub struct VertexBuffer<T> {
    display: Arc<super::DisplayImpl>,
    id: gl::types::GLuint,
    elements_size: uint,
    bindings: VertexBindings,
    elements_count: uint,
}

/// This public function is accessible from within `glium` but not for the user.
#[doc(hidden)]
pub fn get_clone<T>(vb: &VertexBuffer<T>) -> (gl::types::GLuint, uint, VertexBindings) {
    (vb.id.clone(), vb.elements_size.clone(), vb.bindings.clone())
}

impl<T: VertexFormat + 'static + Send> VertexBuffer<T> {
    /// Builds a new vertex buffer.
    ///
    /// # Example
    ///
    /// ```
    /// # #![feature(phase)]
    /// # #[phase(plugin)]
    /// # extern crate glium_macros;
    /// # extern crate glium;
    /// # extern crate glutin;
    /// # use glium::DisplayBuild;
    /// # fn main() {
    /// #[vertex_format]
    /// struct Vertex {
    ///     position: [f32, ..3],
    ///     texcoords: [f32, ..2],
    /// }
    ///
    /// # let display: glium::Display = glutin::HeadlessRendererBuilder::new(1024, 768)
    /// #   .build_glium().unwrap();
    /// let vertex_buffer = glium::VertexBuffer::new(&display, vec![
    ///     Vertex { position: [0.0,  0.0, 0.0], texcoords: [0.0, 1.0] },
    ///     Vertex { position: [5.0, -3.0, 2.0], texcoords: [1.0, 0.0] },
    /// ]);
    /// # }
    /// ```
    ///
    pub fn new(display: &super::Display, data: Vec<T>) -> VertexBuffer<T> {
        VertexBuffer::new_impl(display, data, false)
    }

    /// Builds a new vertex buffer.
    ///
    /// This function will create a buffer that has better performances when it is modified
    ///  frequently.
    pub fn new_dynamic(display: &super::Display, data: Vec<T>) -> VertexBuffer<T> {
        VertexBuffer::new_impl(display, data, true)
    }

    fn new_impl(display: &super::Display, data: Vec<T>, dynamic: bool) -> VertexBuffer<T> {
        let bindings = VertexFormat::build_bindings(None::<T>);

        let elements_size = { use std::mem; mem::size_of::<T>() };
        let elements_count = data.len();
        let buffer_size = elements_count * elements_size as uint;

        let usage = if dynamic { gl::DYNAMIC_DRAW } else { gl::STATIC_DRAW };

        let (tx, rx) = channel();

        display.context.context.exec(proc(gl, state, version, extensions) {
            unsafe {
                let mut id: gl::types::GLuint = mem::uninitialized();
                gl.GenBuffers(1, &mut id);

                if version >= &GlVersion(4, 5) {
                    gl.NamedBufferData(id, buffer_size as gl::types::GLsizei,
                        data.as_ptr() as *const libc::c_void, usage);

                } else if extensions.gl_ext_direct_state_access {
                    gl.NamedBufferDataEXT(id, buffer_size as gl::types::GLsizeiptr,
                        data.as_ptr() as *const libc::c_void, usage);

                } else {
                    gl.BindBuffer(gl::ARRAY_BUFFER, id);
                    state.array_buffer_binding = Some(id);
                    gl.BufferData(gl::ARRAY_BUFFER, buffer_size as gl::types::GLsizeiptr,
                        data.as_ptr() as *const libc::c_void, usage);
                }

                tx.send(id);
            }
        });

        VertexBuffer {
            display: display.context.clone(),
            id: rx.recv(),
            elements_size: elements_size,
            bindings: bindings,
            elements_count: elements_count,
        }
    }

    /// Maps the buffer to allow write access to it.
    ///
    /// **Warning**: using this function can slow things down a lot because the function
    /// waits for all the previous commands to be executed before returning.
    pub fn map<'a>(&'a mut self) -> Mapping<'a, T> {
        let (tx, rx) = channel();
        let id = self.id.clone();
        let elements_count = self.elements_count.clone();

        self.display.context.exec(proc(gl, state, version, _) {
            let ptr = {
                if version >= &GlVersion(4, 5) {
                    gl.MapNamedBuffer(id, gl::READ_WRITE)

                } else {
                    if state.array_buffer_binding != Some(id) {
                        gl.BindBuffer(gl::ARRAY_BUFFER, id);
                        state.array_buffer_binding = Some(id);
                    }

                    gl.MapBuffer(gl::ARRAY_BUFFER, gl::READ_WRITE)
                }
            };

            if ptr.is_null() {
                tx.send(Err("glMapBuffer returned null"));
            } else {
                tx.send(Ok(ptr as *mut T));
            }
        });

        Mapping {
            buffer: self,
            data: unsafe { CVec::new(rx.recv().unwrap(), elements_count) },
        }
    }

    /// Reads the content of the buffer.
    ///
    /// This function is usually better if are just doing one punctual read, while `map` is better
    /// if you want to have multiple small reads.
    pub fn read(&self) -> Vec<T> {
        self.read_slice(0, self.elements_count)
    }

    /// Reads the content of the buffer.
    ///
    /// This function is usually better if are just doing one punctual read, while `map` is better
    /// if you want to have multiple small reads.
    ///
    /// The offset and size are expressed in number of elements.
    ///
    /// ## Panic
    ///
    /// Panics if `offset` or `offset + size` are greated than the size of the buffer.
    pub fn read_slice(&self, offset: uint, size: uint) -> Vec<T> {
        assert!(offset + size <= self.elements_count);

        let id = self.id.clone();
        let elements_size = self.elements_size.clone();
        let (tx, rx) = channel();

        self.display.context.exec(proc(gl, state, version, _) {
            unsafe {
                let mut data = Vec::with_capacity(size);
                data.set_len(size);

                if version >= &GlVersion(4, 5) {
                    gl.GetNamedBufferSubData(id, (offset * elements_size) as gl::types::GLintptr,
                        (size * elements_size) as gl::types::GLsizeiptr,
                        data.as_mut_ptr() as *mut libc::c_void);

                } else {
                    if state.array_buffer_binding != Some(id) {
                        gl.BindBuffer(gl::ARRAY_BUFFER, id);
                        state.array_buffer_binding = Some(id);
                    }

                    gl.GetBufferSubData(gl::ARRAY_BUFFER, (offset * elements_size)
                        as gl::types::GLintptr, (size * elements_size) as gl::types::GLsizeiptr,
                        data.as_mut_ptr() as *mut libc::c_void);
                }

                tx.send_opt(data).ok();
            }
        });

        rx.recv()
    }
}

impl<T> fmt::Show for VertexBuffer<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::FormatError> {
        (format!("VertexBuffer #{}", self.id)).fmt(formatter)
    }
}

#[unsafe_destructor]
impl<T> Drop for VertexBuffer<T> {
    fn drop(&mut self) {
        let id = self.id.clone();
        self.display.context.exec(proc(gl, state, _, _) {
            if state.array_buffer_binding == Some(id) {
                state.array_buffer_binding = None;
            }

            if state.element_array_buffer_binding == Some(id) {
                state.element_array_buffer_binding = None;
            }

            unsafe { gl.DeleteBuffers(1, [ id ].as_ptr()); }
        });
    }
}

/// Describes the attribute of a vertex.
///
/// When you create a vertex buffer, you need to pass some sort of array of data. In order for
/// OpenGL to use this data, we must tell it some informations about each field of each
/// element. This structure describes one such field.
#[deriving(Show, Clone)]
pub struct VertexAttrib {
    /// The offset, in bytes, between the start of each vertex and the attribute.
    pub offset: uint,

    /// Type of the field.
    pub data_type: gl::types::GLenum,

    /// Number of invidual elements in the attribute.
    ///
    /// For example if `data_type` is a f32 and `elements_count` is 2, then you have a `vec2`.
    pub elements_count: u32,
}

/// Describes the layout of each vertex in a vertex buffer.
pub type VertexBindings = Vec<(String, VertexAttrib)>;

/// Trait for structures that represent a vertex.
pub trait VertexFormat: Copy {
    /// Builds the `VertexBindings` representing the layout of this element.
    fn build_bindings(Option<Self>) -> VertexBindings;
}

/// A mapping of a buffer.
pub struct Mapping<'b, T> {
    buffer: &'b mut VertexBuffer<T>,
    data: CVec<T>,
}

#[unsafe_destructor]
impl<'a, T> Drop for Mapping<'a, T> {
    fn drop(&mut self) {
        let id = self.buffer.id.clone();
        self.buffer.display.context.exec(proc(gl, state, version, _) {
            if version >= &GlVersion(4, 5) {
                gl.UnmapNamedBuffer(id);

            } else {
                if state.array_buffer_binding != Some(id) {
                    gl.BindBuffer(gl::ARRAY_BUFFER, id);
                    state.array_buffer_binding = Some(id);
                }

                gl.UnmapBuffer(gl::ARRAY_BUFFER);
            }
        });
    }
}

impl<'a, T> Deref<[T]> for Mapping<'a, T> {
    fn deref<'b>(&'b self) -> &'b [T] {
        self.data.as_slice()
    }
}

impl<'a, T> DerefMut<[T]> for Mapping<'a, T> {
    fn deref_mut<'b>(&'b mut self) -> &'b mut [T] {
        self.data.as_mut_slice()
    }
}
<|endoftext|>


<commit_before>use crate::common::util::*;

extern crate dircolors;
use self::dircolors::{guess_syntax, OutputFmt, StrUtils};

#[test]
fn test_shell_syntax() {
    use std::env;
    let last = env::var("SHELL");
    env::set_var("SHELL", "/path/csh");
    assert_eq!(OutputFmt::CShell, guess_syntax());
    env::set_var("SHELL", "csh");
    assert_eq!(OutputFmt::CShell, guess_syntax());
    env::set_var("SHELL", "/path/bash");
    assert_eq!(OutputFmt::Shell, guess_syntax());
    env::set_var("SHELL", "bash");
    assert_eq!(OutputFmt::Shell, guess_syntax());
    env::set_var("SHELL", "/asd/bar");
    assert_eq!(OutputFmt::Shell, guess_syntax());
    env::set_var("SHELL", "foo");
    assert_eq!(OutputFmt::Shell, guess_syntax());
    env::set_var("SHELL", "");
    assert_eq!(OutputFmt::Unknown, guess_syntax());
    env::remove_var("SHELL");
    assert_eq!(OutputFmt::Unknown, guess_syntax());

    if let Ok(s) = last {
        env::set_var("SHELL", s);
    }
}

#[test]
fn test_str_utils() {
    let s = "  asd#zcv #hk\t\n  ";
    assert_eq!("asd#zcv", s.purify());

    let s = "con256asd";
    assert!(s.fnmatch("*[2][3-6][5-9]?sd")); // spell-checker:disable-line

    let s = "zxc \t\nqwe jlk    hjl"; // spell-checker:disable-line
    let (k, v) = s.split_two();
    assert_eq!("zxc", k);
    assert_eq!("qwe jlk    hjl", v);
}

#[test]
fn test1() {
    test_helper("test1", "gnome");
}

#[test]
fn test_keywords() {
    test_helper("keywords", "");
}

#[test]
fn test_internal_db() {
    new_ucmd!()
        .arg("-p")
        .run()
        .stdout_is_fixture("internal.expected");
}

#[test]
fn test_bash_default() {
    new_ucmd!()
        .env("TERM", "screen")
        .arg("-b")
        .run()
        .stdout_is_fixture("bash_def.expected");
}

#[test]
fn test_csh_default() {
    new_ucmd!()
        .env("TERM", "screen")
        .arg("-c")
        .run()
        .stdout_is_fixture("csh_def.expected");
}

#[test]
fn test_no_env() {
    // no SHELL and TERM
    new_ucmd!().fails();
}

#[test]
fn test_exclusive_option() {
    new_ucmd!().arg("-cp").fails();
}

fn test_helper(file_name: &str, term: &str) {
    new_ucmd!()
        .env("TERM", term)
        .arg("-c")
        .arg(format!("{}.txt", file_name))
        .run()
        .stdout_is_fixture(format!("{}.csh.expected", file_name));

    new_ucmd!()
        .env("TERM", term)
        .arg("-b")
        .arg(format!("{}.txt", file_name))
        .run()
        .stdout_is_fixture(format!("{}.sh.expected", file_name));
}
<commit_msg>dircolors: test for correct error for -bp and -cp<commit_after>use crate::common::util::*;

extern crate dircolors;
use self::dircolors::{guess_syntax, OutputFmt, StrUtils};

#[test]
fn test_shell_syntax() {
    use std::env;
    let last = env::var("SHELL");
    env::set_var("SHELL", "/path/csh");
    assert_eq!(OutputFmt::CShell, guess_syntax());
    env::set_var("SHELL", "csh");
    assert_eq!(OutputFmt::CShell, guess_syntax());
    env::set_var("SHELL", "/path/bash");
    assert_eq!(OutputFmt::Shell, guess_syntax());
    env::set_var("SHELL", "bash");
    assert_eq!(OutputFmt::Shell, guess_syntax());
    env::set_var("SHELL", "/asd/bar");
    assert_eq!(OutputFmt::Shell, guess_syntax());
    env::set_var("SHELL", "foo");
    assert_eq!(OutputFmt::Shell, guess_syntax());
    env::set_var("SHELL", "");
    assert_eq!(OutputFmt::Unknown, guess_syntax());
    env::remove_var("SHELL");
    assert_eq!(OutputFmt::Unknown, guess_syntax());

    if let Ok(s) = last {
        env::set_var("SHELL", s);
    }
}

#[test]
fn test_str_utils() {
    let s = "  asd#zcv #hk\t\n  ";
    assert_eq!("asd#zcv", s.purify());

    let s = "con256asd";
    assert!(s.fnmatch("*[2][3-6][5-9]?sd")); // spell-checker:disable-line

    let s = "zxc \t\nqwe jlk    hjl"; // spell-checker:disable-line
    let (k, v) = s.split_two();
    assert_eq!("zxc", k);
    assert_eq!("qwe jlk    hjl", v);
}

#[test]
fn test1() {
    test_helper("test1", "gnome");
}

#[test]
fn test_keywords() {
    test_helper("keywords", "");
}

#[test]
fn test_internal_db() {
    new_ucmd!()
        .arg("-p")
        .run()
        .stdout_is_fixture("internal.expected");
}

#[test]
fn test_bash_default() {
    new_ucmd!()
        .env("TERM", "screen")
        .arg("-b")
        .run()
        .stdout_is_fixture("bash_def.expected");
}

#[test]
fn test_csh_default() {
    new_ucmd!()
        .env("TERM", "screen")
        .arg("-c")
        .run()
        .stdout_is_fixture("csh_def.expected");
}

#[test]
fn test_no_env() {
    // no SHELL and TERM
    new_ucmd!().fails();
}

#[test]
fn test_exclusive_option() {
    new_ucmd!()
        .arg("-bp")
        .fails()
        .stderr_contains("mutually exclusive");
    new_ucmd!()
        .arg("-cp")
        .fails()
        .stderr_contains("mutually exclusive");
}

fn test_helper(file_name: &str, term: &str) {
    new_ucmd!()
        .env("TERM", term)
        .arg("-c")
        .arg(format!("{}.txt", file_name))
        .run()
        .stdout_is_fixture(format!("{}.csh.expected", file_name));

    new_ucmd!()
        .env("TERM", term)
        .arg("-b")
        .arg(format!("{}.txt", file_name))
        .run()
        .stdout_is_fixture(format!("{}.sh.expected", file_name));
}
<|endoftext|>


<commit_before>#![crate_name = "uu_uname"]

// This file is part of the uutils coreutils package.
//
// (c) Joao Oliveira <joaoxsouls@gmail.com>
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//

// last synced with: uname (GNU coreutils) 8.21

extern crate clap;
extern crate platform_info;
#[macro_use]
extern crate uucore;

use clap::{App, Arg};
use platform_info::*;

const VERSION: &str = env!("CARGO_PKG_VERSION");
const ABOUT: &str = "Print certain system information.  With no OPTION, same as -s.";

const OPT_ALL: &str = "all";
const OPT_KERNELNAME: &str = "kernel-name";
const OPT_NODENAME: &str = "nodename";
const OPT_KERNELVERSION: &str = "kernel-version";
const OPT_KERNELRELEASE: &str = "kernel-release";
const OPT_MACHINE: &str = "machine";

//FIXME: unimplemented options
//const OPT_PROCESSOR: &'static str = "processor";
//const OPT_HWPLATFORM: &'static str = "hardware-platform";
const OPT_OS: &str = "operating-system";

#[cfg(target_os = "linux")]
const HOST_OS: &str = "GNU/Linux";
#[cfg(target_os = "windows")]
const HOST_OS: &str = "Windows NT";
#[cfg(target_os = "freebsd")]
const HOST_OS: &str = "FreeBSD";
#[cfg(target_os = "openbsd")]
const HOST_OS: &str = "OpenBSD";
#[cfg(target_os = "macos")]
const HOST_OS: &str = "Darwin";
#[cfg(target_os = "fuchsia")]
const HOST_OS: &str = "Fuchsia";
#[cfg(target_os = "redox")]
const HOST_OS: &str = "Redox";

pub fn uumain(args: Vec<String>) -> i32 {
    let usage = format!("{} [OPTION]...", executable!());
    let matches = App::new(executable!())
        .version(VERSION)
        .about(ABOUT)
        .usage(&usage[..])
        .arg(Arg::with_name(OPT_ALL)
            .short("a")
            .long(OPT_ALL)
            .help("Behave as though all of the options -mnrsv were specified."))
        .arg(Arg::with_name(OPT_KERNELNAME)
            .short("s")
            .long(OPT_KERNELNAME)
            .alias("sysname") // Obsolescent option in GNU uname
            .help("print the operating system name."))
        .arg(Arg::with_name(OPT_NODENAME)
            .short("n")
            .long(OPT_NODENAME)
            .help("print the nodename (the nodename may be a name that the system is known by to a communications network)."))
        .arg(Arg::with_name(OPT_KERNELRELEASE)
            .short("r")
            .long(OPT_KERNELRELEASE)
            .alias("release") // Obsolescent option in GNU uname
            .help("print the operating system release."))
        .arg(Arg::with_name(OPT_KERNELVERSION)
            .short("v")
            .long(OPT_KERNELVERSION)
            .help("print the operating system version."))

        //FIXME: unimplemented options
        // .arg(Arg::with_name(OPT_PROCESSOR)
        //     .short("p")
        //     .long(OPT_PROCESSOR)
        //     .help("print the processor type (non-portable)"))
        // .arg(Arg::with_name(OPT_HWPLATFORM)
        //     .short("i")
        //     .long(OPT_HWPLATFORM)
        //     .help("print the hardware platform (non-portable)"))
        .arg(Arg::with_name(OPT_MACHINE)
            .short("m")
            .long(OPT_MACHINE)
            .help("print the machine hardware name."))
        .get_matches_from(&args);

    let argc = args.len();
    let uname = return_if_err!(1, PlatformInfo::new());
    let mut output = String::new();

    if matches.is_present(OPT_KERNELNAME) || matches.is_present(OPT_ALL) || argc == 1 {
        output.push_str(&uname.sysname());
        output.push_str(" ");
    }

    if matches.is_present(OPT_NODENAME) || matches.is_present(OPT_ALL) {
        output.push_str(&uname.nodename());
        output.push_str(" ");
    }
    if matches.is_present(OPT_KERNELRELEASE) || matches.is_present(OPT_ALL) {
        output.push_str(&uname.release());
        output.push_str(" ");
    }
    if matches.is_present(OPT_KERNELVERSION) || matches.is_present(OPT_ALL) {
        output.push_str(&uname.version());
        output.push_str(" ");
    }
    if matches.is_present(OPT_MACHINE) || matches.is_present(OPT_ALL) {
        output.push_str(&uname.machine());
        output.push_str(" ");
    }
    if matches.is_present(OPT_OS) || matches.is_present(OPT_ALL) {
        output.push_str(HOST_OS);
        output.push_str(" ");
    }
    println!("{}", output.trim_end());

    0
}
<commit_msg>feature(uname): Add -o/--operating-system flag<commit_after>#![crate_name = "uu_uname"]

// This file is part of the uutils coreutils package.
//
// (c) Joao Oliveira <joaoxsouls@gmail.com>
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//

// last synced with: uname (GNU coreutils) 8.21

extern crate clap;
extern crate platform_info;
#[macro_use]
extern crate uucore;

use clap::{App, Arg};
use platform_info::*;

const VERSION: &str = env!("CARGO_PKG_VERSION");
const ABOUT: &str = "Print certain system information.  With no OPTION, same as -s.";

const OPT_ALL: &str = "all";
const OPT_KERNELNAME: &str = "kernel-name";
const OPT_NODENAME: &str = "nodename";
const OPT_KERNELVERSION: &str = "kernel-version";
const OPT_KERNELRELEASE: &str = "kernel-release";
const OPT_MACHINE: &str = "machine";

//FIXME: unimplemented options
//const OPT_PROCESSOR: &'static str = "processor";
//const OPT_HWPLATFORM: &'static str = "hardware-platform";
const OPT_OS: &str = "operating-system";

#[cfg(target_os = "linux")]
const HOST_OS: &str = "GNU/Linux";
#[cfg(target_os = "windows")]
const HOST_OS: &str = "Windows NT";
#[cfg(target_os = "freebsd")]
const HOST_OS: &str = "FreeBSD";
#[cfg(target_os = "openbsd")]
const HOST_OS: &str = "OpenBSD";
#[cfg(target_os = "macos")]
const HOST_OS: &str = "Darwin";
#[cfg(target_os = "fuchsia")]
const HOST_OS: &str = "Fuchsia";
#[cfg(target_os = "redox")]
const HOST_OS: &str = "Redox";

pub fn uumain(args: Vec<String>) -> i32 {
    let usage = format!("{} [OPTION]...", executable!());
    let matches = App::new(executable!())
        .version(VERSION)
        .about(ABOUT)
        .usage(&usage[..])
        .arg(Arg::with_name(OPT_ALL)
            .short("a")
            .long(OPT_ALL)
            .help("Behave as though all of the options -mnrsv were specified."))
        .arg(Arg::with_name(OPT_KERNELNAME)
            .short("s")
            .long(OPT_KERNELNAME)
            .alias("sysname") // Obsolescent option in GNU uname
            .help("print the kernel name."))
        .arg(Arg::with_name(OPT_NODENAME)
            .short("n")
            .long(OPT_NODENAME)
            .help("print the nodename (the nodename may be a name that the system is known by to a communications network)."))
        .arg(Arg::with_name(OPT_KERNELRELEASE)
            .short("r")
            .long(OPT_KERNELRELEASE)
            .alias("release") // Obsolescent option in GNU uname
            .help("print the operating system release."))
        .arg(Arg::with_name(OPT_KERNELVERSION)
            .short("v")
            .long(OPT_KERNELVERSION)
            .help("print the operating system version."))

        //FIXME: unimplemented options
        // .arg(Arg::with_name(OPT_PROCESSOR)
        //     .short("p")
        //     .long(OPT_PROCESSOR)
        //     .help("print the processor type (non-portable)"))
        // .arg(Arg::with_name(OPT_HWPLATFORM)
        //     .short("i")
        //     .long(OPT_HWPLATFORM)
        //     .help("print the hardware platform (non-portable)"))
        .arg(Arg::with_name(OPT_MACHINE)
            .short("m")
            .long(OPT_MACHINE)
            .help("print the machine hardware name."))
        .arg(Arg::with_name(OPT_OS)
            .short("o")
            .long(OPT_OS)
            .help("print the operating system name."))
        .get_matches_from(&args);

    let argc = args.len();
    let uname = return_if_err!(1, PlatformInfo::new());
    let mut output = String::new();

    if matches.is_present(OPT_KERNELNAME) || matches.is_present(OPT_ALL) || argc == 1 {
        output.push_str(&uname.sysname());
        output.push_str(" ");
    }

    if matches.is_present(OPT_NODENAME) || matches.is_present(OPT_ALL) {
        output.push_str(&uname.nodename());
        output.push_str(" ");
    }
    if matches.is_present(OPT_KERNELRELEASE) || matches.is_present(OPT_ALL) {
        output.push_str(&uname.release());
        output.push_str(" ");
    }
    if matches.is_present(OPT_KERNELVERSION) || matches.is_present(OPT_ALL) {
        output.push_str(&uname.version());
        output.push_str(" ");
    }
    if matches.is_present(OPT_MACHINE) || matches.is_present(OPT_ALL) {
        output.push_str(&uname.machine());
        output.push_str(" ");
    }
    if matches.is_present(OPT_OS) || matches.is_present(OPT_ALL) {
        output.push_str(HOST_OS);
        output.push_str(" ");
    }
    println!("{}", output.trim_end());

    0
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate gimli;
extern crate test;

use gimli::{DebugAbbrev, DebugAranges, DebugInfo, DebugLine, DebugLineOffset, LineNumberProgramHeader,
            LittleEndian, StateMachine};

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

fn read_section(section: &str) -> Vec<u8> {
    let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap_or(".".into()));
    path.push("./fixtures/self/");
    path.push(section);

    assert!(path.is_file());
    let mut file = File::open(path).unwrap();

    let mut buf = Vec::new();
    file.read_to_end(&mut buf).unwrap();
    buf
}

#[bench]
fn bench_parsing_debug_abbrev(b: &mut test::Bencher) {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::<LittleEndian>::new(&debug_info);
    let unit = debug_info.units()
        .next()
        .expect("Should have at least one compilation unit")
        .expect("And it should parse OK");

    let debug_abbrev = read_section("debug_abbrev");

    b.iter(|| {
        let debug_abbrev = DebugAbbrev::<LittleEndian>::new(&debug_abbrev);
        test::black_box(unit.abbreviations(debug_abbrev)
            .expect("Should parse abbreviations"));
    });
}

#[bench]
fn bench_parsing_debug_info(b: &mut test::Bencher) {
    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::<LittleEndian>::new(&debug_abbrev);

    let debug_info = read_section("debug_info");

    b.iter(|| {
        let debug_info = DebugInfo::<LittleEndian>::new(&debug_info);

        for unit in debug_info.units() {
            let unit = unit.expect("Should parse compilation unit");
            let abbrevs = unit.abbreviations(debug_abbrev)
                .expect("Should parse abbreviations");

            let mut cursor = unit.entries(&abbrevs);
            while let Some((_, entry)) = cursor.next_dfs().expect("Should parse next dfs") {
                let mut attrs = entry.attrs();
                while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
                    test::black_box(&attr);
                }
            }
        }
    });
}

#[bench]
fn bench_parsing_debug_aranges(b: &mut test::Bencher) {
    let debug_aranges = read_section("debug_aranges");
    let debug_aranges = DebugAranges::<LittleEndian>::new(&debug_aranges);

    b.iter(|| {
        let mut aranges = debug_aranges.aranges();
        while let Some(arange) = aranges.next_arange().expect("Should parse arange OK") {
            // Not really anything else we can check right now.
        }
    });
}

// We happen to know that there is a line number program and header at
// offset 0 and that address size is 8 bytes. No need to parse DIEs to grab
// this info off of the compilation units.
const OFFSET: DebugLineOffset = DebugLineOffset(0);
const ADDRESS_SIZE: u8 = 8;

#[bench]
fn bench_parsing_line_number_program_opcodes(b: &mut test::Bencher) {
    let debug_line = read_section("debug_line");
    let debug_line = DebugLine::<LittleEndian>::new(&debug_line);

    b.iter(|| {
        let header = LineNumberProgramHeader::new(debug_line, OFFSET, ADDRESS_SIZE)
            .expect("Should parse line number program header");

        let mut opcodes = header.opcodes();
        while let Some(opcode) = opcodes.next_opcode().expect("Should parse opcode") {
            test::black_box(opcode);
        }
    });
}

#[bench]
fn bench_executing_line_number_programs(b: &mut test::Bencher) {
    let debug_line = read_section("debug_line");
    let debug_line = DebugLine::<LittleEndian>::new(&debug_line);

    b.iter(|| {
        let header = LineNumberProgramHeader::new(debug_line, OFFSET, ADDRESS_SIZE)
            .expect("Should parse line number program header");

        let mut state_machine = StateMachine::new(&header);
        while let Some(row) = state_machine.next_row()
            .expect("Should parse and execute all rows in the line number program") {
            test::black_box(row);
        }
    });
}
<commit_msg>Use `test::black_box(arange)` with the .debug_aranges bench<commit_after>#![feature(test)]

extern crate gimli;
extern crate test;

use gimli::{DebugAbbrev, DebugAranges, DebugInfo, DebugLine, DebugLineOffset, LineNumberProgramHeader,
            LittleEndian, StateMachine};

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

fn read_section(section: &str) -> Vec<u8> {
    let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap_or(".".into()));
    path.push("./fixtures/self/");
    path.push(section);

    assert!(path.is_file());
    let mut file = File::open(path).unwrap();

    let mut buf = Vec::new();
    file.read_to_end(&mut buf).unwrap();
    buf
}

#[bench]
fn bench_parsing_debug_abbrev(b: &mut test::Bencher) {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::<LittleEndian>::new(&debug_info);
    let unit = debug_info.units()
        .next()
        .expect("Should have at least one compilation unit")
        .expect("And it should parse OK");

    let debug_abbrev = read_section("debug_abbrev");

    b.iter(|| {
        let debug_abbrev = DebugAbbrev::<LittleEndian>::new(&debug_abbrev);
        test::black_box(unit.abbreviations(debug_abbrev)
            .expect("Should parse abbreviations"));
    });
}

#[bench]
fn bench_parsing_debug_info(b: &mut test::Bencher) {
    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::<LittleEndian>::new(&debug_abbrev);

    let debug_info = read_section("debug_info");

    b.iter(|| {
        let debug_info = DebugInfo::<LittleEndian>::new(&debug_info);

        for unit in debug_info.units() {
            let unit = unit.expect("Should parse compilation unit");
            let abbrevs = unit.abbreviations(debug_abbrev)
                .expect("Should parse abbreviations");

            let mut cursor = unit.entries(&abbrevs);
            while let Some((_, entry)) = cursor.next_dfs().expect("Should parse next dfs") {
                let mut attrs = entry.attrs();
                while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
                    test::black_box(&attr);
                }
            }
        }
    });
}

#[bench]
fn bench_parsing_debug_aranges(b: &mut test::Bencher) {
    let debug_aranges = read_section("debug_aranges");
    let debug_aranges = DebugAranges::<LittleEndian>::new(&debug_aranges);

    b.iter(|| {
        let mut aranges = debug_aranges.aranges();
        while let Some(arange) = aranges.next_arange().expect("Should parse arange OK") {
            test::black_box(arange);
        }
    });
}

// We happen to know that there is a line number program and header at
// offset 0 and that address size is 8 bytes. No need to parse DIEs to grab
// this info off of the compilation units.
const OFFSET: DebugLineOffset = DebugLineOffset(0);
const ADDRESS_SIZE: u8 = 8;

#[bench]
fn bench_parsing_line_number_program_opcodes(b: &mut test::Bencher) {
    let debug_line = read_section("debug_line");
    let debug_line = DebugLine::<LittleEndian>::new(&debug_line);

    b.iter(|| {
        let header = LineNumberProgramHeader::new(debug_line, OFFSET, ADDRESS_SIZE)
            .expect("Should parse line number program header");

        let mut opcodes = header.opcodes();
        while let Some(opcode) = opcodes.next_opcode().expect("Should parse opcode") {
            test::black_box(opcode);
        }
    });
}

#[bench]
fn bench_executing_line_number_programs(b: &mut test::Bencher) {
    let debug_line = read_section("debug_line");
    let debug_line = DebugLine::<LittleEndian>::new(&debug_line);

    b.iter(|| {
        let header = LineNumberProgramHeader::new(debug_line, OFFSET, ADDRESS_SIZE)
            .expect("Should parse line number program header");

        let mut state_machine = StateMachine::new(&header);
        while let Some(row) = state_machine.next_row()
            .expect("Should parse and execute all rows in the line number program") {
            test::black_box(row);
        }
    });
}
<|endoftext|>


<commit_before>use crate::{AssistContext, AssistId, Assists};
use ra_syntax::{ast, ast::TypeParamsOwner, AstNode, SyntaxKind};
use std::collections::HashSet;

// Assist: change_lifetime_anon_to_named
//
// Change an anonymous lifetime to a named lifetime.
//
// ```
// impl Cursor<'_<|>> {
//     fn node(self) -> &SyntaxNode {
//         match self {
//             Cursor::Replace(node) | Cursor::Before(node) => node,
//         }
//     }
// }
// ```
// ->
// ```
// impl<'a> Cursor<'a> {
//     fn node(self) -> &SyntaxNode {
//         match self {
//             Cursor::Replace(node) | Cursor::Before(node) => node,
//         }
//     }
// }
// ```
// FIXME: How can we handle renaming any one of multiple anonymous lifetimes?
pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let lifetime_token = ctx.find_token_at_offset(SyntaxKind::LIFETIME)?;
    let lifetime_arg = ast::LifetimeArg::cast(lifetime_token.parent())?;
    if lifetime_arg.syntax().text() != "'_" {
        return None;
    }
    let next_token = lifetime_token.next_token()?;
    if next_token.kind() != SyntaxKind::R_ANGLE {
        // only allow naming the last anonymous lifetime
        return None;
    }
    let impl_def = lifetime_arg.syntax().ancestors().find_map(ast::ImplDef::cast)?;
    // get the `impl` keyword so we know where to add the lifetime argument
    let impl_kw = impl_def.syntax().first_child_or_token()?.into_token()?;
    if impl_kw.kind() != SyntaxKind::IMPL_KW {
        return None;
    }
    let new_lifetime_param = match impl_def.type_param_list() {
        Some(type_params) => {
            let used_lifetime_params: HashSet<_> = type_params
                .lifetime_params()
                .map(|p| {
                    let mut param_name = p.syntax().text().to_string();
                    param_name.remove(0);
                    param_name
                })
                .collect();
            (b'a'..=b'z')
                .map(char::from)
                .find(|c| !used_lifetime_params.contains(&c.to_string()))?
        }
        None => 'a',
    };
    acc.add(
        AssistId("change_lifetime_anon_to_named"),
        "Give anonymous lifetime a name",
        lifetime_arg.syntax().text_range(),
        |builder| {
            match impl_def.type_param_list() {
                Some(type_params) => {
                    builder.insert(
                        (u32::from(type_params.syntax().text_range().end()) - 1).into(),
                        format!(", '{}", new_lifetime_param),
                    );
                }
                None => {
                    builder
                        .insert(impl_kw.text_range().end(), format!("<'{}>", new_lifetime_param));
                }
            }
            builder.replace(lifetime_arg.syntax().text_range(), format!("'{}", new_lifetime_param));
        },
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::tests::{check_assist, check_assist_not_applicable};

    #[test]
    fn test_example_case() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl Cursor<'_<|>> {
                fn node(self) -> &SyntaxNode {
                    match self {
                        Cursor::Replace(node) | Cursor::Before(node) => node,
                    }
                }
            }"#,
            r#"impl<'a> Cursor<'a> {
                fn node(self) -> &SyntaxNode {
                    match self {
                        Cursor::Replace(node) | Cursor::Before(node) => node,
                    }
                }
            }"#,
        );
    }

    #[test]
    fn test_example_case_simplified() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl Cursor<'_<|>> {"#,
            r#"impl<'a> Cursor<'a> {"#,
        );
    }

    #[test]
    fn test_not_applicable() {
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<'_><|> {"#);
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<|><'_> {"#);
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<'a<|>> {"#);
    }

    #[test]
    fn test_with_type_parameter() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl<T> Cursor<T, '_<|>>"#,
            r#"impl<T, 'a> Cursor<T, 'a>"#,
        );
    }

    #[test]
    fn test_with_existing_lifetime_name_conflict() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl<'a, 'b> Cursor<'a, 'b, '_<|>>"#,
            r#"impl<'a, 'b, 'c> Cursor<'a, 'b, 'c>"#,
        );
    }
}
<commit_msg>add support for naming anon lifetimes in function return type<commit_after>use crate::{assist_context::AssistBuilder, AssistContext, AssistId, Assists};
use ast::{NameOwner, ParamList, TypeAscriptionOwner, TypeParamList, TypeRef};
use ra_syntax::{ast, ast::TypeParamsOwner, AstNode, SyntaxKind, TextRange, TextSize};
use rustc_hash::FxHashSet;

static ASSIST_NAME: &str = "change_lifetime_anon_to_named";
static ASSIST_LABEL: &str = "Give anonymous lifetime a name";

// Assist: change_lifetime_anon_to_named
//
// Change an anonymous lifetime to a named lifetime.
//
// ```
// impl Cursor<'_<|>> {
//     fn node(self) -> &SyntaxNode {
//         match self {
//             Cursor::Replace(node) | Cursor::Before(node) => node,
//         }
//     }
// }
// ```
// ->
// ```
// impl<'a> Cursor<'a> {
//     fn node(self) -> &SyntaxNode {
//         match self {
//             Cursor::Replace(node) | Cursor::Before(node) => node,
//         }
//     }
// }
// ```
// FIXME: How can we handle renaming any one of multiple anonymous lifetimes?
// FIXME: should also add support for the case fun(f: &Foo) -> &<|>Foo
pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let lifetime_token = ctx
        .find_token_at_offset(SyntaxKind::LIFETIME)
        .filter(|lifetime| lifetime.text() == "'_")?;
    if let Some(fn_def) = lifetime_token.ancestors().find_map(ast::FnDef::cast) {
        generate_fn_def_assist(acc, &fn_def, lifetime_token.text_range())
    } else if let Some(impl_def) = lifetime_token.ancestors().find_map(ast::ImplDef::cast) {
        // only allow naming the last anonymous lifetime
        lifetime_token.next_token().filter(|tok| tok.kind() == SyntaxKind::R_ANGLE)?;
        generate_impl_def_assist(acc, &impl_def, lifetime_token.text_range())
    } else {
        None
    }
}

/// Generate the assist for the fn def case
fn generate_fn_def_assist(
    acc: &mut Assists,
    fn_def: &ast::FnDef,
    lifetime_loc: TextRange,
) -> Option<()> {
    let param_list: ParamList = fn_def.param_list()?;
    let new_lifetime_param = generate_unique_lifetime_param_name(&fn_def.type_param_list())?;
    let end_of_fn_ident = fn_def.name()?.ident_token()?.text_range().end();
    let self_param =
        // use the self if it's a reference and has no explicit lifetime
        param_list.self_param().filter(|p| p.lifetime_token().is_none() && p.amp_token().is_some());
    // compute the location which implicitly has the same lifetime as the anonymous lifetime
    let loc_needing_lifetime = if let Some(self_param) = self_param {
        // if we have a self reference, use that
        Some(self_param.self_token()?.text_range().start())
    } else {
        // otherwise, if there's a single reference parameter without a named liftime, use that
        let fn_params_without_lifetime: Vec<_> = param_list
            .params()
            .filter_map(|param| match param.ascribed_type() {
                Some(TypeRef::ReferenceType(ascribed_type))
                    if ascribed_type.lifetime_token() == None =>
                {
                    Some(ascribed_type.amp_token()?.text_range().end())
                }
                _ => None,
            })
            .collect();
        match fn_params_without_lifetime.len() {
            1 => Some(fn_params_without_lifetime.into_iter().nth(0)?),
            0 => None,
            // multiple unnnamed is invalid. assist is not applicable
            _ => return None,
        }
    };
    acc.add(AssistId(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| {
        add_lifetime_param(fn_def, builder, end_of_fn_ident, new_lifetime_param);
        builder.replace(lifetime_loc, format!("'{}", new_lifetime_param));
        loc_needing_lifetime.map(|loc| builder.insert(loc, format!("'{} ", new_lifetime_param)));
    })
}

/// Generate the assist for the impl def case
fn generate_impl_def_assist(
    acc: &mut Assists,
    impl_def: &ast::ImplDef,
    lifetime_loc: TextRange,
) -> Option<()> {
    let new_lifetime_param = generate_unique_lifetime_param_name(&impl_def.type_param_list())?;
    let end_of_impl_kw = impl_def.impl_token()?.text_range().end();
    acc.add(AssistId(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| {
        add_lifetime_param(impl_def, builder, end_of_impl_kw, new_lifetime_param);
        builder.replace(lifetime_loc, format!("'{}", new_lifetime_param));
    })
}

/// Given a type parameter list, generate a unique lifetime parameter name
/// which is not in the list
fn generate_unique_lifetime_param_name(
    existing_type_param_list: &Option<TypeParamList>,
) -> Option<char> {
    match existing_type_param_list {
        Some(type_params) => {
            let used_lifetime_params: FxHashSet<_> = type_params
                .lifetime_params()
                .map(|p| p.syntax().text().to_string()[1..].to_owned())
                .collect();
            (b'a'..=b'z').map(char::from).find(|c| !used_lifetime_params.contains(&c.to_string()))
        }
        None => Some('a'),
    }
}

/// Add the lifetime param to `builder`. If there are type parameters in `type_params_owner`, add it to the end. Otherwise
/// add new type params brackets with the lifetime parameter at `new_type_params_loc`.
fn add_lifetime_param<TypeParamsOwner: ast::TypeParamsOwner>(
    type_params_owner: &TypeParamsOwner,
    builder: &mut AssistBuilder,
    new_type_params_loc: TextSize,
    new_lifetime_param: char,
) {
    match type_params_owner.type_param_list() {
        // add the new lifetime parameter to an existing type param list
        Some(type_params) => {
            builder.insert(
                (u32::from(type_params.syntax().text_range().end()) - 1).into(),
                format!(", '{}", new_lifetime_param),
            );
        }
        // create a new type param list containing only the new lifetime parameter
        None => {
            builder.insert(new_type_params_loc, format!("<'{}>", new_lifetime_param));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::tests::{check_assist, check_assist_not_applicable};

    #[test]
    fn test_example_case() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl Cursor<'_<|>> {
                fn node(self) -> &SyntaxNode {
                    match self {
                        Cursor::Replace(node) | Cursor::Before(node) => node,
                    }
                }
            }"#,
            r#"impl<'a> Cursor<'a> {
                fn node(self) -> &SyntaxNode {
                    match self {
                        Cursor::Replace(node) | Cursor::Before(node) => node,
                    }
                }
            }"#,
        );
    }

    #[test]
    fn test_example_case_simplified() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl Cursor<'_<|>> {"#,
            r#"impl<'a> Cursor<'a> {"#,
        );
    }

    #[test]
    fn test_example_case_cursor_after_tick() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl Cursor<'<|>_> {"#,
            r#"impl<'a> Cursor<'a> {"#,
        );
    }

    #[test]
    fn test_example_case_cursor_before_tick() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl Cursor<<|>'_> {"#,
            r#"impl<'a> Cursor<'a> {"#,
        );
    }

    #[test]
    fn test_not_applicable_cursor_position() {
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<'_><|> {"#);
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<|><'_> {"#);
    }

    #[test]
    fn test_not_applicable_lifetime_already_name() {
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<'a<|>> {"#);
        check_assist_not_applicable(
            change_lifetime_anon_to_named,
            r#"fn my_fun<'a>() -> X<'a<|>>"#,
        );
    }

    #[test]
    fn test_with_type_parameter() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl<T> Cursor<T, '_<|>>"#,
            r#"impl<T, 'a> Cursor<T, 'a>"#,
        );
    }

    #[test]
    fn test_with_existing_lifetime_name_conflict() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl<'a, 'b> Cursor<'a, 'b, '_<|>>"#,
            r#"impl<'a, 'b, 'c> Cursor<'a, 'b, 'c>"#,
        );
    }

    #[test]
    fn test_function_return_value_anon_lifetime_param() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"fn my_fun() -> X<'_<|>>"#,
            r#"fn my_fun<'a>() -> X<'a>"#,
        );
    }

    #[test]
    fn test_function_return_value_anon_reference_lifetime() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"fn my_fun() -> &'_<|> X"#,
            r#"fn my_fun<'a>() -> &'a X"#,
        );
    }

    #[test]
    fn test_function_param_anon_lifetime() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"fn my_fun(x: X<'_<|>>)"#,
            r#"fn my_fun<'a>(x: X<'a>)"#,
        );
    }

    #[test]
    fn test_function_add_lifetime_to_params() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"fn my_fun(f: &Foo) -> X<'_<|>>"#,
            r#"fn my_fun<'a>(f: &'a Foo) -> X<'a>"#,
        );
    }

    #[test]
    fn test_function_add_lifetime_to_params_in_presence_of_other_lifetime() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"fn my_fun<'other>(f: &Foo, b: &'other Bar) -> X<'_<|>>"#,
            r#"fn my_fun<'other, 'a>(f: &'a Foo, b: &'other Bar) -> X<'a>"#,
        );
    }

    #[test]
    fn test_function_not_applicable_without_self_and_multiple_unnamed_param_lifetimes() {
        // this is not permitted under lifetime elision rules
        check_assist_not_applicable(
            change_lifetime_anon_to_named,
            r#"fn my_fun(f: &Foo, b: &Bar) -> X<'_<|>>"#,
        );
    }

    #[test]
    fn test_function_add_lifetime_to_self_ref_param() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"fn my_fun<'other>(&self, f: &Foo, b: &'other Bar) -> X<'_<|>>"#,
            r#"fn my_fun<'other, 'a>(&'a self, f: &Foo, b: &'other Bar) -> X<'a>"#,
        );
    }

    #[test]
    fn test_function_add_lifetime_to_param_with_non_ref_self() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"fn my_fun<'other>(self, f: &Foo, b: &'other Bar) -> X<'_<|>>"#,
            r#"fn my_fun<'other, 'a>(self, f: &'a Foo, b: &'other Bar) -> X<'a>"#,
        );
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::hash_map::{Entry, HashMap};
use std::collections::hash_set::HashSet;
use std::rc::Rc;
use std::cmp;
use std::mem;

use js_types::js_type::{JsVar, JsType, JsPtrEnum};
use uuid::Uuid;

// Initial Arena size in bytes
const INITIAL_SIZE: usize = 1024;
// Minimum Arena capacity is at least 1 byte
const MIN_CAP: usize = 1;

pub type Alloc<T> = Rc<RefCell<T>>;

pub struct Scope {
    parent: Option<Rc<Scope>>,
    children: Vec<Box<Scope>>,
    black_set: HashMap<Uuid, Alloc<JsVar>>,
    grey_set: HashMap<Uuid, Alloc<JsVar>>,
    white_set: HashMap<Uuid, Alloc<JsVar>>,
    get_roots: Box<Fn() -> HashSet<Uuid>>,
}

impl Scope {
    pub fn new<F>(get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: None,
            children: Vec::new(),
            black_set: HashMap::new(),
            grey_set: HashMap::new(),
            white_set: HashMap::new(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn as_child<F>(parent: Rc<Scope>, get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: Some(parent),
            children: Vec::new(),
            black_set: HashMap::new(),
            grey_set: HashMap::new(),
            white_set: HashMap::new(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn set_parent(&mut self, parent: Rc<Scope>) {
        self.parent = Some(parent);
    }

    pub fn add_child(&mut self, child: Scope) {
        self.children.push(Box::new(child));
    }

    pub fn alloc(&mut self, var: JsVar) -> Uuid {
        let uuid = var.uuid;
        self.white_set.insert(uuid, Rc::new(RefCell::new(var)));
        uuid
    }

    pub fn dealloc(&mut self, uuid: &Uuid) -> bool {
        if let Some(_) = self.white_set.remove(uuid) { true } else { false }
    }

    pub fn get_var_copy(&self, uuid: &Uuid) -> Option<JsVar> {
        self.find_id(uuid).map(|var|
                               (*var.clone()).clone().into_inner())
    }

    pub fn update_var(&mut self, var: JsVar) -> bool {
        if let Entry::Occupied(mut view) = self.find_id_mut(&var.uuid) {
            let inner = view.get_mut();
            *inner.borrow_mut() = var;
            true
        } else { false }
    }

    /// TODO Compute the roots of the current scope-- any variable that is
    /// directly referenced or declared within the scope. This might just be the
    /// key set of the uuid map(?) Not necessarily, I think. What if you do
    /// something like this:
    /// var x = {}
    /// var y = { 1: x }
    /// y = x
    /// y would be a root by the definition above, but is no longer reachable at
    /// the end of the scope because it now aliases x. A better definition would
    /// be "Any variable that is declared or referenced directly, but a direct
    /// reference (variable usage) supercedes a declaration." The above example
    /// demonstrates why this is necessary.
    /// This should come from the interpreter, so I shouldn't actually have to
    /// care about getting the root set myself.

    /// Roots always get marked as Black, since they're always reachable from
    /// the current scope. NB that this assumes all root references are actually
    /// valid reference types, i.e. they're not numbers, etc.
    pub fn mark_roots(&mut self) {
        let marks = (self.get_roots)();
        for mark in marks.iter() {
            if let Some(var) = self.white_set.remove(mark) {
                let uuid = var.borrow().uuid;
                // Get all child references
                let child_ids = Scope::get_var_children(&var);
                // Mark current ref as black
                self.black_set.insert(uuid, var);
                // Mark child references as grey
                self.grey_children(child_ids);
            }
        }
    }

    pub fn mark_phase(&mut self) {
        // Mark any grey object as black, and mark all white objs it refs as grey
        let mut new_grey_set = HashMap::new();
        for (uuid, var) in self.grey_set.drain() {
            let child_ids = Scope::get_var_children(&var);
            self.black_set.insert(uuid, var);
            for child_id in child_ids {
                if let Some(var) = self.white_set.remove(&child_id) {
                    new_grey_set.insert(child_id, var);
                }
            }
        }
        self.grey_set = new_grey_set;
    }

    pub fn sweep_phase(&mut self) {
        self.white_set = HashMap::new();
    }

    pub fn find_id(&self, uuid: &Uuid) -> Option<&Alloc<JsVar>> {
        self.white_set.get(uuid).or_else(||
            self.grey_set.get(uuid).or_else(||
                self.black_set.get(uuid)))
    }

    fn find_id_mut(&mut self, uuid: &Uuid) -> Entry<Uuid, Alloc<JsVar>> {
        if let e @ Entry::Occupied(_) = self.white_set.entry(*uuid) {
            e
        } else if let e @ Entry::Occupied(_) = self.grey_set.entry(*uuid) {
            e
        } else { self.black_set.entry(*uuid) }
    }

    fn grey_children(&mut self, child_ids: HashSet<Uuid>) {
        for child_id in child_ids.iter() {
            if let Some(var) = self.white_set.remove(child_id) {
                self.grey_set.insert(*child_id, var);
            }
        }
    }

    fn get_var_children(var: &Alloc<JsVar>) -> HashSet<Uuid> {
        if let JsType::JsPtr(ref ptr) = (*var.borrow()).t {
            match ptr {
                &JsPtrEnum::JsObj(ref obj) => obj.get_children(),
                _ => HashSet::new(),
            }
        } else { HashSet::new() }
    }

}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::hash_set::HashSet;
    use std::rc::Rc;
    use js_types::js_type::{JsVar, JsType, JsPtrEnum, JsKey, JsKeyEnum};
    use js_types::js_obj::{JsObjStruct};
    use uuid::Uuid;

    fn dummy_get_roots() -> HashSet<Uuid> {
        HashSet::new()
    }

    fn make_num(i: f64) -> JsVar {
        JsVar::new(JsType::JsNum(i))
    }

    fn make_obj(kvs: Vec<(JsKey, Alloc<JsVar>)>) -> JsVar {
        JsVar::new(JsType::JsPtr(JsPtrEnum::JsObj(JsObjStruct::new(None, "test", kvs))))
    }

    #[test]
    fn test_new_scope() {
        let mut test_scope = Scope::new(dummy_get_roots);
        assert!(test_scope.parent.is_none());
        assert!(test_scope.black_set.is_empty());
        assert!(test_scope.grey_set.is_empty());
        assert!(test_scope.white_set.is_empty());
        assert_eq!(test_scope.children.len(), 0);
    }

    #[test]
    fn test_as_child_scope() {
        let parent_scope = Scope::new(dummy_get_roots);
        let mut test_scope = Scope::as_child(Rc::new(parent_scope), dummy_get_roots);

        assert!(test_scope.parent.is_some());
        assert!(test_scope.black_set.is_empty());
        assert!(test_scope.grey_set.is_empty());
        assert!(test_scope.white_set.is_empty());
        assert_eq!(test_scope.children.len(), 0);
    }

    #[test]
    fn test_set_parent() {
        let parent_scope = Scope::new(dummy_get_roots);
        let mut test_scope = Scope::new(dummy_get_roots);
        assert!(test_scope.parent.is_none());
        test_scope.set_parent(Rc::new(parent_scope));
        assert!(test_scope.parent.is_some());
    }

    #[test]
    fn test_add_child() {
        let mut test_scope = Scope::new(dummy_get_roots);
        let child_scope1 = Scope::new(dummy_get_roots);
        let child_scope2 = Scope::new(dummy_get_roots);
        assert_eq!(test_scope.children.len(), 0);
        test_scope.add_child(child_scope1);
        assert_eq!(test_scope.children.len(), 1);
        test_scope.add_child(child_scope2);
        assert_eq!(test_scope.children.len(), 2);
    }

    #[test]
    fn test_alloc() {
        let mut test_scope = Scope::new(dummy_get_roots);
        let test_var = make_num(1.0);
        let test_uuid = test_var.uuid.clone();
        let uuid = test_scope.alloc(test_var);
        assert_eq!(test_uuid, uuid);
        assert!(test_scope.white_set.contains_key(&uuid));
        assert_eq!(test_scope.white_set.len(), 1);
        assert_eq!(test_scope.grey_set.len(), 0);
        assert_eq!(test_scope.black_set.len(), 0);
        let test_var2 = make_num(2.0);
        let uuid = test_scope.alloc(test_var2);
        assert!(test_scope.white_set.contains_key(&uuid));
        assert_eq!(test_scope.white_set.len(), 2);
        assert_eq!(test_scope.grey_set.len(), 0);
        assert_eq!(test_scope.black_set.len(), 0);
    }

    #[test]
    fn test_dealloc() {
        let mut test_scope = Scope::new(dummy_get_roots);
        let test_var = make_num(1.0);
        let uuid = test_scope.alloc(test_var);
        let bad_uuid = Uuid::new_v4();
        assert!(test_scope.dealloc(&uuid));
        assert_eq!(test_scope.white_set.len(), 0);
        assert_eq!(test_scope.grey_set.len(), 0);
        assert_eq!(test_scope.black_set.len(), 0);
        assert!(!test_scope.dealloc(&bad_uuid));
    }

    #[test]
    fn test_get_var_copy() {
        let mut test_scope = Scope::new(dummy_get_roots);
        let test_var = make_num(1.0);
        let uuid = test_scope.alloc(test_var);
        let bad_uuid = Uuid::new_v4();
        let var_copy = test_scope.get_var_copy(&uuid);
        assert!(var_copy.is_some());
        let var = var_copy.unwrap();
        assert_eq!(var.uuid, uuid);
        let bad_copy = test_scope.get_var_copy(&bad_uuid);
        assert!(bad_copy.is_none());
    }

    #[test]
    fn test_update_var() {
        let mut test_scope = Scope::new(dummy_get_roots);
        let test_var = make_num(1.0);
        let uuid = test_scope.alloc(test_var);
        let mut update = test_scope.get_var_copy(&uuid).unwrap();
        update = make_num(2.0);
        assert!(test_scope.update_var(update));
        let update = test_scope.get_var_copy(&uuid).unwrap();
        match update {
            JsVar{ t: JsType::JsNum(i), ..} => assert_eq!(i, 2.0),
            _ => ()
        }
        test_scope.dealloc(&uuid);
        assert!(!test_scope.update_var(update));
    }

    #[test]
    fn test_mark_roots() {
        let test_uuid = Uuid::new_v4();
        let mut test_var = make_num(1.0);
        let mut test_var2 = make_num(2.0);
        test_var.uuid = test_uuid;
        let simple_get_roots = move || { let mut set = HashSet::new();
                                    set.insert(test_uuid);
                                    set };
        let mut test_scope = Scope::new(simple_get_roots);
        let test_uuid = test_scope.alloc(test_var);
        let test_uuid2 = test_scope.alloc(test_var2);
        test_scope.mark_roots();
        assert_eq!(test_scope.black_set.len(), 1);
        assert!(test_scope.black_set.get(&test_uuid).is_some());
        assert!(test_scope.black_set.get(&test_uuid2).is_none());
    }

    #[test]
    fn test_mark_phase() {
        let test_uuid = Uuid::new_v4();
        let simple_get_roots = move || { let mut set = HashSet::new();
                                    set.insert(test_uuid);
                                    set };
        let mut test_scope = Scope::new(simple_get_roots);

        let mut test_var2 = make_num(2.0);
        let test_uuid2 = test_scope.alloc(test_var2);
        let test_var2_alloc = test_scope.find_id(&test_uuid2).unwrap().clone();

        let test_key = JsKey::new(JsKeyEnum::JsNum(1.0));
        let mut test_var = make_obj(vec![(test_key, test_var2_alloc)]);
        test_var.uuid = test_uuid;
        let test_uuid = test_scope.alloc(test_var);

        // Mark roots first...
        test_scope.mark_roots();
        assert!(test_scope.black_set.get(&test_uuid).is_some());
        assert_eq!(test_scope.black_set.len(), 1);
        assert_eq!(test_scope.grey_set.len(), 1);

        // ...then mark everything else
        test_scope.mark_phase();

        assert_eq!(test_scope.grey_set.len(), 0);
        assert!(test_scope.black_set.get(&test_uuid).is_some());
        assert!(test_scope.black_set.get(&test_uuid2).is_some());
    }
}
<commit_msg>Fix Scope::update_var test<commit_after>use std::cell::RefCell;
use std::collections::hash_map::{Entry, HashMap};
use std::collections::hash_set::HashSet;
use std::rc::Rc;
use std::cmp;
use std::mem;

use js_types::js_type::{JsVar, JsType, JsPtrEnum};
use uuid::Uuid;

// Initial Arena size in bytes
const INITIAL_SIZE: usize = 1024;
// Minimum Arena capacity is at least 1 byte
const MIN_CAP: usize = 1;

pub type Alloc<T> = Rc<RefCell<T>>;

pub struct Scope {
    parent: Option<Rc<Scope>>,
    children: Vec<Box<Scope>>,
    black_set: HashMap<Uuid, Alloc<JsVar>>,
    grey_set: HashMap<Uuid, Alloc<JsVar>>,
    white_set: HashMap<Uuid, Alloc<JsVar>>,
    get_roots: Box<Fn() -> HashSet<Uuid>>,
}

impl Scope {
    pub fn new<F>(get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: None,
            children: Vec::new(),
            black_set: HashMap::new(),
            grey_set: HashMap::new(),
            white_set: HashMap::new(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn as_child<F>(parent: Rc<Scope>, get_roots: F) -> Scope
        where F: Fn() -> HashSet<Uuid> + 'static {
        Scope {
            parent: Some(parent),
            children: Vec::new(),
            black_set: HashMap::new(),
            grey_set: HashMap::new(),
            white_set: HashMap::new(),
            get_roots: Box::new(get_roots),
        }
    }

    pub fn set_parent(&mut self, parent: Rc<Scope>) {
        self.parent = Some(parent);
    }

    pub fn add_child(&mut self, child: Scope) {
        self.children.push(Box::new(child));
    }

    pub fn alloc(&mut self, var: JsVar) -> Uuid {
        let uuid = var.uuid;
        self.white_set.insert(uuid, Rc::new(RefCell::new(var)));
        uuid
    }

    pub fn dealloc(&mut self, uuid: &Uuid) -> bool {
        if let Some(_) = self.white_set.remove(uuid) { true } else { false }
    }

    pub fn get_var_copy(&self, uuid: &Uuid) -> Option<JsVar> {
        self.find_id(uuid).map(|var|
                               (*var.clone()).clone().into_inner())
    }

    pub fn update_var(&mut self, var: JsVar) -> bool {
        if let Entry::Occupied(mut view) = self.find_id_mut(&var.uuid) {
            let inner = view.get_mut();
            *inner.borrow_mut() = var;
            true
        } else { false }
    }

    /// TODO Compute the roots of the current scope-- any variable that is
    /// directly referenced or declared within the scope. This might just be the
    /// key set of the uuid map(?) Not necessarily, I think. What if you do
    /// something like this:
    /// var x = {}
    /// var y = { 1: x }
    /// y = x
    /// y would be a root by the definition above, but is no longer reachable at
    /// the end of the scope because it now aliases x. A better definition would
    /// be "Any variable that is declared or referenced directly, but a direct
    /// reference (variable usage) supercedes a declaration." The above example
    /// demonstrates why this is necessary.
    /// This should come from the interpreter, so I shouldn't actually have to
    /// care about getting the root set myself.

    /// Roots always get marked as Black, since they're always reachable from
    /// the current scope. NB that this assumes all root references are actually
    /// valid reference types, i.e. they're not numbers, etc.
    pub fn mark_roots(&mut self) {
        let marks = (self.get_roots)();
        for mark in marks.iter() {
            if let Some(var) = self.white_set.remove(mark) {
                let uuid = var.borrow().uuid;
                // Get all child references
                let child_ids = Scope::get_var_children(&var);
                // Mark current ref as black
                self.black_set.insert(uuid, var);
                // Mark child references as grey
                self.grey_children(child_ids);
            }
        }
    }

    pub fn mark_phase(&mut self) {
        // Mark any grey object as black, and mark all white objs it refs as grey
        let mut new_grey_set = HashMap::new();
        for (uuid, var) in self.grey_set.drain() {
            let child_ids = Scope::get_var_children(&var);
            self.black_set.insert(uuid, var);
            for child_id in child_ids {
                if let Some(var) = self.white_set.remove(&child_id) {
                    new_grey_set.insert(child_id, var);
                }
            }
        }
        self.grey_set = new_grey_set;
    }

    pub fn sweep_phase(&mut self) {
        self.white_set = HashMap::new();
    }

    pub fn find_id(&self, uuid: &Uuid) -> Option<&Alloc<JsVar>> {
        self.white_set.get(uuid).or_else(||
            self.grey_set.get(uuid).or_else(||
                self.black_set.get(uuid)))
    }

    fn find_id_mut(&mut self, uuid: &Uuid) -> Entry<Uuid, Alloc<JsVar>> {
        if let e @ Entry::Occupied(_) = self.white_set.entry(*uuid) {
            e
        } else if let e @ Entry::Occupied(_) = self.grey_set.entry(*uuid) {
            e
        } else { self.black_set.entry(*uuid) }
    }

    fn grey_children(&mut self, child_ids: HashSet<Uuid>) {
        for child_id in child_ids.iter() {
            if let Some(var) = self.white_set.remove(child_id) {
                self.grey_set.insert(*child_id, var);
            }
        }
    }

    fn get_var_children(var: &Alloc<JsVar>) -> HashSet<Uuid> {
        if let JsType::JsPtr(ref ptr) = (*var.borrow()).t {
            match ptr {
                &JsPtrEnum::JsObj(ref obj) => obj.get_children(),
                _ => HashSet::new(),
            }
        } else { HashSet::new() }
    }

}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::hash_set::HashSet;
    use std::rc::Rc;
    use js_types::js_type::{JsVar, JsType, JsPtrEnum, JsKey, JsKeyEnum};
    use js_types::js_obj::{JsObjStruct};
    use uuid::Uuid;

    fn dummy_get_roots() -> HashSet<Uuid> {
        HashSet::new()
    }

    fn make_num(i: f64) -> JsVar {
        JsVar::new(JsType::JsNum(i))
    }

    fn make_obj(kvs: Vec<(JsKey, Alloc<JsVar>)>) -> JsVar {
        JsVar::new(JsType::JsPtr(JsPtrEnum::JsObj(JsObjStruct::new(None, "test", kvs))))
    }

    #[test]
    fn test_new_scope() {
        let mut test_scope = Scope::new(dummy_get_roots);
        assert!(test_scope.parent.is_none());
        assert!(test_scope.black_set.is_empty());
        assert!(test_scope.grey_set.is_empty());
        assert!(test_scope.white_set.is_empty());
        assert_eq!(test_scope.children.len(), 0);
    }

    #[test]
    fn test_as_child_scope() {
        let parent_scope = Scope::new(dummy_get_roots);
        let mut test_scope = Scope::as_child(Rc::new(parent_scope), dummy_get_roots);

        assert!(test_scope.parent.is_some());
        assert!(test_scope.black_set.is_empty());
        assert!(test_scope.grey_set.is_empty());
        assert!(test_scope.white_set.is_empty());
        assert_eq!(test_scope.children.len(), 0);
    }

    #[test]
    fn test_set_parent() {
        let parent_scope = Scope::new(dummy_get_roots);
        let mut test_scope = Scope::new(dummy_get_roots);
        assert!(test_scope.parent.is_none());
        test_scope.set_parent(Rc::new(parent_scope));
        assert!(test_scope.parent.is_some());
    }

    #[test]
    fn test_add_child() {
        let mut test_scope = Scope::new(dummy_get_roots);
        let child_scope1 = Scope::new(dummy_get_roots);
        let child_scope2 = Scope::new(dummy_get_roots);
        assert_eq!(test_scope.children.len(), 0);
        test_scope.add_child(child_scope1);
        assert_eq!(test_scope.children.len(), 1);
        test_scope.add_child(child_scope2);
        assert_eq!(test_scope.children.len(), 2);
    }

    #[test]
    fn test_alloc() {
        let mut test_scope = Scope::new(dummy_get_roots);
        let test_var = make_num(1.0);
        let test_uuid = test_var.uuid.clone();
        let uuid = test_scope.alloc(test_var);
        assert_eq!(test_uuid, uuid);
        assert!(test_scope.white_set.contains_key(&uuid));
        assert_eq!(test_scope.white_set.len(), 1);
        assert_eq!(test_scope.grey_set.len(), 0);
        assert_eq!(test_scope.black_set.len(), 0);
        let test_var2 = make_num(2.0);
        let uuid = test_scope.alloc(test_var2);
        assert!(test_scope.white_set.contains_key(&uuid));
        assert_eq!(test_scope.white_set.len(), 2);
        assert_eq!(test_scope.grey_set.len(), 0);
        assert_eq!(test_scope.black_set.len(), 0);
    }

    #[test]
    fn test_dealloc() {
        let mut test_scope = Scope::new(dummy_get_roots);
        let test_var = make_num(1.0);
        let uuid = test_scope.alloc(test_var);
        let bad_uuid = Uuid::new_v4();
        assert!(test_scope.dealloc(&uuid));
        assert_eq!(test_scope.white_set.len(), 0);
        assert_eq!(test_scope.grey_set.len(), 0);
        assert_eq!(test_scope.black_set.len(), 0);
        assert!(!test_scope.dealloc(&bad_uuid));
    }

    #[test]
    fn test_get_var_copy() {
        let mut test_scope = Scope::new(dummy_get_roots);
        let test_var = make_num(1.0);
        let uuid = test_scope.alloc(test_var);
        let bad_uuid = Uuid::new_v4();
        let var_copy = test_scope.get_var_copy(&uuid);
        assert!(var_copy.is_some());
        let var = var_copy.unwrap();
        assert_eq!(var.uuid, uuid);
        let bad_copy = test_scope.get_var_copy(&bad_uuid);
        assert!(bad_copy.is_none());
    }

    #[test]
    fn test_update_var() {
        let mut test_scope = Scope::new(dummy_get_roots);
        let test_var = make_num(1.0);
        let uuid = test_scope.alloc(test_var);
        let mut update = test_scope.get_var_copy(&uuid).unwrap();
        update = make_num(2.0);
        update.uuid = uuid;
        assert!(test_scope.update_var(update));
        let update = test_scope.get_var_copy(&uuid).unwrap();
        match update {
            JsVar{ t: JsType::JsNum(i), ..} => assert_eq!(i, 2.0),
            _ => ()
        }
        test_scope.dealloc(&uuid);
        assert!(!test_scope.update_var(update));
    }

    #[test]
    fn test_mark_roots() {
        let test_uuid = Uuid::new_v4();
        let mut test_var = make_num(1.0);
        let mut test_var2 = make_num(2.0);
        test_var.uuid = test_uuid;
        let simple_get_roots = move || { let mut set = HashSet::new();
                                    set.insert(test_uuid);
                                    set };
        let mut test_scope = Scope::new(simple_get_roots);
        let test_uuid = test_scope.alloc(test_var);
        let test_uuid2 = test_scope.alloc(test_var2);
        test_scope.mark_roots();
        assert_eq!(test_scope.black_set.len(), 1);
        assert!(test_scope.black_set.get(&test_uuid).is_some());
        assert!(test_scope.black_set.get(&test_uuid2).is_none());
    }

    #[test]
    fn test_mark_phase() {
        let test_uuid = Uuid::new_v4();
        let simple_get_roots = move || { let mut set = HashSet::new();
                                    set.insert(test_uuid);
                                    set };
        let mut test_scope = Scope::new(simple_get_roots);

        let mut test_var2 = make_num(2.0);
        let test_uuid2 = test_scope.alloc(test_var2);
        let test_var2_alloc = test_scope.find_id(&test_uuid2).unwrap().clone();

        let test_key = JsKey::new(JsKeyEnum::JsNum(1.0));
        let mut test_var = make_obj(vec![(test_key, test_var2_alloc)]);
        test_var.uuid = test_uuid;
        let test_uuid = test_scope.alloc(test_var);

        // Mark roots first...
        test_scope.mark_roots();
        assert!(test_scope.black_set.get(&test_uuid).is_some());
        assert_eq!(test_scope.black_set.len(), 1);
        assert_eq!(test_scope.grey_set.len(), 1);

        // ...then mark everything else
        test_scope.mark_phase();

        assert_eq!(test_scope.grey_set.len(), 0);
        assert!(test_scope.black_set.get(&test_uuid).is_some());
        assert!(test_scope.black_set.get(&test_uuid2).is_some());
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// 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 serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::{self, Visitor, SeqVisitor, MapVisitor};

use std::marker::PhantomData;

use imp_prelude::*;

use super::arraytraits::ARRAY_FORMAT_VERSION;
use super::Iter;
use Dim;
use dimension::DimPrivate;

/// **Requires crate feature `"serde"`**
impl<I> Serialize for Dim<I>
    where I: Serialize,
{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: Serializer
    {
        self.ix().serialize(serializer)
    }
}

/// **Requires crate feature `"serde"`**
impl<I> Deserialize for Dim<I>
    where I: Deserialize,
{
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer
    {
        I::deserialize(deserializer).map(Dim::new)
    }
}

/// **Requires crate feature `"serde"`**
impl<A, D, S> Serialize for ArrayBase<S, D>
    where A: Serialize,
          D: Dimension + Serialize,
          S: Data<Elem = A>

{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: Serializer
    {
        let mut struct_state = try!(serializer.serialize_struct("Array", 3));
        try!(serializer.serialize_struct_elt(&mut struct_state, "v", ARRAY_FORMAT_VERSION));
        try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.raw_dimension()));
        try!(serializer.serialize_struct_elt(&mut struct_state, "data", Sequence(self.iter())));
        serializer.serialize_struct_end(struct_state)
    }
}

// private iterator wrapper
struct Sequence<'a, A: 'a, D>(Iter<'a, A, D>);

impl<'a, A, D> Serialize for Sequence<'a, A, D>
    where A: Serialize,
          D: Dimension + Serialize
{
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        let iter = &self.0;
        let mut seq_state = try!(serializer.serialize_seq(Some(iter.len())));
        for elt in iter.clone() {
            try!(serializer.serialize_seq_elt(&mut seq_state, elt));
        }
        serializer.serialize_seq_end(seq_state)
    }
}

struct ArrayVisitor<S, Di> {
    _marker_a: PhantomData<S>,
    _marker_b: PhantomData<Di>,
}

enum ArrayField {
    Version,
    Dim,
    Data,
}

impl<S, Di> ArrayVisitor<S, Di> {
    pub fn new() -> Self {
        ArrayVisitor { _marker_a: PhantomData, _marker_b: PhantomData, }
    }
}

/// **Requires crate feature `"serde"`**
impl<A, Di, S> Deserialize for ArrayBase<S, Di>
    where A: Deserialize,
          Di: Deserialize + Dimension,
          S: DataOwned<Elem = A>
{
    fn deserialize<D>(deserializer: &mut D) -> Result<ArrayBase<S, Di>, D::Error>
        where D: Deserializer
    {
        static FIELDS: &'static [&'static str] = &["v", "dim", "data"];

        deserializer.deserialize_struct("Array", FIELDS, ArrayVisitor::new())
    }
}

impl Deserialize for ArrayField {
    fn deserialize<D>(deserializer: &mut D) -> Result<ArrayField, D::Error>
        where D: Deserializer
    {
        struct ArrayFieldVisitor;

        impl Visitor for ArrayFieldVisitor {
            type Value = ArrayField;

            fn visit_str<E>(&mut self, value: &str) -> Result<ArrayField, E>
                where E: de::Error
            {
                match value {
                    "v" => Ok(ArrayField::Version),
                    "data" => Ok(ArrayField::Data),
                    "dim" => Ok(ArrayField::Dim),
                    _ => Err(de::Error::custom("expected v, data, or dim")),
                }
            }
        }

        deserializer.deserialize(ArrayFieldVisitor)
    }
}

impl<A, Di, S> Visitor for ArrayVisitor<S,Di>
    where A: Deserialize,
          Di: Deserialize + Dimension,
          S: DataOwned<Elem = A>
{
    type Value = ArrayBase<S, Di>;

    fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ArrayBase<S, Di>, V::Error>
        where V: SeqVisitor
    {
        let v: u8 = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(de::Error::invalid_length(0));
            }
        };

        if v != ARRAY_FORMAT_VERSION {
            try!(Err(de::Error::custom(format!("unknown array version: {}", v))));
        }

        let dim: Di = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(de::Error::invalid_length(1));
            }
        };

        let data: Vec<A> = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(de::Error::invalid_length(2));
            }
        };

        try!(visitor.end());

        if let Ok(array) = ArrayBase::from_shape_vec(dim, data) {
            Ok(array)
        } else {
            Err(de::Error::custom("data and dimension must match in size"))
        }
    }

    fn visit_map<V>(&mut self, mut visitor: V) -> Result<ArrayBase<S, Di>, V::Error>
        where V: MapVisitor,
    {
        let mut v: Option<u8> = None;
        let mut data: Option<Vec<A>> = None;
        let mut dim: Option<Di> = None;

        while let Some(key) = try!(visitor.visit_key()) {
            match key {
                ArrayField::Version => {
                    let val = try!(visitor.visit_value());
                    if val != ARRAY_FORMAT_VERSION {
                        let err_msg = format!("unknown array version: {}", val);
                        try!(Err(de::Error::custom(err_msg)));
                    }
                    v = Some(val);
                },
                ArrayField::Data => {
                    data = Some(try!(visitor.visit_value()));
                },
                ArrayField::Dim => {
                    dim = Some(try!(visitor.visit_value()));
                },
            }
        }
        try!(visitor.end());

        let _v = match v {
            Some(v) => v,
            None => try!(visitor.missing_field("v")),
        };

        let data = match data {
            Some(data) => data,
            None => try!(visitor.missing_field("data")),
        };

        let dim = match dim {
            Some(dim) => dim,
            None => try!(visitor.missing_field("dim")),
        };

        if let Ok(array) = ArrayBase::from_shape_vec(dim, data) {
            Ok(array)
        } else {
            Err(de::Error::custom("data and dimension must match in size"))
        }
    }
}
<commit_msg>Error on missing fields using the trait instead of the visitor.<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// 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 serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::{self, Visitor, SeqVisitor, MapVisitor};

use std::marker::PhantomData;

use imp_prelude::*;

use super::arraytraits::ARRAY_FORMAT_VERSION;
use super::Iter;
use Dim;
use dimension::DimPrivate;

/// **Requires crate feature `"serde"`**
impl<I> Serialize for Dim<I>
    where I: Serialize,
{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: Serializer
    {
        self.ix().serialize(serializer)
    }
}

/// **Requires crate feature `"serde"`**
impl<I> Deserialize for Dim<I>
    where I: Deserialize,
{
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer
    {
        I::deserialize(deserializer).map(Dim::new)
    }
}

/// **Requires crate feature `"serde"`**
impl<A, D, S> Serialize for ArrayBase<S, D>
    where A: Serialize,
          D: Dimension + Serialize,
          S: Data<Elem = A>

{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: Serializer
    {
        let mut struct_state = try!(serializer.serialize_struct("Array", 3));
        try!(serializer.serialize_struct_elt(&mut struct_state, "v", ARRAY_FORMAT_VERSION));
        try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.raw_dimension()));
        try!(serializer.serialize_struct_elt(&mut struct_state, "data", Sequence(self.iter())));
        serializer.serialize_struct_end(struct_state)
    }
}

// private iterator wrapper
struct Sequence<'a, A: 'a, D>(Iter<'a, A, D>);

impl<'a, A, D> Serialize for Sequence<'a, A, D>
    where A: Serialize,
          D: Dimension + Serialize
{
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        let iter = &self.0;
        let mut seq_state = try!(serializer.serialize_seq(Some(iter.len())));
        for elt in iter.clone() {
            try!(serializer.serialize_seq_elt(&mut seq_state, elt));
        }
        serializer.serialize_seq_end(seq_state)
    }
}

struct ArrayVisitor<S, Di> {
    _marker_a: PhantomData<S>,
    _marker_b: PhantomData<Di>,
}

enum ArrayField {
    Version,
    Dim,
    Data,
}

impl<S, Di> ArrayVisitor<S, Di> {
    pub fn new() -> Self {
        ArrayVisitor { _marker_a: PhantomData, _marker_b: PhantomData, }
    }
}

/// **Requires crate feature `"serde"`**
impl<A, Di, S> Deserialize for ArrayBase<S, Di>
    where A: Deserialize,
          Di: Deserialize + Dimension,
          S: DataOwned<Elem = A>
{
    fn deserialize<D>(deserializer: &mut D) -> Result<ArrayBase<S, Di>, D::Error>
        where D: Deserializer
    {
        static FIELDS: &'static [&'static str] = &["v", "dim", "data"];

        deserializer.deserialize_struct("Array", FIELDS, ArrayVisitor::new())
    }
}

impl Deserialize for ArrayField {
    fn deserialize<D>(deserializer: &mut D) -> Result<ArrayField, D::Error>
        where D: Deserializer
    {
        struct ArrayFieldVisitor;

        impl Visitor for ArrayFieldVisitor {
            type Value = ArrayField;

            fn visit_str<E>(&mut self, value: &str) -> Result<ArrayField, E>
                where E: de::Error
            {
                match value {
                    "v" => Ok(ArrayField::Version),
                    "data" => Ok(ArrayField::Data),
                    "dim" => Ok(ArrayField::Dim),
                    _ => Err(de::Error::custom("expected v, data, or dim")),
                }
            }
        }

        deserializer.deserialize(ArrayFieldVisitor)
    }
}

impl<A, Di, S> Visitor for ArrayVisitor<S,Di>
    where A: Deserialize,
          Di: Deserialize + Dimension,
          S: DataOwned<Elem = A>
{
    type Value = ArrayBase<S, Di>;

    fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ArrayBase<S, Di>, V::Error>
        where V: SeqVisitor
    {
        let v: u8 = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(de::Error::invalid_length(0));
            }
        };

        if v != ARRAY_FORMAT_VERSION {
            try!(Err(de::Error::custom(format!("unknown array version: {}", v))));
        }

        let dim: Di = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(de::Error::invalid_length(1));
            }
        };

        let data: Vec<A> = match try!(visitor.visit()) {
            Some(value) => value,
            None => {
                try!(visitor.end());
                return Err(de::Error::invalid_length(2));
            }
        };

        try!(visitor.end());

        if let Ok(array) = ArrayBase::from_shape_vec(dim, data) {
            Ok(array)
        } else {
            Err(de::Error::custom("data and dimension must match in size"))
        }
    }

    fn visit_map<V>(&mut self, mut visitor: V) -> Result<ArrayBase<S, Di>, V::Error>
        where V: MapVisitor,
    {
        let mut v: Option<u8> = None;
        let mut data: Option<Vec<A>> = None;
        let mut dim: Option<Di> = None;

        while let Some(key) = try!(visitor.visit_key()) {
            match key {
                ArrayField::Version => {
                    let val = try!(visitor.visit_value());
                    if val != ARRAY_FORMAT_VERSION {
                        let err_msg = format!("unknown array version: {}", val);
                        try!(Err(de::Error::custom(err_msg)));
                    }
                    v = Some(val);
                },
                ArrayField::Data => {
                    data = Some(try!(visitor.visit_value()));
                },
                ArrayField::Dim => {
                    dim = Some(try!(visitor.visit_value()));
                },
            }
        }
        try!(visitor.end());

        let _v = match v {
            Some(v) => v,
            None => try!(Err(de::Error::missing_field("v"))),
        };

        let data = match data {
            Some(data) => data,
            None => try!(Err(de::Error::missing_field("data"))),
        };

        let dim = match dim {
            Some(dim) => dim,
            None => try!(Err(de::Error::missing_field("dim"))),
        };

        if let Ok(array) = ArrayBase::from_shape_vec(dim, data) {
            Ok(array)
        } else {
            Err(de::Error::custom("data and dimension must match in size"))
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Tests for async mode.. should be run with RUST_TEST_THREADS=1

pub mod common;

//mines for a bit on each available plugin, one after the other
#[test]
fn on_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("");
	for c in &caps {
		let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		common::mine_async_for_duration(plugin_path_vec, 30, None);
	}
}

//Same as above, but only for cuda
#[test]
fn on_cuda_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("cuda");
	for c in &caps {
	 let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		common::mine_async_for_duration(plugin_path_vec, 60, None);
	}
}

//mine cuda and matrix (mean) miner for a bit
#[test]
fn on_cuda_commit_mine_mean_cpu_and_lean_cuda_async() {
	let caps = common::get_plugin_vec("");
	let mut plugin_path_vec:Vec<&str> = Vec::new();
	for c in &caps {
		if c.full_path.contains("lean_cuda_30") || c.full_path.contains("mean_cpu_30"){
			plugin_path_vec.push(&c.full_path);
		}
	}
	common::mine_async_for_duration(plugin_path_vec, 180, None);
}

//Mines for a bit on all available plugins at once
//(won't be efficient, but should stress-tes plugins nicely)
#[test]
fn on_commit_mine_plugins_async() {
	// Get a list of installed plugins and capabilities
	// only do cuckoo 30s
	let caps = common::get_plugin_vec("30");
	let mut plugin_path_vec:Vec<&str> = Vec::new();
	for c in &caps {
		//Have to confine this for the time being to 2, due to travis CI memory constraints
		if c.full_path.contains("lean_cuda_30") || c.full_path.contains("mean_cpu_30"){
			plugin_path_vec.push(&c.full_path);
		}
	}
	common::mine_async_for_duration(plugin_path_vec, 120, None);
}
<commit_msg>more travis scale-back<commit_after>// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Tests for async mode.. should be run with RUST_TEST_THREADS=1

pub mod common;

//mines for a bit on each available plugin, one after the other
#[test]
fn on_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("");
	for c in &caps {
		let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		common::mine_async_for_duration(plugin_path_vec, 30, None);
	}
}

//Same as above, but only for cuda
#[test]
fn on_cuda_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("cuda");
	for c in &caps {
	 let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		common::mine_async_for_duration(plugin_path_vec, 60, None);
	}
}

//mine cuda and matrix (mean) miner for a bit
#[test]
fn on_cuda_commit_mine_mean_cpu_and_lean_cuda_async() {
	let caps = common::get_plugin_vec("");
	let mut plugin_path_vec:Vec<&str> = Vec::new();
	for c in &caps {
		if c.full_path.contains("lean_cuda_30") || c.full_path.contains("mean_cpu_30"){
			plugin_path_vec.push(&c.full_path);
		}
	}
	common::mine_async_for_duration(plugin_path_vec, 180, None);
}

//Mines for a bit on all available plugins at once
//(won't be efficient, but should stress-tes plugins nicely)
#[test]
fn on_commit_mine_plugins_async() {
	// Get a list of installed plugins and capabilities
	// only do cuckoo 30s
	let caps = common::get_plugin_vec("16");
	let mut plugin_path_vec:Vec<&str> = Vec::new();
	for c in &caps {
		//Have to confine this for the time being to 2, due to travis CI memory constraints
		if c.full_path.contains("lean_cuda") || c.full_path.contains("mean_cpu"){
			plugin_path_vec.push(&c.full_path);
		}
	}
	common::mine_async_for_duration(plugin_path_vec, 120, None);
}
<|endoftext|>