<commit_before>// this exists primarily to test various API usages of scroll; e.g., must compile

// guard against potential undefined behaviour when borrowing from
// packed structs. See https://github.com/rust-lang/rust/issues/46043
#![deny(safe_packed_borrows)]

// #[macro_use] extern crate scroll_derive;

use scroll::ctx::SizeWith;
use scroll::{ctx, Cread, Pread, Result};
use std::ops::{Deref, DerefMut};

#[derive(Default)]
pub struct Section<'a> {
    pub sectname: [u8; 16],
    pub segname: [u8; 16],
    pub addr: u64,
    pub size: u64,
    pub offset: u32,
    pub align: u32,
    pub reloff: u32,
    pub nreloc: u32,
    pub flags: u32,
    pub data: &'a [u8],
}

impl<'a> Section<'a> {
    pub fn name(&self) -> Result<&str> {
        self.sectname.pread::<&str>(0)
    }
    pub fn segname(&self) -> Result<&str> {
        self.segname.pread::<&str>(0)
    }
}

impl<'a> ctx::SizeWith for Section<'a> {
    fn size_with(_ctx: &()) -> usize {
        4
    }
}

#[repr(C)]
// renable when scroll_derive Pread/Pwrite matches
//#[derive(Debug, Clone, Copy, Pread, Pwrite)]
#[derive(Debug, Clone, Copy)]
pub struct Section32 {
    pub sectname: [u8; 16],
    pub segname: [u8; 16],
    pub addr: u32,
    pub size: u32,
    pub offset: u32,
    pub align: u32,
    pub reloff: u32,
    pub nreloc: u32,
    pub flags: u32,
    pub reserved1: u32,
    pub reserved2: u32,
}

impl<'a> ctx::TryFromCtx<'a, ()> for Section<'a> {
    type Error = scroll::Error;
    fn try_from_ctx(
        _bytes: &'a [u8],
        _ctx: (),
    ) -> ::std::result::Result<(Self, usize), Self::Error> {
        let section = Section::default();
        Ok((section, ::std::mem::size_of::<Section>()))
    }
}

pub struct Segment<'a> {
    pub cmd: u32,
    pub cmdsize: u32,
    pub segname: [u8; 16],
    pub vmaddr: u64,
    pub vmsize: u64,
    pub fileoff: u64,
    pub filesize: u64,
    pub maxprot: u32,
    pub initprot: u32,
    pub nsects: u32,
    pub flags: u32,
    pub data: &'a [u8],
    offset: usize,
    raw_data: &'a [u8],
}

impl<'a> Segment<'a> {
    pub fn name(&self) -> Result<&str> {
        Ok(self.segname.pread::<&str>(0)?)
    }
    pub fn sections(&self) -> Result<Vec<Section<'a>>> {
        let nsects = self.nsects as usize;
        let mut sections = Vec::with_capacity(nsects);
        let offset = &mut (self.offset + Self::size_with(&()));
        let _size = Section::size_with(&());
        let raw_data: &'a [u8] = self.raw_data;
        for _ in 0..nsects {
            let section = raw_data.gread_with::<Section<'a>>(offset, ())?;
            sections.push(section);
            //offset += size;
        }
        Ok(sections)
    }
}

impl<'a> ctx::SizeWith for Segment<'a> {
    fn size_with(_ctx: &()) -> usize {
        4
    }
}

pub struct Segments<'a> {
    pub segments: Vec<Segment<'a>>,
}

impl<'a> Deref for Segments<'a> {
    type Target = Vec<Segment<'a>>;
    fn deref(&self) -> &Self::Target {
        &self.segments
    }
}

impl<'a> DerefMut for Segments<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.segments
    }
}

impl<'a> Segments<'a> {
    pub fn new() -> Self {
        Segments {
            segments: Vec::new(),
        }
    }
    pub fn sections(&self) -> Result<Vec<Vec<Section<'a>>>> {
        let mut sections = Vec::new();
        for segment in &self.segments {
            sections.push(segment.sections()?);
        }
        Ok(sections)
    }
}

fn lifetime_passthrough_<'a>(segments: &Segments<'a>, section_name: &str) -> Option<&'a [u8]> {
    let segment_name = "__TEXT";
    for segment in &segments.segments {
        if let Ok(name) = segment.name() {
            println!("segment.name: {}", name);
            if name == segment_name {
                if let Ok(sections) = segment.sections() {
                    for section in sections {
                        let sname = section.name().unwrap();
                        println!("section.name: {}", sname);
                        if section_name == sname {
                            return Some(section.data);
                        }
                    }
                }
            }
        }
    }
    None
}

#[test]
fn lifetime_passthrough() {
    let segments = Segments::new();
    let _res = lifetime_passthrough_(&segments, "__text");
    assert!(true)
}

#[derive(Default)]
#[repr(packed)]
struct Foo {
    foo: i64,
    bar: u32,
}

impl scroll::ctx::FromCtx<scroll::Endian> for Foo {
    fn from_ctx(bytes: &[u8], ctx: scroll::Endian) -> Self {
        Foo {
            foo: bytes.cread_with::<i64>(0, ctx),
            bar: bytes.cread_with::<u32>(8, ctx),
        }
    }
}

impl scroll::ctx::SizeWith<scroll::Endian> for Foo {
    fn size_with(_: &scroll::Endian) -> usize {
        ::std::mem::size_of::<Foo>()
    }
}

#[test]
fn ioread_api() {
    use scroll::{IOread, LE};
    use std::io::Cursor;
    let bytes_ = [
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xbe, 0x00, 0x00,
    ];
    let mut bytes = Cursor::new(bytes_);
    let foo = bytes.ioread_with::<i64>(LE).unwrap();
    let bar = bytes.ioread_with::<u32>(LE).unwrap();
    assert_eq!(foo, 1);
    assert_eq!(bar, 0xbeef);
    let error = bytes.ioread_with::<f64>(LE);
    assert!(error.is_err());
    let mut bytes = Cursor::new(bytes_);
    let foo_ = bytes.ioread_with::<Foo>(LE).unwrap();
    assert_eq!({ foo_.foo }, foo);
    assert_eq!({ foo_.bar }, bar);
}

#[repr(packed)]
struct Bar {
    foo: i32,
    bar: u32,
}

impl scroll::ctx::FromCtx<scroll::Endian> for Bar {
    fn from_ctx(bytes: &[u8], ctx: scroll::Endian) -> Self {
        Bar {
            foo: bytes.cread_with(0, ctx),
            bar: bytes.cread_with(4, ctx),
        }
    }
}

#[test]
fn cread_api() {
    use scroll::{Cread, LE};
    let bytes = [
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xbe, 0x00, 0x00,
    ];
    let foo = bytes.cread_with::<u64>(0, LE);
    let bar = bytes.cread_with::<u32>(8, LE);
    assert_eq!(foo, 1);
    assert_eq!(bar, 0xbeef);
}

#[test]
fn cread_api_customtype() {
    use scroll::{Cread, LE};
    let bytes = [0xff, 0xff, 0xff, 0xff, 0xef, 0xbe, 0xad, 0xde];
    let bar = &bytes[..].cread_with::<Bar>(0, LE);
    assert_eq!({ bar.foo }, -1);
    assert_eq!({ bar.bar }, 0xdeadbeef);
}

#[test]
#[should_panic]
fn cread_api_badindex() {
    use scroll::Cread;
    let bytes = [
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xbe, 0xad, 0xde,
    ];
    let _foo = bytes.cread::<i64>(1_000_000);
}

#[test]
fn cwrite_api() {
    use scroll::Cread;
    use scroll::Cwrite;
    let mut bytes = [0x0; 16];
    bytes.cwrite::<u64>(42, 0);
    bytes.cwrite::<u32>(0xdeadbeef, 8);
    assert_eq!(bytes.cread::<u64>(0), 42);
    assert_eq!(bytes.cread::<u32>(8), 0xdeadbeef);
}

impl scroll::ctx::IntoCtx<scroll::Endian> for Bar {
    fn into_ctx(self, bytes: &mut [u8], ctx: scroll::Endian) {
        use scroll::Cwrite;
        bytes.cwrite_with(self.foo, 0, ctx);
        bytes.cwrite_with(self.bar, 4, ctx);
    }
}

#[test]
fn cwrite_api_customtype() {
    use scroll::{Cread, Cwrite};
    let bar = Bar {
        foo: -1,
        bar: 0xdeadbeef,
    };
    let mut bytes = [0x0; 16];
    &bytes[..].cwrite::<Bar>(bar, 0);
    let bar = bytes.cread::<Bar>(0);
    assert_eq!({ bar.foo }, -1);
    assert_eq!({ bar.bar }, 0xdeadbeef);
}
<commit_msg>tests: fix warning and update to deny(unaligned_references)<commit_after>// this exists primarily to test various API usages of scroll; e.g., must compile

// guard against potential undefined behaviour when borrowing from
// packed structs. See https://github.com/rust-lang/rust/issues/46043
#![deny(unaligned_references)]

// #[macro_use] extern crate scroll_derive;

use scroll::ctx::SizeWith;
use scroll::{ctx, Cread, Pread, Result};
use std::ops::{Deref, DerefMut};

#[derive(Default)]
pub struct Section<'a> {
    pub sectname: [u8; 16],
    pub segname: [u8; 16],
    pub addr: u64,
    pub size: u64,
    pub offset: u32,
    pub align: u32,
    pub reloff: u32,
    pub nreloc: u32,
    pub flags: u32,
    pub data: &'a [u8],
}

impl<'a> Section<'a> {
    pub fn name(&self) -> Result<&str> {
        self.sectname.pread::<&str>(0)
    }
    pub fn segname(&self) -> Result<&str> {
        self.segname.pread::<&str>(0)
    }
}

impl<'a> ctx::SizeWith for Section<'a> {
    fn size_with(_ctx: &()) -> usize {
        4
    }
}

#[repr(C)]
// renable when scroll_derive Pread/Pwrite matches
//#[derive(Debug, Clone, Copy, Pread, Pwrite)]
#[derive(Debug, Clone, Copy)]
pub struct Section32 {
    pub sectname: [u8; 16],
    pub segname: [u8; 16],
    pub addr: u32,
    pub size: u32,
    pub offset: u32,
    pub align: u32,
    pub reloff: u32,
    pub nreloc: u32,
    pub flags: u32,
    pub reserved1: u32,
    pub reserved2: u32,
}

impl<'a> ctx::TryFromCtx<'a, ()> for Section<'a> {
    type Error = scroll::Error;
    fn try_from_ctx(
        _bytes: &'a [u8],
        _ctx: (),
    ) -> ::std::result::Result<(Self, usize), Self::Error> {
        let section = Section::default();
        Ok((section, ::std::mem::size_of::<Section>()))
    }
}

pub struct Segment<'a> {
    pub cmd: u32,
    pub cmdsize: u32,
    pub segname: [u8; 16],
    pub vmaddr: u64,
    pub vmsize: u64,
    pub fileoff: u64,
    pub filesize: u64,
    pub maxprot: u32,
    pub initprot: u32,
    pub nsects: u32,
    pub flags: u32,
    pub data: &'a [u8],
    offset: usize,
    raw_data: &'a [u8],
}

impl<'a> Segment<'a> {
    pub fn name(&self) -> Result<&str> {
        Ok(self.segname.pread::<&str>(0)?)
    }
    pub fn sections(&self) -> Result<Vec<Section<'a>>> {
        let nsects = self.nsects as usize;
        let mut sections = Vec::with_capacity(nsects);
        let offset = &mut (self.offset + Self::size_with(&()));
        let _size = Section::size_with(&());
        let raw_data: &'a [u8] = self.raw_data;
        for _ in 0..nsects {
            let section = raw_data.gread_with::<Section<'a>>(offset, ())?;
            sections.push(section);
            //offset += size;
        }
        Ok(sections)
    }
}

impl<'a> ctx::SizeWith for Segment<'a> {
    fn size_with(_ctx: &()) -> usize {
        4
    }
}

pub struct Segments<'a> {
    pub segments: Vec<Segment<'a>>,
}

impl<'a> Deref for Segments<'a> {
    type Target = Vec<Segment<'a>>;
    fn deref(&self) -> &Self::Target {
        &self.segments
    }
}

impl<'a> DerefMut for Segments<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.segments
    }
}

impl<'a> Segments<'a> {
    pub fn new() -> Self {
        Segments {
            segments: Vec::new(),
        }
    }
    pub fn sections(&self) -> Result<Vec<Vec<Section<'a>>>> {
        let mut sections = Vec::new();
        for segment in &self.segments {
            sections.push(segment.sections()?);
        }
        Ok(sections)
    }
}

fn lifetime_passthrough_<'a>(segments: &Segments<'a>, section_name: &str) -> Option<&'a [u8]> {
    let segment_name = "__TEXT";
    for segment in &segments.segments {
        if let Ok(name) = segment.name() {
            println!("segment.name: {}", name);
            if name == segment_name {
                if let Ok(sections) = segment.sections() {
                    for section in sections {
                        let sname = section.name().unwrap();
                        println!("section.name: {}", sname);
                        if section_name == sname {
                            return Some(section.data);
                        }
                    }
                }
            }
        }
    }
    None
}

#[test]
fn lifetime_passthrough() {
    let segments = Segments::new();
    let _res = lifetime_passthrough_(&segments, "__text");
    assert!(true)
}

#[derive(Default)]
#[repr(packed)]
struct Foo {
    foo: i64,
    bar: u32,
}

impl scroll::ctx::FromCtx<scroll::Endian> for Foo {
    fn from_ctx(bytes: &[u8], ctx: scroll::Endian) -> Self {
        Foo {
            foo: bytes.cread_with::<i64>(0, ctx),
            bar: bytes.cread_with::<u32>(8, ctx),
        }
    }
}

impl scroll::ctx::SizeWith<scroll::Endian> for Foo {
    fn size_with(_: &scroll::Endian) -> usize {
        ::std::mem::size_of::<Foo>()
    }
}

#[test]
fn ioread_api() {
    use scroll::{IOread, LE};
    use std::io::Cursor;
    let bytes_ = [
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xbe, 0x00, 0x00,
    ];
    let mut bytes = Cursor::new(bytes_);
    let foo = bytes.ioread_with::<i64>(LE).unwrap();
    let bar = bytes.ioread_with::<u32>(LE).unwrap();
    assert_eq!(foo, 1);
    assert_eq!(bar, 0xbeef);
    let error = bytes.ioread_with::<f64>(LE);
    assert!(error.is_err());
    let mut bytes = Cursor::new(bytes_);
    let foo_ = bytes.ioread_with::<Foo>(LE).unwrap();
    assert_eq!({ foo_.foo }, foo);
    assert_eq!({ foo_.bar }, bar);
}

#[repr(packed)]
struct Bar {
    foo: i32,
    bar: u32,
}

impl scroll::ctx::FromCtx<scroll::Endian> for Bar {
    fn from_ctx(bytes: &[u8], ctx: scroll::Endian) -> Self {
        Bar {
            foo: bytes.cread_with(0, ctx),
            bar: bytes.cread_with(4, ctx),
        }
    }
}

#[test]
fn cread_api() {
    use scroll::{Cread, LE};
    let bytes = [
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xbe, 0x00, 0x00,
    ];
    let foo = bytes.cread_with::<u64>(0, LE);
    let bar = bytes.cread_with::<u32>(8, LE);
    assert_eq!(foo, 1);
    assert_eq!(bar, 0xbeef);
}

#[test]
fn cread_api_customtype() {
    use scroll::{Cread, LE};
    let bytes = [0xff, 0xff, 0xff, 0xff, 0xef, 0xbe, 0xad, 0xde];
    let bar = &bytes[..].cread_with::<Bar>(0, LE);
    assert_eq!({ bar.foo }, -1);
    assert_eq!({ bar.bar }, 0xdeadbeef);
}

#[test]
#[should_panic]
fn cread_api_badindex() {
    use scroll::Cread;
    let bytes = [
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xbe, 0xad, 0xde,
    ];
    let _foo = bytes.cread::<i64>(1_000_000);
}

#[test]
fn cwrite_api() {
    use scroll::Cread;
    use scroll::Cwrite;
    let mut bytes = [0x0; 16];
    bytes.cwrite::<u64>(42, 0);
    bytes.cwrite::<u32>(0xdeadbeef, 8);
    assert_eq!(bytes.cread::<u64>(0), 42);
    assert_eq!(bytes.cread::<u32>(8), 0xdeadbeef);
}

impl scroll::ctx::IntoCtx<scroll::Endian> for Bar {
    fn into_ctx(self, bytes: &mut [u8], ctx: scroll::Endian) {
        use scroll::Cwrite;
        bytes.cwrite_with(self.foo, 0, ctx);
        bytes.cwrite_with(self.bar, 4, ctx);
    }
}

#[test]
fn cwrite_api_customtype() {
    use scroll::{Cread, Cwrite};
    let bar = Bar {
        foo: -1,
        bar: 0xdeadbeef,
    };
    let mut bytes = [0x0; 16];
    let _ = &bytes[..].cwrite::<Bar>(bar, 0);
    let bar = bytes.cread::<Bar>(0);
    assert_eq!({ bar.foo }, -1);
    assert_eq!({ bar.bar }, 0xdeadbeef);
}
<|endoftext|>


<commit_before>extern crate deque;
extern crate rand;

use std::boxed::Box;
use std::mem;
use std::thread;
use std::thread::JoinGuard;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, AtomicUsize, ATOMIC_USIZE_INIT};
use std::sync::atomic::Ordering::SeqCst;

use deque::{Data, BufferPool, Abort, Empty, Worker, Stealer};
use rand::Rng;

#[test]
fn smoke() {
    let pool = BufferPool::<isize>::new();
    let (w, s) = pool.deque();
    assert_eq!(w.pop(), None);
    assert_eq!(s.steal(), Empty);
    w.push(1);
    assert_eq!(w.pop(), Some(1));
    w.push(1);
    assert_eq!(s.steal(), Data(1));
    w.push(1);
    assert_eq!(s.clone().steal(), Data(1));
}

#[test]
fn stealpush() {
    static AMT: isize = 100000;
    let pool = BufferPool::<isize>::new();
    let (w, s) = pool.deque();
    let t = thread::scoped(move || {
        let mut left = AMT;
        while left > 0 {
            match s.steal() {
                Data(i) => {
                    assert_eq!(i, 1);
                    left -= 1;
                }
                Abort | Empty => {}
            }
        }
    });

    for _ in 0..AMT {
        w.push(1);
    }

    t.join()
}

#[test]
fn stealpush_large() {
    static AMT: isize = 100000;
    let pool = BufferPool::<(isize, isize)>::new();
    let (w, s) = pool.deque();
    let t = thread::scoped(move || {
        let mut left = AMT;
        while left > 0 {
            match s.steal() {
                Data((1, 10)) => { left -= 1; }
                Data(..) => panic!(),
                Abort | Empty => {}
            }
        }
    });

    for _ in 0..AMT {
        w.push((1, 10));
    }

    t.join()
}

struct UnsafeAtomicUsize(*mut AtomicUsize);

unsafe impl Send for UnsafeAtomicUsize { }
impl Copy for UnsafeAtomicUsize { }

fn stampede(w: Worker<Box<isize>>, s: Stealer<Box<isize>>,
            nthreads: isize, amt: usize) {
    for _ in 0..amt {
        w.push(Box::new(20));
    }
    let mut remaining = AtomicUsize::new(amt);
    let unsafe_remaining = UnsafeAtomicUsize(&mut remaining);

    let threads = (0..nthreads).map(|_| {
        let s = s.clone();
        thread::scoped(move || {
            unsafe {
                let UnsafeAtomicUsize(unsafe_remaining) = unsafe_remaining;
                while (*unsafe_remaining).load(SeqCst) > 0 {
                    match s.steal() {
                        Data(ref i) if **i == 20 => {
                            (*unsafe_remaining).fetch_sub(1, SeqCst);
                        }
                        Data(..) => panic!(),
                        Abort | Empty => {}
                    }
                }
            }
        })
    }).collect::<Vec<JoinGuard<()>>>();

    while remaining.load(SeqCst) > 0 {
        match w.pop() {
            Some(ref i) if **i == 20 => { remaining.fetch_sub(1, SeqCst); }
            Some(..) => panic!(),
            None => {}
        }
    }

    for thread in threads.into_iter() {
        thread.join()
    }
}

#[test]
fn run_stampede() {
    let pool = BufferPool::<Box<isize>>::new();
    let (w, s) = pool.deque();
    stampede(w, s, 8, 10000);
}

#[test]
fn many_stampede() {
    static AMT: usize = 4;
    let pool = BufferPool::<Box<isize>>::new();
    let threads = (0..AMT).map(|_| {
        let (w, s) = pool.deque();
        thread::scoped(move || {
            stampede(w, s, 4, 10000);
        })
    }).collect::<Vec<JoinGuard<()>>>();

    for thread in threads.into_iter() {
        thread.join()
    }
}

#[test]
fn stress() {
    static AMT: isize = 100000;
    static NTHREADS: isize = 8;
    static DONE: AtomicBool = ATOMIC_BOOL_INIT;
    static HITS: AtomicUsize = ATOMIC_USIZE_INIT;
    let pool = BufferPool::<isize>::new();
    let (w, s) = pool.deque();

    let threads = (0..NTHREADS).map(|_| {
        let s = s.clone();
        thread::scoped(move || {
            loop {
                match s.steal() {
                    Data(2) => { HITS.fetch_add(1, SeqCst); }
                    Data(..) => panic!(),
                    _ if DONE.load(SeqCst) => break,
                    _ => {}
                }
            }
        })
    }).collect::<Vec<JoinGuard<()>>>();

    let mut rng = rand::thread_rng();
    let mut expected = 0;
    while expected < AMT {
        if rng.gen_range(0, 3) == 2 {
            match w.pop() {
                None => {}
                Some(2) => { HITS.fetch_add(1, SeqCst); },
                Some(_) => panic!(),
            }
        } else {
            expected += 1;
            w.push(2);
        }
    }

    while HITS.load(SeqCst) < AMT as usize {
        match w.pop() {
            None => {}
            Some(2) => { HITS.fetch_add(1, SeqCst); },
            Some(_) => panic!(),
        }
    }
    DONE.store(true, SeqCst);

    for thread in threads.into_iter() {
        thread.join()
    }

    assert_eq!(HITS.load(SeqCst), expected as usize);
}

#[test]
#[cfg_attr(windows, ignore)] // apparently windows scheduling is weird?
fn no_starvation() {
    static AMT: isize = 10000;
    static NTHREADS: isize = 4;
    static DONE: AtomicBool = ATOMIC_BOOL_INIT;
    let pool = BufferPool::<(isize, usize)>::new();
    let (w, s) = pool.deque();

    let (threads, hits): (Vec<_>, Vec<_>) = (0..NTHREADS).map(|_| {
        let s = s.clone();
        let unique_box = Box::new(AtomicUsize::new(0));
        let thread_box = UnsafeAtomicUsize(unsafe {
            *mem::transmute::<&Box<AtomicUsize>,
                              *const *mut AtomicUsize>(&unique_box)
        });
        (thread::scoped(move || {
            unsafe {
                let UnsafeAtomicUsize(thread_box) = thread_box;
                loop {
                    match s.steal() {
                        Data((1, 2)) => {
                            (*thread_box).fetch_add(1, SeqCst);
                        }
                        Data(..) => panic!(),
                        _ if DONE.load(SeqCst) => break,
                        _ => {}
                    }
                }
            }
        }), unique_box)
    }).unzip();

    let mut rng = rand::thread_rng();
    let mut myhit = false;
    'outer: loop {
        for _ in (0..rng.gen_range(0, AMT)) {
            if !myhit && rng.gen_range(0, 3) == 2 {
                match w.pop() {
                    None => {}
                    Some((1, 2)) => myhit = true,
                    Some(_) => panic!(),
                }
            } else {
                w.push((1, 2));
            }
        }

        for slot in hits.iter() {
            let amt = slot.load(SeqCst);
            if amt == 0 { continue 'outer; }
        }
        if myhit {
            break
        }
    }

    DONE.store(true, SeqCst);

    for thread in threads.into_iter() {
        thread.join()
    }
}
<commit_msg>`UnsafeAtomicUsize` derives `Clone` and `Copy`.<commit_after>#![allow(raw_pointer_derive)]

extern crate deque;
extern crate rand;

use std::boxed::Box;
use std::mem;
use std::thread;
use std::thread::JoinGuard;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, AtomicUsize, ATOMIC_USIZE_INIT};
use std::sync::atomic::Ordering::SeqCst;

use deque::{Data, BufferPool, Abort, Empty, Worker, Stealer};
use rand::Rng;

#[test]
fn smoke() {
    let pool = BufferPool::<isize>::new();
    let (w, s) = pool.deque();
    assert_eq!(w.pop(), None);
    assert_eq!(s.steal(), Empty);
    w.push(1);
    assert_eq!(w.pop(), Some(1));
    w.push(1);
    assert_eq!(s.steal(), Data(1));
    w.push(1);
    assert_eq!(s.clone().steal(), Data(1));
}

#[test]
fn stealpush() {
    static AMT: isize = 100000;
    let pool = BufferPool::<isize>::new();
    let (w, s) = pool.deque();
    let t = thread::scoped(move || {
        let mut left = AMT;
        while left > 0 {
            match s.steal() {
                Data(i) => {
                    assert_eq!(i, 1);
                    left -= 1;
                }
                Abort | Empty => {}
            }
        }
    });

    for _ in 0..AMT {
        w.push(1);
    }

    t.join()
}

#[test]
fn stealpush_large() {
    static AMT: isize = 100000;
    let pool = BufferPool::<(isize, isize)>::new();
    let (w, s) = pool.deque();
    let t = thread::scoped(move || {
        let mut left = AMT;
        while left > 0 {
            match s.steal() {
                Data((1, 10)) => { left -= 1; }
                Data(..) => panic!(),
                Abort | Empty => {}
            }
        }
    });

    for _ in 0..AMT {
        w.push((1, 10));
    }

    t.join()
}

#[derive(Clone, Copy)]
struct UnsafeAtomicUsize(*mut AtomicUsize);

unsafe impl Send for UnsafeAtomicUsize { }

fn stampede(w: Worker<Box<isize>>, s: Stealer<Box<isize>>,
            nthreads: isize, amt: usize) {
    for _ in 0..amt {
        w.push(Box::new(20));
    }
    let mut remaining = AtomicUsize::new(amt);
    let unsafe_remaining = UnsafeAtomicUsize(&mut remaining);

    let threads = (0..nthreads).map(|_| {
        let s = s.clone();
        thread::scoped(move || {
            unsafe {
                let UnsafeAtomicUsize(unsafe_remaining) = unsafe_remaining;
                while (*unsafe_remaining).load(SeqCst) > 0 {
                    match s.steal() {
                        Data(ref i) if **i == 20 => {
                            (*unsafe_remaining).fetch_sub(1, SeqCst);
                        }
                        Data(..) => panic!(),
                        Abort | Empty => {}
                    }
                }
            }
        })
    }).collect::<Vec<JoinGuard<()>>>();

    while remaining.load(SeqCst) > 0 {
        match w.pop() {
            Some(ref i) if **i == 20 => { remaining.fetch_sub(1, SeqCst); }
            Some(..) => panic!(),
            None => {}
        }
    }

    for thread in threads.into_iter() {
        thread.join()
    }
}

#[test]
fn run_stampede() {
    let pool = BufferPool::<Box<isize>>::new();
    let (w, s) = pool.deque();
    stampede(w, s, 8, 10000);
}

#[test]
fn many_stampede() {
    static AMT: usize = 4;
    let pool = BufferPool::<Box<isize>>::new();
    let threads = (0..AMT).map(|_| {
        let (w, s) = pool.deque();
        thread::scoped(move || {
            stampede(w, s, 4, 10000);
        })
    }).collect::<Vec<JoinGuard<()>>>();

    for thread in threads.into_iter() {
        thread.join()
    }
}

#[test]
fn stress() {
    static AMT: isize = 100000;
    static NTHREADS: isize = 8;
    static DONE: AtomicBool = ATOMIC_BOOL_INIT;
    static HITS: AtomicUsize = ATOMIC_USIZE_INIT;
    let pool = BufferPool::<isize>::new();
    let (w, s) = pool.deque();

    let threads = (0..NTHREADS).map(|_| {
        let s = s.clone();
        thread::scoped(move || {
            loop {
                match s.steal() {
                    Data(2) => { HITS.fetch_add(1, SeqCst); }
                    Data(..) => panic!(),
                    _ if DONE.load(SeqCst) => break,
                    _ => {}
                }
            }
        })
    }).collect::<Vec<JoinGuard<()>>>();

    let mut rng = rand::thread_rng();
    let mut expected = 0;
    while expected < AMT {
        if rng.gen_range(0, 3) == 2 {
            match w.pop() {
                None => {}
                Some(2) => { HITS.fetch_add(1, SeqCst); },
                Some(_) => panic!(),
            }
        } else {
            expected += 1;
            w.push(2);
        }
    }

    while HITS.load(SeqCst) < AMT as usize {
        match w.pop() {
            None => {}
            Some(2) => { HITS.fetch_add(1, SeqCst); },
            Some(_) => panic!(),
        }
    }
    DONE.store(true, SeqCst);

    for thread in threads.into_iter() {
        thread.join()
    }

    assert_eq!(HITS.load(SeqCst), expected as usize);
}

#[test]
#[cfg_attr(windows, ignore)] // apparently windows scheduling is weird?
fn no_starvation() {
    static AMT: isize = 10000;
    static NTHREADS: isize = 4;
    static DONE: AtomicBool = ATOMIC_BOOL_INIT;
    let pool = BufferPool::<(isize, usize)>::new();
    let (w, s) = pool.deque();

    let (threads, hits): (Vec<_>, Vec<_>) = (0..NTHREADS).map(|_| {
        let s = s.clone();
        let unique_box = Box::new(AtomicUsize::new(0));
        let thread_box = UnsafeAtomicUsize(unsafe {
            *mem::transmute::<&Box<AtomicUsize>,
                              *const *mut AtomicUsize>(&unique_box)
        });
        (thread::scoped(move || {
            unsafe {
                let UnsafeAtomicUsize(thread_box) = thread_box;
                loop {
                    match s.steal() {
                        Data((1, 2)) => {
                            (*thread_box).fetch_add(1, SeqCst);
                        }
                        Data(..) => panic!(),
                        _ if DONE.load(SeqCst) => break,
                        _ => {}
                    }
                }
            }
        }), unique_box)
    }).unzip();

    let mut rng = rand::thread_rng();
    let mut myhit = false;
    'outer: loop {
        for _ in (0..rng.gen_range(0, AMT)) {
            if !myhit && rng.gen_range(0, 3) == 2 {
                match w.pop() {
                    None => {}
                    Some((1, 2)) => myhit = true,
                    Some(_) => panic!(),
                }
            } else {
                w.push((1, 2));
            }
        }

        for slot in hits.iter() {
            let amt = slot.load(SeqCst);
            if amt == 0 { continue 'outer; }
        }
        if myhit {
            break
        }
    }

    DONE.store(true, SeqCst);

    for thread in threads.into_iter() {
        thread.join()
    }
}
<|endoftext|>


<commit_before>extern crate cron;
extern crate chrono;

#[cfg(test)]
mod tests {
  use cron::CronSchedule;
  use chrono::*;

  #[test]
  fn test_parse_with_seconds() {
    let expression = "1 2 3 4 5 6 2015";
    assert!(CronSchedule::parse(expression).is_ok());
  }

  #[test]
  fn test_parse_with_seconds_list() {
    let expression = "1,30,40 2 3 4 5 6 2015";
    assert!(CronSchedule::parse(expression).is_ok());
  }

  #[test]
  fn test_parse_with_lists() {
    let expression = "1 2,17,51 1-3,6,9-11 4,29 2,3,7 6 2015-2017";
    let mut schedule = CronSchedule::parse(expression).unwrap();
    let mut date = UTC::now();
    println!("Fire times for {}:", expression);
    for _ in 0..20 {
      date = schedule.next_utc_after(&date).expect("No further dates!");
      println!("-> {}", date);
    }
    assert!(true);
  }

  #[test]
  fn test_upcoming_iterator() {
    let expression = "2,17,51 1-3,6,9-11 4,29 2,3,7 6 2015-2017";
    let mut schedule = CronSchedule::parse(expression).unwrap();
    println!("Upcoming fire times for '{}':", expression);
    for datetime in schedule.upcoming().take(12) {
      println!("-> {}", datetime);
    }
    assert!(true);
  }

  #[test]
  fn test_parse_without_seconds() {
    let expression = "1 2 3 4 5 2015";
    assert!(CronSchedule::parse(expression).is_ok());
  }

  #[test]
  fn test_parse_too_many_fields() {
    let expression = "1 2 3 4 5 6 7 8 9 2015";
    assert!(CronSchedule::parse(expression).is_err());
  }

  #[test]
  fn test_not_enough_fields() {
    let expression = "1 2 3 2015";
    assert!(CronSchedule::parse(expression).is_err());
  }

  #[test]
  fn test_next_utc() {
    let expression = "1 2 3 4 10 6 2015,2016,2017,2018";
    let mut schedule = CronSchedule::parse(expression).unwrap();
    let next = schedule.next_utc().expect("There was no upcoming fire time.");
    println!("Next fire time: {}", next.to_rfc3339());
  }
}
<commit_msg>Removed unnecessary mut.<commit_after>extern crate cron;
extern crate chrono;

#[cfg(test)]
mod tests {
  use cron::CronSchedule;
  use chrono::*;

  #[test]
  fn test_parse_with_seconds() {
    let expression = "1 2 3 4 5 6 2015";
    assert!(CronSchedule::parse(expression).is_ok());
  }

  #[test]
  fn test_parse_with_seconds_list() {
    let expression = "1,30,40 2 3 4 5 6 2015";
    assert!(CronSchedule::parse(expression).is_ok());
  }

  #[test]
  fn test_parse_with_lists() {
    let expression = "1 2,17,51 1-3,6,9-11 4,29 2,3,7 6 2015-2017";
    let schedule = CronSchedule::parse(expression).unwrap();
    let mut date = UTC::now();
    println!("Fire times for {}:", expression);
    for _ in 0..20 {
      date = schedule.next_utc_after(&date).expect("No further dates!");
      println!("-> {}", date);
    }
    assert!(true);
  }

  #[test]
  fn test_upcoming_iterator() {
    let expression = "2,17,51 1-3,6,9-11 4,29 2,3,7 6 2015-2017";
    let schedule = CronSchedule::parse(expression).unwrap();
    println!("Upcoming fire times for '{}':", expression);
    for datetime in schedule.upcoming().take(12) {
      println!("-> {}", datetime);
    }
    assert!(true);
  }

  #[test]
  fn test_parse_without_seconds() {
    let expression = "1 2 3 4 5 2015";
    assert!(CronSchedule::parse(expression).is_ok());
  }

  #[test]
  fn test_parse_too_many_fields() {
    let expression = "1 2 3 4 5 6 7 8 9 2015";
    assert!(CronSchedule::parse(expression).is_err());
  }

  #[test]
  fn test_not_enough_fields() {
    let expression = "1 2 3 2015";
    assert!(CronSchedule::parse(expression).is_err());
  }

  #[test]
  fn test_next_utc() {
    let expression = "1 2 3 4 10 6 2015,2016,2017,2018";
    let schedule = CronSchedule::parse(expression).unwrap();
    let next = schedule.next_utc().expect("There was no upcoming fire time.");
    println!("Next fire time: {}", next.to_rfc3339());
  }
}
<|endoftext|>


<commit_before>#![feature(plugin, custom_attribute, custom_derive)]
#![feature(convert)]
#![feature(alloc)]
#![plugin(quickcheck_macros)]

extern crate spki_sexp;
extern crate quickcheck;
extern crate rustc_serialize;
extern crate num;

use quickcheck::{Arbitrary, Gen};
use std::{error,fmt};
use std::io::{self, Write};
use std::iter::{Iterator, FromIterator,Peekable};
use std::sync::Arc;
use std::rc::{self, Rc};
use std::result::Result;
use std::collections::HashMap;

use rustc_serialize::{Decodable, Encodable};

use spki_sexp::*;

fn vec8_as_str(v :&Vec<u8>) -> String {
  String::from_utf8_lossy(v).into_owned()
}

#[derive(PartialEq, Eq,Debug, Clone)]
struct Tok(spki_sexp::SexpToken);

fn detok(t: &Tok) -> SexpToken {
  match t {
    &Tok(ref sexp) => sexp.clone()
  }
}

impl quickcheck::Arbitrary for Tok {
  fn arbitrary<G: quickcheck::Gen>(g : &mut G) -> Tok {
    match u64::arbitrary(g) % 3 {
      0 => Tok(SexpToken::OpenParen),
      1 => Tok(SexpToken::CloseParen),
      2 => Tok(SexpToken::Atom(quickcheck::Arbitrary::arbitrary(g))),
      n => panic!("Unexpected value mod 3: {:?}", n)
    }
  }

  fn shrink(&self) -> Box<Iterator<Item=Tok>+'static> {
//    writeln!(std::io::stderr(),"shrink: {:?}", self).unwrap();
    match *self {
      Tok(SexpToken::OpenParen) => quickcheck::empty_shrinker(),
      Tok(SexpToken::CloseParen) => quickcheck::single_shrinker(Tok(SexpToken::OpenParen)),
      Tok(SexpToken::Atom(ref x)) => {
	let chained = quickcheck::single_shrinker(Tok(SexpToken::CloseParen))
		      .chain(quickcheck::single_shrinker(Tok(SexpToken::OpenParen)))
		      .chain(x.shrink().map(SexpToken::Atom).map(Tok));
	Box::new(chained)
      }
    }
  }
}

#[quickcheck]
fn round_trip_tokens(toks : Vec<Tok>) -> bool {
  let toks : Vec<SexpToken> = toks.iter().map(detok).collect();
//   writeln!(std::io::stderr(),"orig: {:?}", toks).unwrap();
  let encd = encode((&toks).iter()).unwrap();
//   writeln!(std::io::stderr(),"{:?}", vec8_as_str(&encd)).unwrap();
  let mut res = Vec::from_iter(tokenise(encd.iter().map(|p|p.clone())));
//   writeln!(std::io::stderr(),"{:?} -> {:?} -> {:?} => {:?}", toks, vec8_as_str(&encd), res, res == toks).unwrap();
  res == toks
}

// struct <'a>(spki_sexp::SexpInfo<'a>);
#[derive(PartialEq, Eq,Debug, Clone)]
pub enum ASexp {
  Atom(Vec<u8>),
  List(Arc<Vec<ASexp>>)
}

impl ASexp {
  fn desexp(&self) -> SexpInfo {
    match self {
      &ASexp::Atom(ref n) => SexpInfo::Atom(n.clone()),
      &ASexp::List(ref l) => SexpInfo::List(Rc::new(l.iter().map(ASexp::desexp).collect()))
    }
  }
}

impl fmt::Display for ASexp {
  fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
     match self {
      &ASexp::Atom(ref n) => String::from_utf8_lossy(n).fmt(fmt),
      &ASexp::List(ref l) => {
	try!(fmt.write_str("("));
	for (n, val) in l.iter().enumerate() {
	  if n != 0 {
	    try!(fmt.write_str(" "))
	  }
	  try!(val.fmt(fmt))

	}
	fmt.write_str(")")
      }
    }
  }
}
thread_local!(static DEPTH: Rc<()> = Rc::new(()));

impl<'a> quickcheck::Arbitrary for ASexp {
  fn arbitrary<G: quickcheck::Gen>(g : &mut G) -> ASexp {
    DEPTH.with(|d| {
      let guard = d.clone();
      let ndeep = rc::strong_count(d);
      // writeln!(std::io::stderr(),"Depth: {:?} / {:?}", ndeep, 1 <<ndeep).unwrap();

      match u64::arbitrary(g) % (1<<ndeep) {
	0 => ASexp::List(Arc::new(Arbitrary::arbitrary(g))),
	_ => {
	  let word : String = Arbitrary::arbitrary(g);
	  ASexp::Atom(word.into_bytes())
	}
      }
    })
  }

  fn shrink(&self) -> Box<Iterator<Item=ASexp>+'static> {
//    writeln!(std::io::stderr(),"shrink: {:?}", self).unwrap();
    match *self {
      ASexp::Atom(ref x) => {
	let chained = quickcheck::empty_shrinker()
		      .chain(x.shrink().map(ASexp::Atom));
	Box::new(chained)
      }
      ASexp::List(ref l) => {
	let chained = l.shrink().map(|l| ASexp::List(Arc::new(l)))
		      .chain(quickcheck::single_shrinker(ASexp::Atom("shrunken-list".to_string().into_bytes())))
		      .map(|x| { writeln!(std::io::stderr(),"shrunk: {:?}", x).unwrap(); x }) ;
	Box::new(chained)
      }
    }
  }
}

#[quickcheck]
fn round_trip_sexp_tree(val : ASexp) -> bool {
  let v = val.desexp();
  // writeln!(std::io::stderr(),"wheee: {:?}", val).unwrap();
  let mut buf = vec![];
  v.write_to(&mut buf).unwrap();
  // writeln!(std::io::stderr(),"wheee: {:?}", vec8_as_str(&buf)).unwrap();
  let decd = SexpInfo::read_from(&mut io::Cursor::new(buf.clone())).unwrap();
  // writeln!(std::io::stderr(),"result: {:?} -> {:?} -> {:?}; {:?}", v, vec8_as_str(&buf), decd, v == decd).unwrap();
  decd == v
}

fn round_trip_prop<T : fmt::Debug + Encodable + Decodable + PartialEq>(val: T, verbose: bool, equalish: fn(&T, &T) -> bool) -> bool{
  let encd = spki_sexp::to_bytes(&val).unwrap();
  if verbose { writeln!(std::io::stderr(),"round_trip: {:?} -> {:?}", val, vec8_as_str(&encd)).unwrap(); };
  let dec = spki_sexp::from_bytes::<T>(encd.as_slice());
  if verbose { writeln!(std::io::stderr(),"{:?} -> {:?} -> {:?}", val, vec8_as_str(&encd), dec).unwrap(); };
  if let Ok(decoded) = dec {
    if verbose { writeln!(std::io::stderr(),"-> {:?}", equalish(&decoded, &val)).unwrap(); };
    equalish(&decoded, &val)
  } else {
    if verbose { writeln!(std::io::stderr(),"-> {:?}", dec).unwrap(); };
    false
  }
}

fn round_trip_prop_eq<T : fmt::Debug + Encodable + Decodable + PartialEq>(val: T, verbose: bool) -> bool{
  round_trip_prop(val, verbose, std::cmp::PartialEq::eq)
}

trait Epsilon { fn eps() -> Self; }

impl Epsilon for f64 { fn eps() -> f64 { 0.00001f64 } }
impl Epsilon for f32 { fn eps() -> f32 { 0.0001f32 } }

fn close_enough<T>(x: &T, y: &T) -> bool where T: num::Float + Epsilon {
  let max = x.abs().max(y.abs());
  if max == T::zero() {
    true
  } else {
    let delta = x.abs_sub(*y) / max;
    delta <= T::eps()
  }
}

#[quickcheck] fn round_trip_unit(val: ()) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_bool(val: bool) -> bool { round_trip_prop_eq(val, false) }

#[quickcheck] fn round_trip_usize(val: usize) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_u64(val: u64) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_u8(val: u8) -> bool { round_trip_prop_eq(val, false) }

#[quickcheck] fn round_trip_isize(val: isize) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_i64(val: i64) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_i8(val: i8) -> bool { round_trip_prop_eq(val, false) }

#[quickcheck] fn round_trip_f64(val: f64) -> bool { round_trip_prop(val, false, close_enough::<f64>) }
#[quickcheck] fn round_trip_f32(val: f32) -> bool { round_trip_prop(val, true, close_enough::<f32>) }

#[quickcheck] fn round_trip_char(val: char) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_string(val: String) -> bool { round_trip_prop_eq(val, false) }

#[quickcheck] fn round_trip_tuple_u64_u64(val: (u64,u64)) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_vec_u64(val: Vec<u64>) -> bool { round_trip_prop_eq(val, false) }

#[quickcheck] fn round_trip_option_u64(val: Option<u64>) -> bool { round_trip_prop_eq(val, false) }
#[test] fn parse_bad_none() { assert!(spki_sexp::from_bytes::<Option<u64>>(b"5:nodnol").is_err()) }
#[test] fn parse_bad_some_insufficient_items() { assert!(spki_sexp::from_bytes::<Option<u64>>(b"(4:some)").is_err()) }
#[test] fn parse_bad_some_too_many_items() { assert!(spki_sexp::from_bytes::<Option<u64>>(b"(4:some1:14:spam)").is_err()) }
#[test] fn parse_bad_some_bad_label() { assert!(spki_sexp::from_bytes::<Option<u64>>(b"(3:lol1:2)").is_err()) }
#[test] fn parse_bad_some_ok() { assert_eq!(spki_sexp::from_bytes::<Option<u64>>(b"(4:some2:99)").unwrap(), Some(99)) }

#[quickcheck] fn round_trip_map_u64_u64(val: HashMap<u64,u64>) -> bool { round_trip_prop_eq(val, false) }

#[derive(PartialEq,Eq,Debug,RustcEncodable,RustcDecodable)]
struct TupleStruct(i32, i32, String);
#[quickcheck] fn round_trip_tpl_struct(val: (i32,i32, String)) -> bool { match val { (a,b,c) => round_trip_prop_eq(TupleStruct(a,b,c), false) } }
#[derive(PartialEq,Eq,Debug,RustcEncodable,RustcDecodable)]
struct NameStruct { x: String, y: String }
#[quickcheck] fn round_trip_name_struct(val: (String, String)) -> bool { match val { (a,b) => round_trip_prop_eq(NameStruct{x:a,y:b}, false) } }

#[derive(Clone,PartialEq,Eq,Debug,RustcEncodable,RustcDecodable)]
enum SomeEnum {
  Foo,
  Bar(String),
  Baz { some: i32 }
}

impl quickcheck::Arbitrary for SomeEnum {
  fn arbitrary<G: quickcheck::Gen>(g : &mut G) -> SomeEnum {
    match u64::arbitrary(g) % 3 {
      0 => SomeEnum::Foo,
      1 => SomeEnum::Bar(quickcheck::Arbitrary::arbitrary(g)),
      2 => SomeEnum::Baz { some: quickcheck::Arbitrary::arbitrary(g) },
      n => panic!("Unexpected value mod 2: {:?}", n)
    }
  }

  fn shrink(&self) -> Box<Iterator<Item=SomeEnum>+'static> {
//    writeln!(std::io::stderr(),"shrink: {:?}", self).unwrap();
    match *self {
      SomeEnum::Foo => quickcheck::empty_shrinker(),
      SomeEnum::Bar(ref x) => {
        let chained = quickcheck::single_shrinker(SomeEnum::Foo)
                      .chain(x.shrink().map(SomeEnum::Bar));
        Box::new(chained)
      }
      SomeEnum::Baz { some: x } => {
        let chained = quickcheck::single_shrinker(SomeEnum::Foo)
                      .chain(x.shrink().map(|n| SomeEnum::Baz { some: n}));
        Box::new(chained)
      }
    }
  }
}

#[quickcheck] fn round_trip_some_enum(val: SomeEnum) -> bool { round_trip_prop_eq(val, false) }
<commit_msg>Add benchmarks.<commit_after>#![feature(plugin, custom_attribute, custom_derive)]
#![feature(convert)]
#![feature(alloc)]
#![feature(test)]
#![plugin(quickcheck_macros)]

extern crate spki_sexp;
extern crate quickcheck;
extern crate rustc_serialize;
extern crate num;
extern crate test;

use quickcheck::{Arbitrary, Gen};
use std::{error,fmt};
use std::io::{self, Write};
use std::iter::{Iterator, FromIterator,Peekable};
use std::sync::Arc;
use std::rc::{self, Rc};
use std::result::Result;
use std::collections::HashMap;
use std::iter;

use rustc_serialize::{Decodable, Encodable};
use test::Bencher;

use spki_sexp::*;
use spki_sexp::SexpInfo::*;

fn vec8_as_str(v :&Vec<u8>) -> String {
  String::from_utf8_lossy(v).into_owned()
}

#[derive(PartialEq, Eq,Debug, Clone)]
struct Tok(spki_sexp::SexpToken);

fn detok(t: &Tok) -> SexpToken {
  match t {
    &Tok(ref sexp) => sexp.clone()
  }
}

impl quickcheck::Arbitrary for Tok {
  fn arbitrary<G: quickcheck::Gen>(g : &mut G) -> Tok {
    match u64::arbitrary(g) % 3 {
      0 => Tok(SexpToken::OpenParen),
      1 => Tok(SexpToken::CloseParen),
      2 => Tok(SexpToken::Atom(quickcheck::Arbitrary::arbitrary(g))),
      n => panic!("Unexpected value mod 3: {:?}", n)
    }
  }

  fn shrink(&self) -> Box<Iterator<Item=Tok>+'static> {
//    writeln!(std::io::stderr(),"shrink: {:?}", self).unwrap();
    match *self {
      Tok(SexpToken::OpenParen) => quickcheck::empty_shrinker(),
      Tok(SexpToken::CloseParen) => quickcheck::single_shrinker(Tok(SexpToken::OpenParen)),
      Tok(SexpToken::Atom(ref x)) => {
	let chained = quickcheck::single_shrinker(Tok(SexpToken::CloseParen))
		      .chain(quickcheck::single_shrinker(Tok(SexpToken::OpenParen)))
		      .chain(x.shrink().map(SexpToken::Atom).map(Tok));
	Box::new(chained)
      }
    }
  }
}

#[quickcheck]
fn round_trip_tokens(toks : Vec<Tok>) -> bool {
  let toks : Vec<SexpToken> = toks.iter().map(detok).collect();
//   writeln!(std::io::stderr(),"orig: {:?}", toks).unwrap();
  let encd = encode((&toks).iter()).unwrap();
//   writeln!(std::io::stderr(),"{:?}", vec8_as_str(&encd)).unwrap();
  let mut res = Vec::from_iter(tokenise(encd.iter().map(|p|p.clone())));
//   writeln!(std::io::stderr(),"{:?} -> {:?} -> {:?} => {:?}", toks, vec8_as_str(&encd), res, res == toks).unwrap();
  res == toks
}

// struct <'a>(spki_sexp::SexpInfo<'a>);
#[derive(PartialEq, Eq,Debug, Clone)]
pub enum ASexp {
  Atom(Vec<u8>),
  List(Arc<Vec<ASexp>>)
}

impl ASexp {
  fn desexp(&self) -> SexpInfo {
    match self {
      &ASexp::Atom(ref n) => SexpInfo::Atom(n.clone()),
      &ASexp::List(ref l) => SexpInfo::List(Rc::new(l.iter().map(ASexp::desexp).collect()))
    }
  }
}

impl fmt::Display for ASexp {
  fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
     match self {
      &ASexp::Atom(ref n) => String::from_utf8_lossy(n).fmt(fmt),
      &ASexp::List(ref l) => {
	try!(fmt.write_str("("));
	for (n, val) in l.iter().enumerate() {
	  if n != 0 {
	    try!(fmt.write_str(" "))
	  }
	  try!(val.fmt(fmt))

	}
	fmt.write_str(")")
      }
    }
  }
}
thread_local!(static DEPTH: Rc<()> = Rc::new(()));

impl<'a> quickcheck::Arbitrary for ASexp {
  fn arbitrary<G: quickcheck::Gen>(g : &mut G) -> ASexp {
    DEPTH.with(|d| {
      let guard = d.clone();
      let ndeep = rc::strong_count(d);
      // writeln!(std::io::stderr(),"Depth: {:?} / {:?}", ndeep, 1 <<ndeep).unwrap();

      match u64::arbitrary(g) % (1<<ndeep) {
	0 => ASexp::List(Arc::new(Arbitrary::arbitrary(g))),
	_ => {
	  let word : String = Arbitrary::arbitrary(g);
	  ASexp::Atom(word.into_bytes())
	}
      }
    })
  }

  fn shrink(&self) -> Box<Iterator<Item=ASexp>+'static> {
//    writeln!(std::io::stderr(),"shrink: {:?}", self).unwrap();
    match *self {
      ASexp::Atom(ref x) => {
	let chained = quickcheck::empty_shrinker()
		      .chain(x.shrink().map(ASexp::Atom));
	Box::new(chained)
      }
      ASexp::List(ref l) => {
	let chained = l.shrink().map(|l| ASexp::List(Arc::new(l)))
		      .chain(quickcheck::single_shrinker(ASexp::Atom("shrunken-list".to_string().into_bytes())))
		      .map(|x| { writeln!(std::io::stderr(),"shrunk: {:?}", x).unwrap(); x }) ;
	Box::new(chained)
      }
    }
  }
}

#[quickcheck]
fn round_trip_sexp_tree(val : ASexp) -> bool {
  let v = val.desexp();
  // writeln!(std::io::stderr(),"wheee: {:?}", val).unwrap();
  let mut buf = vec![];
  v.write_to(&mut buf).unwrap();
  // writeln!(std::io::stderr(),"wheee: {:?}", vec8_as_str(&buf)).unwrap();
  let decd = SexpInfo::read_from(&mut io::Cursor::new(buf.clone())).unwrap();
  // writeln!(std::io::stderr(),"result: {:?} -> {:?} -> {:?}; {:?}", v, vec8_as_str(&buf), decd, v == decd).unwrap();
  decd == v
}

fn round_trip_prop<T : fmt::Debug + Encodable + Decodable + PartialEq>(val: T, verbose: bool, equalish: fn(&T, &T) -> bool) -> bool{
  let encd = spki_sexp::to_bytes(&val).unwrap();
  if verbose { writeln!(std::io::stderr(),"round_trip: {:?} -> {:?}", val, vec8_as_str(&encd)).unwrap(); };
  let dec = spki_sexp::from_bytes::<T>(encd.as_slice());
  if verbose { writeln!(std::io::stderr(),"{:?} -> {:?} -> {:?}", val, vec8_as_str(&encd), dec).unwrap(); };
  if let Ok(decoded) = dec {
    if verbose { writeln!(std::io::stderr(),"-> {:?}", equalish(&decoded, &val)).unwrap(); };
    equalish(&decoded, &val)
  } else {
    if verbose { writeln!(std::io::stderr(),"-> {:?}", dec).unwrap(); };
    false
  }
}

fn round_trip_prop_eq<T : fmt::Debug + Encodable + Decodable + PartialEq>(val: T, verbose: bool) -> bool{
  round_trip_prop(val, verbose, std::cmp::PartialEq::eq)
}

trait Epsilon { fn eps() -> Self; }

impl Epsilon for f64 { fn eps() -> f64 { 0.00001f64 } }
impl Epsilon for f32 { fn eps() -> f32 { 0.0001f32 } }

fn close_enough<T>(x: &T, y: &T) -> bool where T: num::Float + Epsilon {
  let max = x.abs().max(y.abs());
  if max == T::zero() {
    true
  } else {
    let delta = x.abs_sub(*y) / max;
    delta <= T::eps()
  }
}

#[quickcheck] fn round_trip_unit(val: ()) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_bool(val: bool) -> bool { round_trip_prop_eq(val, false) }

#[quickcheck] fn round_trip_usize(val: usize) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_u64(val: u64) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_u8(val: u8) -> bool { round_trip_prop_eq(val, false) }

#[quickcheck] fn round_trip_isize(val: isize) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_i64(val: i64) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_i8(val: i8) -> bool { round_trip_prop_eq(val, false) }

#[quickcheck] fn round_trip_f64(val: f64) -> bool { round_trip_prop(val, false, close_enough::<f64>) }
#[quickcheck] fn round_trip_f32(val: f32) -> bool { round_trip_prop(val, false, close_enough::<f32>) }

#[quickcheck] fn round_trip_char(val: char) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_string(val: String) -> bool { round_trip_prop_eq(val, false) }

#[quickcheck] fn round_trip_tuple_u64_u64(val: (u64,u64)) -> bool { round_trip_prop_eq(val, false) }
#[quickcheck] fn round_trip_vec_u64(val: Vec<u64>) -> bool { round_trip_prop_eq(val, false) }

#[quickcheck] fn round_trip_option_u64(val: Option<u64>) -> bool { round_trip_prop_eq(val, false) }
#[test] fn parse_bad_none() { assert!(spki_sexp::from_bytes::<Option<u64>>(b"5:nodnol").is_err()) }
#[test] fn parse_bad_some_insufficient_items() { assert!(spki_sexp::from_bytes::<Option<u64>>(b"(4:some)").is_err()) }
#[test] fn parse_bad_some_too_many_items() { assert!(spki_sexp::from_bytes::<Option<u64>>(b"(4:some1:14:spam)").is_err()) }
#[test] fn parse_bad_some_bad_label() { assert!(spki_sexp::from_bytes::<Option<u64>>(b"(3:lol1:2)").is_err()) }
#[test] fn parse_bad_some_ok() { assert_eq!(spki_sexp::from_bytes::<Option<u64>>(b"(4:some2:99)").unwrap(), Some(99)) }

#[quickcheck] fn round_trip_map_u64_u64(val: HashMap<u64,u64>) -> bool { round_trip_prop_eq(val, false) }

#[derive(PartialEq,Eq,Debug,RustcEncodable,RustcDecodable)]
struct TupleStruct(i32, i32, String);
#[quickcheck] fn round_trip_tpl_struct(val: (i32,i32, String)) -> bool { match val { (a,b,c) => round_trip_prop_eq(TupleStruct(a,b,c), false) } }
#[derive(PartialEq,Eq,Debug,RustcEncodable,RustcDecodable)]
struct NameStruct { x: String, y: String }
#[quickcheck] fn round_trip_name_struct(val: (String, String)) -> bool { match val { (a,b) => round_trip_prop_eq(NameStruct{x:a,y:b}, false) } }

#[derive(Clone,PartialEq,Eq,Debug,RustcEncodable,RustcDecodable)]
enum SomeEnum {
  Foo,
  Bar(String),
  Baz { some: i32 }
}

impl quickcheck::Arbitrary for SomeEnum {
  fn arbitrary<G: quickcheck::Gen>(g : &mut G) -> SomeEnum {
    match u64::arbitrary(g) % 3 {
      0 => SomeEnum::Foo,
      1 => SomeEnum::Bar(quickcheck::Arbitrary::arbitrary(g)),
      2 => SomeEnum::Baz { some: quickcheck::Arbitrary::arbitrary(g) },
      n => panic!("Unexpected value mod 2: {:?}", n)
    }
  }

  fn shrink(&self) -> Box<Iterator<Item=SomeEnum>+'static> {
//    writeln!(std::io::stderr(),"shrink: {:?}", self).unwrap();
    match *self {
      SomeEnum::Foo => quickcheck::empty_shrinker(),
      SomeEnum::Bar(ref x) => {
        let chained = quickcheck::single_shrinker(SomeEnum::Foo)
                      .chain(x.shrink().map(SomeEnum::Bar));
        Box::new(chained)
      }
      SomeEnum::Baz { some: x } => {
        let chained = quickcheck::single_shrinker(SomeEnum::Foo)
                      .chain(x.shrink().map(|n| SomeEnum::Baz { some: n}));
        Box::new(chained)
      }
    }
  }
}

#[quickcheck] fn round_trip_some_enum(val: SomeEnum) -> bool { round_trip_prop_eq(val, false) }

fn bench_emit(b: &mut Bencher, v: SexpInfo) {
  let mut buf = vec![];
  v.write_to(&mut buf).unwrap();

  b.bytes = buf.len() as u64;
// writeln!(std::io::stderr(),"size: {:?}", buf.len()).unwrap();
  b.iter(|| v.write_to(&mut buf).unwrap() )
}

fn bench_read(b: &mut Bencher, v: SexpInfo) {
  let mut buf = vec![];
  v.write_to(&mut buf).unwrap();

  b.bytes = buf.len() as u64;
  writeln!(std::io::stderr(),"size: {:?}", buf.len()).unwrap();
  b.iter(|| SexpInfo::read_from(&mut io::Cursor::new(buf.clone())).unwrap() )
}
#[bench]
fn bench_emit_atom(b: &mut Bencher) {
  bench_emit(b, Atom("hello world!".into()));
}

#[bench]
fn bench_read_atom(b: &mut Bencher) {
  bench_read(b, Atom("Hello world!".into()))
}

#[bench]
fn bench_emit_list(b: &mut Bencher) {
  let a = Atom("hello world!".into());
  let l = List(Rc::new(iter::repeat(a).take(64).collect()));
  bench_emit(b, l);
}

#[bench]
fn bench_read_list(b: &mut Bencher) {
  let a = Atom("hello world!".into());
  let l = List(Rc::new(iter::repeat(a).take(64).collect()));
  bench_read(b, l)
}
#[bench]
fn bench_emit_nested(b: &mut Bencher) {
  let a = Atom("hello world!".into());
  let l = List(Rc::new(iter::repeat(a).take(8).collect()));
  let l = List(Rc::new(iter::repeat(l).take(8).collect()));
  let l = List(Rc::new(iter::repeat(l).take(8).collect()));
  bench_emit(b, l);
}

#[bench]
fn bench_read_nested(b: &mut Bencher) {
  let a = Atom("hello world!".into());
  let l = List(Rc::new(iter::repeat(a).take(8).collect()));
  let l = List(Rc::new(iter::repeat(l).take(8).collect()));
  let l = List(Rc::new(iter::repeat(l).take(8).collect()));
  bench_read(b, l)
}
<|endoftext|>


<commit_before>use std::process::Command;
use std::fs;

fn test_output(result: &str, expected: &str) {
    assert!(Command::new("cmp")
            .arg(result)
            .arg(expected)
            .spawn().unwrap().wait().unwrap().success());
    fs::remove_file(result).unwrap();
}

fn run_cmd(cmd: &str, prefix: Option<&str>) -> bool {
    let build = if cfg!(debug_assertions) { "debug" } else { "release" };

    println!("{}", cmd);

    Command::new("bash")
            .arg("-c")
            .arg(format!(
                "{prefix}target/{build}/{cmd}",
                prefix=prefix.unwrap_or(""),
                cmd=cmd,
                build=build
            ))
            .spawn().unwrap().wait().unwrap().success()
}

fn run_exp(dataset: &str, codebook: &str, params: &str) -> bool {
    run_cmd(
        &format!(
            "merfishtools -v exp -t 1 {codebook} --estimate {est} --stats {stats} {params} < {raw} > {cdf}",
            codebook=format!("tests/codebook/{}.txt", codebook),
            raw=format!("tests/data/{}.txt", dataset),
            cdf=format!("tests/results/{}.txt", dataset),
            est=format!("tests/results/{}.est.txt", dataset),
            stats=format!("tests/results/{}.stats.txt", dataset),
            params=params
        ),
        None
    )
}

#[test]
fn test_exp_mhd4_cell0() {
    assert!(run_exp("140genesData.1.cell0", "140genesData.1", "--p0 0.01258132102084181 0.013360438064572837 0.019941605919281354 0.016581551788592854 0.22860571489439577 0.22269171721737882 0.2073701214077358 0.02231576033300221 0.017689514891827997 0.02054328192011981 0.02101414200654054 0.03938992313394839 0.023995219270935196 0.03557793748730565 0.17007370565085334 0.03569158826173908 --p1 0.5912118122316706 0.5063863207089024 0.42338772914919315 0.43282699715628403 0.17843503208026912 0.18766044306365068 0.1989449380102563 0.42262699427628003 0.4930707032134955 0.4034046655581933 0.4610572590564446 0.30553305919201673 0.2931349183480258 0.2634814096058736 0.16619112507647252 0.36410395236487053"));
    //assert!(run_exp("140genesData.1.cell0", "140genesData.1", "--p0 0.016 0.015 0.021 0.015 0.051 0.065 0.062 0.026 0.019 0.021 0.023 0.034 0.02 0.029 0.07 0.027 --p1 0.05 0.04 0.065 0.052 0.177 0.135 0.155 0.07 0.053 0.057 0.066 0.09 0.069 0.07 0.145 0.103"));
    //assert!(run_exp("140genesData.1.cell0", "140genesData.1", "--p0 0.1 --p1 0.6"));
}

#[test]
fn test_exp_mhd4_thbs_bias() {
    assert!(run_exp("140genesData.1.cell24", "140genesData.1", "--p0 0.016 0.015 0.021 0.015 0.051 0.065 0.062 0.026 0.019 0.021 0.023 0.034 0.02 0.029 0.07 0.027 --p1 0.05 0.04 0.065 0.052 0.177 0.135 0.155 0.07 0.053 0.057 0.066 0.09 0.069 0.07 0.145 0.103"));
}

#[test]
fn test_exp_mhd2() {
    assert!(run_exp("1001genesData.3.cell0", "1001genesData", ""));
}

/// This is a longrunning test that should be activated only on purpose.
fn test_exp_mhd2_8() {
    assert!(run_exp("simulated-MHD2-8.25.all", "simulated-MHD2-8", "--p0 0.005 --p1 0.01"));
}

#[test]
fn test_exp_mhd4_sim() {
    assert!(run_exp("simulated-MHD4.35.1", "simulated-MHD4", "--p0 0.04 --p1 0.1"));
}

#[test]
fn test_estimate_error_rates_real() {
    assert!(run_cmd(
        "merfishtools -v est-error-rates tests/codebook/140genesData.1.txt > tests/results/140genesData.error-rates.tsv",
        Some("grep -P '^3\\t' tests/data/140genesData.readouts.txt | cut -f2,3,4 | ")
    ));
}

#[test]
fn test_estimate_error_rates_simulated() {
    assert!(run_cmd(
        "merfishtools -v est-error-rates tests/codebook/140genesData.1.txt < tests/data/simulated-MHD4.35.readouts.txt > tests/results/simulated-MHD4.35.error-rates.tsv",
        None
    ));
}
<commit_msg>Minor<commit_after>use std::process::Command;
use std::fs;

fn test_output(result: &str, expected: &str) {
    assert!(Command::new("cmp")
            .arg(result)
            .arg(expected)
            .spawn().unwrap().wait().unwrap().success());
    fs::remove_file(result).unwrap();
}

fn run_cmd(cmd: &str, prefix: Option<&str>) -> bool {
    let build = if cfg!(debug_assertions) { "debug" } else { "release" };

    println!("{}", cmd);

    Command::new("bash")
            .arg("-c")
            .arg(format!(
                "{prefix}target/{build}/{cmd}",
                prefix=prefix.unwrap_or(""),
                cmd=cmd,
                build=build
            ))
            .spawn().unwrap().wait().unwrap().success()
}

fn run_exp(dataset: &str, codebook: &str, params: &str) -> bool {
    run_cmd(
        &format!(
            "merfishtools -v exp -t 1 {codebook} --estimate {est} --stats {stats} {params} < {raw} > {cdf}",
            codebook=format!("tests/codebook/{}.txt", codebook),
            raw=format!("tests/data/{}.txt", dataset),
            cdf=format!("tests/results/{}.txt", dataset),
            est=format!("tests/results/{}.est.txt", dataset),
            stats=format!("tests/results/{}.stats.txt", dataset),
            params=params
        ),
        None
    )
}

#[test]
fn test_exp_mhd4_cell0() {
    assert!(run_exp("140genesData.1.cell0", "140genesData.1", "--p0 0.01258132102084181 0.013360438064572837 0.019941605919281354 0.016581551788592854 0.22860571489439577 0.22269171721737882 0.2073701214077358 0.02231576033300221 0.017689514891827997 0.02054328192011981 0.02101414200654054 0.03938992313394839 0.023995219270935196 0.03557793748730565 0.17007370565085334 0.03569158826173908 --p1 0.5912118122316706 0.5063863207089024 0.42338772914919315 0.43282699715628403 0.17843503208026912 0.18766044306365068 0.1989449380102563 0.42262699427628003 0.4930707032134955 0.4034046655581933 0.4610572590564446 0.30553305919201673 0.2931349183480258 0.2634814096058736 0.16619112507647252 0.36410395236487053"));
    //assert!(run_exp("140genesData.1.cell0", "140genesData.1", "--p0 0.016 0.015 0.021 0.015 0.051 0.065 0.062 0.026 0.019 0.021 0.023 0.034 0.02 0.029 0.07 0.027 --p1 0.05 0.04 0.065 0.052 0.177 0.135 0.155 0.07 0.053 0.057 0.066 0.09 0.069 0.07 0.145 0.103"));
    //assert!(run_exp("140genesData.1.cell0", "140genesData.1", "--p0 0.1 --p1 0.6"));
}

#[test]
fn test_exp_mhd4_thbs_bias() {
    assert!(run_exp("140genesData.1.cell24", "140genesData.1", "--p0 0.01258132102084181 0.013360438064572837 0.019941605919281354 0.016581551788592854 0.22860571489439577 0.22269171721737882 0.2073701214077358 0.02231576033300221 0.017689514891827997 0.02054328192011981 0.02101414200654054 0.03938992313394839 0.023995219270935196 0.03557793748730565 0.17007370565085334 0.03569158826173908 --p1 0.5912118122316706 0.5063863207089024 0.42338772914919315 0.43282699715628403 0.17843503208026912 0.18766044306365068 0.1989449380102563 0.42262699427628003 0.4930707032134955 0.4034046655581933 0.4610572590564446 0.30553305919201673 0.2931349183480258 0.2634814096058736 0.16619112507647252 0.36410395236487053"));
}

#[test]
fn test_exp_mhd2() {
    assert!(run_exp("1001genesData.3.cell0", "1001genesData", ""));
}

/// This is a longrunning test that should be activated only on purpose.
fn test_exp_mhd2_8() {
    assert!(run_exp("simulated-MHD2-8.25.all", "simulated-MHD2-8", "--p0 0.005 --p1 0.01"));
}

#[test]
fn test_exp_mhd4_sim() {
    assert!(run_exp("simulated-MHD4.35.1", "simulated-MHD4", "--p0 0.04 --p1 0.1"));
}

#[test]
fn test_estimate_error_rates_real() {
    assert!(run_cmd(
        "merfishtools -v est-error-rates tests/codebook/140genesData.1.txt > tests/results/140genesData.error-rates.tsv",
        Some("grep -P '^3\\t' tests/data/140genesData.readouts.txt | cut -f2,3,4 | ")
    ));
}

#[test]
fn test_estimate_error_rates_simulated() {
    assert!(run_cmd(
        "merfishtools -v est-error-rates tests/codebook/140genesData.1.txt < tests/data/simulated-MHD4.35.readouts.txt > tests/results/simulated-MHD4.35.error-rates.tsv",
        None
    ));
}
<|endoftext|>


<commit_before>
extern crate elastic_responses;

#[macro_use]
extern crate log;

#[macro_use]
extern crate json_str;

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

extern crate slog_stdlog;
extern crate slog_envlogger;

use elastic_responses::*;
use elastic_responses::error::*;
use std::fs::File;
use std::io::{Read, Cursor};

fn load_file_as_response(status: u16, p: &str) -> HttpResponse<Cursor<Vec<u8>>> {
    let mut f = File::open(p).unwrap();
    let mut s = Vec::new();
    f.read_to_end(&mut s).unwrap();

    HttpResponse::new(status, Cursor::new(s))
}

#[test]
fn test_parse_hits_simple() {
    let s = load_file_as_response(200, "tests/samples/hits_only.json");

    let deserialized = SearchResponse::from_response(s).unwrap();

    assert_eq!(deserialized.hits().into_iter().count(), 5);
}

#[test]
fn test_parse_simple_aggs() {
    let s = load_file_as_response(200, "tests/samples/aggregation_simple.json");
    let deserialized = SearchResponse::from_response(s).unwrap();

    assert_eq!(deserialized.aggs().into_iter().count(), 124);
}

#[test]
fn test_parse_3level_aggs() {
    let s = load_file_as_response(200, "tests/samples/aggregation_3level.json");
    let deserialized = SearchResponse::from_response(s).unwrap();

    assert_eq!(deserialized.aggs().into_iter().count(), 201);
}

#[test]
fn test_parse_3level_multichild_aggs() {
    let s = load_file_as_response(200, "tests/samples/aggregation_3level_multichild.json");
    let deserialized = SearchResponse::from_response(s).unwrap();

    let min = "min_ack_pkts_sent";
    let avg = "avg_ack_pkts_sent";
    let max = "max_ack_pkts_sent";
    let mut first = true;
    let mut count = 0;
    for i in deserialized.aggs().into_iter().take(500000) {
        count += 1;
        if first {
            assert!(i.contains_key(min));
            assert!(i.contains_key(max));
            assert!(i.contains_key(avg));
            first = false;
        }
    }
    assert_eq!(count, 201);
}

#[test]
fn test_parse_3level_multistats_aggs() {
    let s = load_file_as_response(200, "tests/samples/aggregation_3level_multistats.json");
    let deserialized = SearchResponse::from_response(s).unwrap();

    let min = "extstats_ack_pkts_sent_min";
    let avg = "stats_ack_pkts_sent_avg";
    let max = "extstats_ack_pkts_sent_max";
    let stddevu = "extstats_ack_pkts_sent_std_deviation_bounds_upper";
    let mut first = true;
    let mut count = 0;
    for i in deserialized.aggs().into_iter().take(500000) {
        count += 1;
        if first {
            assert!(i.contains_key(min));
            assert!(i.contains_key(max));
            assert!(i.contains_key(avg));
            assert!(i.contains_key(stddevu));
            first = false;
        }
    }
    assert_eq!(count, 61);
}

#[test]
fn test_parse_simple_aggs_no_empty_first_record() {
    let s = load_file_as_response(200, "tests/samples/aggregation_simple.json");
    let deserialized = SearchResponse::from_response(s).unwrap();

    let s = "timechart";
    let mut first = true;
    for i in deserialized.aggs().into_iter().take(50) {
        if first {
            assert!(i.contains_key(s));
            first = false;
        }
    }
}

#[test]
fn test_parse_found_doc_response() {
    let s = load_file_as_response(200, "tests/samples/get_found.json");
    let deserialized = GetResponse::from_response(s).unwrap();

    let id = deserialized.source
        .unwrap()
        .as_object()
        .and_then(|src| src.get("id"))
        .and_then(|id| id.as_u64());

    assert!(deserialized.found);
    assert_eq!("testindex", deserialized.index);
    assert_eq!("testtype", deserialized.ty);
    assert_eq!(Some(8), deserialized.version);
    assert_eq!(Some(1), id);
}

#[test]
fn test_parse_not_found_doc_response() {
    let s = load_file_as_response(404, "tests/samples/get_not_found.json");
    let deserialized = GetResponse::from_response(s).unwrap();

    assert!(!deserialized.found);
}

#[test]
fn test_parse_index_not_found_error() {
    let s = load_file_as_response(404, "tests/samples/error_index_not_found.json");
    let deserialized = GetResponse::from_response(s).unwrap_err();

    let valid = match deserialized {
        ResponseError::Api(ApiError::IndexNotFound { ref index })
        if index == "carrots" => true,
        _ => false
    };

    assert!(valid);
}

#[test]
fn test_parse_parsing_error() {
    let s = load_file_as_response(400, "tests/samples/error_parsing.json");
    let deserialized = SearchResponse::from_response(s).unwrap_err();

    let valid = match deserialized {
        ResponseError::Api(ApiError::Parsing { line: 2, col: 9, ref reason })
        if reason == "Unknown key for a START_OBJECT in [qry]." => true,
        _ => false
    };

    assert!(valid);
}

#[test]
fn test_parse_other_error() {
    let s = load_file_as_response(500, "tests/samples/error_other.json");
    let deserialized = SearchResponse::from_response(s).unwrap_err();

    let reason = match deserialized {
        ResponseError::Api(ApiError::Other(ref err)) => err.get("reason")
                                       .and_then(|reason| reason.as_str())
                                       .map(|reason| reason.to_owned()),
        _ => None
    };

    assert_eq!(Some(String::from("An error that we don't know about.")), reason);
}<commit_msg>remove unused crates from tests<commit_after>
extern crate elastic_responses;

#[macro_use]
extern crate json_str;

extern crate serde_json;

use elastic_responses::*;
use elastic_responses::error::*;
use std::fs::File;
use std::io::{Read, Cursor};

fn load_file_as_response(status: u16, p: &str) -> HttpResponse<Cursor<Vec<u8>>> {
    let mut f = File::open(p).unwrap();
    let mut s = Vec::new();
    f.read_to_end(&mut s).unwrap();

    HttpResponse::new(status, Cursor::new(s))
}

#[test]
fn test_parse_hits_simple() {
    let s = load_file_as_response(200, "tests/samples/hits_only.json");

    let deserialized = SearchResponse::from_response(s).unwrap();

    assert_eq!(deserialized.hits().into_iter().count(), 5);
}

#[test]
fn test_parse_simple_aggs() {
    let s = load_file_as_response(200, "tests/samples/aggregation_simple.json");
    let deserialized = SearchResponse::from_response(s).unwrap();

    assert_eq!(deserialized.aggs().into_iter().count(), 124);
}

#[test]
fn test_parse_3level_aggs() {
    let s = load_file_as_response(200, "tests/samples/aggregation_3level.json");
    let deserialized = SearchResponse::from_response(s).unwrap();

    assert_eq!(deserialized.aggs().into_iter().count(), 201);
}

#[test]
fn test_parse_3level_multichild_aggs() {
    let s = load_file_as_response(200, "tests/samples/aggregation_3level_multichild.json");
    let deserialized = SearchResponse::from_response(s).unwrap();

    let min = "min_ack_pkts_sent";
    let avg = "avg_ack_pkts_sent";
    let max = "max_ack_pkts_sent";
    let mut first = true;
    let mut count = 0;
    for i in deserialized.aggs().into_iter().take(500000) {
        count += 1;
        if first {
            assert!(i.contains_key(min));
            assert!(i.contains_key(max));
            assert!(i.contains_key(avg));
            first = false;
        }
    }
    assert_eq!(count, 201);
}

#[test]
fn test_parse_3level_multistats_aggs() {
    let s = load_file_as_response(200, "tests/samples/aggregation_3level_multistats.json");
    let deserialized = SearchResponse::from_response(s).unwrap();

    let min = "extstats_ack_pkts_sent_min";
    let avg = "stats_ack_pkts_sent_avg";
    let max = "extstats_ack_pkts_sent_max";
    let stddevu = "extstats_ack_pkts_sent_std_deviation_bounds_upper";
    let mut first = true;
    let mut count = 0;
    for i in deserialized.aggs().into_iter().take(500000) {
        count += 1;
        if first {
            assert!(i.contains_key(min));
            assert!(i.contains_key(max));
            assert!(i.contains_key(avg));
            assert!(i.contains_key(stddevu));
            first = false;
        }
    }
    assert_eq!(count, 61);
}

#[test]
fn test_parse_simple_aggs_no_empty_first_record() {
    let s = load_file_as_response(200, "tests/samples/aggregation_simple.json");
    let deserialized = SearchResponse::from_response(s).unwrap();

    let s = "timechart";
    let mut first = true;
    for i in deserialized.aggs().into_iter().take(50) {
        if first {
            assert!(i.contains_key(s));
            first = false;
        }
    }
}

#[test]
fn test_parse_found_doc_response() {
    let s = load_file_as_response(200, "tests/samples/get_found.json");
    let deserialized = GetResponse::from_response(s).unwrap();

    let id = deserialized.source
        .unwrap()
        .as_object()
        .and_then(|src| src.get("id"))
        .and_then(|id| id.as_u64());

    assert!(deserialized.found);
    assert_eq!("testindex", deserialized.index);
    assert_eq!("testtype", deserialized.ty);
    assert_eq!(Some(8), deserialized.version);
    assert_eq!(Some(1), id);
}

#[test]
fn test_parse_not_found_doc_response() {
    let s = load_file_as_response(404, "tests/samples/get_not_found.json");
    let deserialized = GetResponse::from_response(s).unwrap();

    assert!(!deserialized.found);
}

#[test]
fn test_parse_index_not_found_error() {
    let s = load_file_as_response(404, "tests/samples/error_index_not_found.json");
    let deserialized = GetResponse::from_response(s).unwrap_err();

    let valid = match deserialized {
        ResponseError::Api(ApiError::IndexNotFound { ref index })
        if index == "carrots" => true,
        _ => false
    };

    assert!(valid);
}

#[test]
fn test_parse_parsing_error() {
    let s = load_file_as_response(400, "tests/samples/error_parsing.json");
    let deserialized = SearchResponse::from_response(s).unwrap_err();

    let valid = match deserialized {
        ResponseError::Api(ApiError::Parsing { line: 2, col: 9, ref reason })
        if reason == "Unknown key for a START_OBJECT in [qry]." => true,
        _ => false
    };

    assert!(valid);
}

#[test]
fn test_parse_other_error() {
    let s = load_file_as_response(500, "tests/samples/error_other.json");
    let deserialized = SearchResponse::from_response(s).unwrap_err();

    let reason = match deserialized {
        ResponseError::Api(ApiError::Other(ref err)) => err.get("reason")
                                       .and_then(|reason| reason.as_str())
                                       .map(|reason| reason.to_owned()),
        _ => None
    };

    assert_eq!(Some(String::from("An error that we don't know about.")), reason);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;
//extern crate serialize;

use nom::{IResult,FlatMapper,Mapper,Producer,ProducerState,FileProducer};
use nom::IResult::*;

use std::str;
use std::collections::HashMap;
//use serialize::hex::ToHex;

pub trait HexDisplay {
      /// Converts the value of `self` to a hex value, returning the owned
      ///     /// string.
  fn to_hex(&self, chunk_size: usize) -> String;
}

static CHARS: &'static[u8] = b"0123456789abcdef";

impl HexDisplay for [u8] {
    fn to_hex(&self, chunk_size: usize) -> String {
      let mut v = Vec::with_capacity(self.len() * 3);
      for chunk in self.chunks(chunk_size) {
        for &byte in chunk {
          v.push(CHARS[(byte >> 4) as usize]);
          v.push(CHARS[(byte & 0xf) as usize]);
          v.push(' ' as u8);
        }
        if chunk_size > chunk.len() {
          for i in 0..(chunk_size - chunk.len()) {
            v.push(' ' as u8);
            v.push(' ' as u8);
            v.push(' ' as u8);
          }
        }
        v.push('\t' as u8);

        for &byte in chunk {
          if (byte >=32 && byte <= 126) || byte >= 128 {
            v.push(byte);
          } else {
            v.push('.' as u8);
          }
        }
        v.push('\n' as u8);
      }

      unsafe {
        String::from_utf8_unchecked(v)
      }
    }
}

#[derive(PartialEq,Eq,Debug)]
struct Brand<'a> {
  major:   &'a str,
  version: &'a [u8]
}
take!(offset 4);
tag!(ftyp    "ftyp".as_bytes());

fn major_brand(input:&[u8]) -> IResult<&[u8],&str> {
  take!(major_brand_bytes 4);
  major_brand_bytes(input).map_res(str::from_utf8)
}
take!(major_brand_version 4);

fn brand<'a>(input: &'a[u8]) -> IResult<&'a [u8], Brand<'a> > {
  chaining_parser!(input, ||{Brand{major: m, version:v}}, m: major_brand, v: major_brand_version,)
}

o!(begin <&[u8], Brand>  offset ~ ftyp ~ [ brand ]);

fn parse_mp4_file(filename: &str) {
  FileProducer::new(filename, 100).map(|producer: FileProducer| {
    let mut p = producer;
    match p.produce() {
      ProducerState::Data(bytes) => {
        println!("bytes:\n{}", bytes.to_hex(8));
        match begin(bytes) {
          Done(i, o) => {
            //println!("parsed: {:?}\n{}", o, i.to_hex(8))
            println!("parsed: {:?}\n", o)
          },
          a          => println!("error: {:?}", a)
        }
      },
      _                          => println!("got error")
    }
    /*//p.push(|par| {println!("parsed file: {}", par); par});
    //p.push(|par| par.flat_map(print));
    fn pr<'a,'b,'c>(data: &[u8]) -> IResult<'b,&[u8], &[u8]> {
      println!("bytes: {:?}", &data[0..20]);
      //Done("".as_bytes(), data).map_res(str::from_utf8);
      Done("".as_bytes(),"".as_bytes())
    }
    pusher!(ps, pr);
    ps(&mut p);
    */
    assert!(false);
  });

}
#[test]
fn file_test() {
  parse_mp4_file("small.mp4");
}
#[test]
fn bunny_test() {
  parse_mp4_file("bigbuckbunny.mp4");
}
<commit_msg>add address number<commit_after>#[macro_use]
extern crate nom;
//extern crate serialize;

use nom::{IResult,FlatMapper,Mapper,Producer,ProducerState,FileProducer};
use nom::IResult::*;

use std::str;
use std::collections::HashMap;
//use serialize::hex::ToHex;

pub trait HexDisplay {
      /// Converts the value of `self` to a hex value, returning the owned
      ///     /// string.
  fn to_hex(&self, chunk_size: usize) -> String;
}

static CHARS: &'static[u8] = b"0123456789abcdef";

impl HexDisplay for [u8] {
    fn to_hex(&self, chunk_size: usize) -> String {
      let mut v = Vec::with_capacity(self.len() * 3);
      let mut i = 0;
      for chunk in self.chunks(chunk_size) {
        let s = format!("{:08x}", i);
        let s2: &str = &s;
        for &ch in s.as_bytes().iter() {
          v.push(ch);
        }
        v.push('\t' as u8);

        i = i + chunk_size;

        for &byte in chunk {
          v.push(CHARS[(byte >> 4) as usize]);
          v.push(CHARS[(byte & 0xf) as usize]);
          v.push(' ' as u8);
        }
        if chunk_size > chunk.len() {
          for i in 0..(chunk_size - chunk.len()) {
            v.push(' ' as u8);
            v.push(' ' as u8);
            v.push(' ' as u8);
          }
        }
        v.push('\t' as u8);

        for &byte in chunk {
          if (byte >=32 && byte <= 126) || byte >= 128 {
            v.push(byte);
          } else {
            v.push('.' as u8);
          }
        }
        v.push('\n' as u8);
      }

      unsafe {
        String::from_utf8_unchecked(v)
      }
    }
}

#[derive(PartialEq,Eq,Debug)]
struct Brand<'a> {
  major:   &'a str,
  version: &'a [u8]
}
take!(offset 4);
tag!(ftyp    "ftyp".as_bytes());

fn major_brand(input:&[u8]) -> IResult<&[u8],&str> {
  take!(major_brand_bytes 4);
  major_brand_bytes(input).map_res(str::from_utf8)
}
take!(major_brand_version 4);

fn brand<'a>(input: &'a[u8]) -> IResult<&'a [u8], Brand<'a> > {
  chaining_parser!(input, ||{Brand{major: m, version:v}}, m: major_brand, v: major_brand_version,)
}

o!(begin <&[u8], Brand>  offset ~ ftyp ~ [ brand ]);

fn parse_mp4_file(filename: &str) {
  FileProducer::new(filename, 100).map(|producer: FileProducer| {
    let mut p = producer;
    match p.produce() {
      ProducerState::Data(bytes) => {
        println!("bytes:\n{}", bytes.to_hex(8));
        match begin(bytes) {
          Done(i, o) => {
            //println!("parsed: {:?}\n{}", o, i.to_hex(8))
            println!("parsed: {:?}\n", o)
          },
          a          => println!("error: {:?}", a)
        }
      },
      _                          => println!("got error")
    }
    /*//p.push(|par| {println!("parsed file: {}", par); par});
    //p.push(|par| par.flat_map(print));
    fn pr<'a,'b,'c>(data: &[u8]) -> IResult<'b,&[u8], &[u8]> {
      println!("bytes: {:?}", &data[0..20]);
      //Done("".as_bytes(), data).map_res(str::from_utf8);
      Done("".as_bytes(),"".as_bytes())
    }
    pusher!(ps, pr);
    ps(&mut p);
    */
    assert!(false);
  });

}
#[test]
fn file_test() {
  parse_mp4_file("small.mp4");
}
#[test]
fn bunny_test() {
  parse_mp4_file("bigbuckbunny.mp4");
}
<|endoftext|>


<commit_before>
extern crate fftw;
extern crate ndarray;
extern crate ndarray_linalg;

use fftw::*;
use ndarray::*;
use ndarray_linalg::*;

fn test_r2c2r<R, C>(mut pair: Pair<R, C, Ix1>, rtol: R::Real)
where
    R: FFTWReal + Scalar,
    C: FFTWComplex + Scalar,
{
    let a: Array1<R> = random(pair.size());
    println!("a = {:?}", &a);
    let b = {
        let b = pair.forward(a.as_slice().unwrap());
        Array::from_vec(b.to_vec())
    };
    println!("b = {:?}", &b);
    let a2 = pair.backward(b.as_slice().unwrap());
    let a2: Array1<R> = Array::from_vec(a2.to_vec());
    println!("a2 = {:?}", &a2);
    assert_close_l2!(&a2, &a, rtol);
}

#[test]
fn r2c2r() {
    let n = 32;
    let pair: Pair<f64, c64, Ix1> = r2c_1d(n).to_pair().unwrap();
    test_r2c2r(pair, 1e-7);
}
<commit_msg>Update test for r2c<commit_after>
extern crate num_traits;
extern crate fftw;
extern crate ndarray;
#[macro_use]
extern crate ndarray_linalg;

use fftw::*;
use ndarray::*;
use ndarray_linalg::*;

/// Check successive forward and backward transformation conserves.
fn test_r2c2r<R, C>(mut pair: Pair<R, C, Ix1>, rtol: R::Real)
where
    R: FFTWReal,
    C: FFTWComplex<Real = R::Real>,
{
    let a: Array1<R> = random(pair.size());
    println!("a = {:?}", &a);
    let b = {
        let b = pair.forward(a.as_slice().unwrap());
        Array::from_vec(b.to_vec())
    };
    println!("b = {:?}", &b);
    let a2 = pair.backward(b.as_slice().unwrap());
    let a2: Array1<R> = Array::from_vec(a2.to_vec());
    println!("a2 = {:?}", &a2);
    assert_close_l2!(&a2, &a, rtol);
}

/// Check `cos(k_0 x)` is transformed `b[1] = 1.0 + 0.0i`
fn test_r2c<R, C>(mut pair: Pair<R, C, Ix1>, rtol: C::Real)
where
    R: FFTWReal,
    C: FFTWComplex<Real = R::Real>,
{
    let n = pair.size().size();
    let pi = ::std::f64::consts::PI;
    let a: Array1<R> = Array::from_iter((0..n).map(|i| {
        Scalar::from_f64((2.0 * pi * i as f64 / n as f64).cos())
    }));
    println!("a = {:?}", &a);
    let b = {
        let b = pair.forward(a.as_slice().unwrap());
        Array::from_vec(b.to_vec())
    };
    println!("b = {:?}", &b);
    let mut ans: Array1<C> = Array::zeros(b.len());
    ans[1] = Scalar::from_f64(0.5); // cos(x) = 0.5*exp(ix) + c.c.
    assert_close_l2!(&b, &ans, rtol);
}

mod _64 {
    use super::*;

    #[test]
    fn r2c2r() {
        let n = 32;
        let pair: Pair<f64, c64, Ix1> = r2c_1d(n).to_pair().unwrap();
        test_r2c2r(pair, 1e-7);
    }

    #[test]
    fn r2c() {
        let n = 32;
        let pair: Pair<f64, c64, Ix1> = r2c_1d(n).to_pair().unwrap();
        test_r2c(pair, 1e-7);
    }

}
<|endoftext|>


<commit_before>extern crate rsedis;

use rsedis::database::Database;

#[test]
fn sadd() {
    let mut database = Database::new();
    let key = vec![1u8];
    let value = vec![1u8, 2, 3, 4];

    let mut el = database.get_or_create(0, &key);
    assert_eq!(el.sadd(Vec::clone(&value)).unwrap(), true);
    assert_eq!(el.sadd(Vec::clone(&value)).unwrap(), false);
}

#[test]
fn scard() {
    let mut database = Database::new();
    let key = vec![1u8];
    let value = vec![1u8, 2, 3, 4];

    let mut el = database.get_or_create(0, &key);
    assert_eq!(el.scard().unwrap(), 0);
    assert_eq!(el.sadd(Vec::clone(&value)).unwrap(), true);
    assert_eq!(el.scard().unwrap(), 1);
}

#[test]
fn sdiff() {
    let mut database = Database::new();
    let key = vec![1u8];
    let key2 = vec![2u8];
    let value1 = vec![1u8, 2, 3, 4];
    let value2 = vec![1u8, 2, 3, 5];
    let value3 = vec![1u8, 2, 3, 6];

    {
        let mut el = database.get_or_create(0, &key);
        assert_eq!(el.sadd(Vec::clone(&value1)).unwrap(), true);
        assert_eq!(el.sadd(Vec::clone(&value2)).unwrap(), true);
    }
    {
        let mut el2 = database.get_or_create(0, &key2);
        assert_eq!(el2.sadd(Vec::clone(&value1)).unwrap(), true);
        assert_eq!(el2.sadd(Vec::clone(&value3)).unwrap(), true);
    }
    assert_eq!(database.get(0, &key).unwrap().sdiff(&vec![database.get(0, &key2).unwrap()]).unwrap().iter().collect::<Vec<_>>(),
            vec![&value2]);
}
<commit_msg>Remove unnecesary test code<commit_after>extern crate rsedis;

use rsedis::database::Value;

#[test]
fn sadd() {
    let mut value = Value::Nil;
    let v1 = vec![1, 2, 3, 4];

    assert_eq!(value.sadd(v1.clone()).unwrap(), true);
    assert_eq!(value.sadd(v1.clone()).unwrap(), false);
}

#[test]
fn scard() {
    let mut value = Value::Nil;
    let v1 = vec![1, 2, 3, 4];

    assert_eq!(value.scard().unwrap(), 0);
    assert_eq!(value.sadd(v1.clone()).unwrap(), true);
    assert_eq!(value.scard().unwrap(), 1);
}

#[test]
fn sdiff() {
    let mut value1 = Value::Nil;
    let mut value2 = Value::Nil;
    let v1 = vec![1, 2, 3, 4];
    let v2 = vec![5, 6, 7, 8];
    let v3 = vec![0, 9, 1, 2];

    assert_eq!(value1.sadd(v1.clone()).unwrap(), true);
    assert_eq!(value1.sadd(v2.clone()).unwrap(), true);

    assert_eq!(value2.sadd(v1.clone()).unwrap(), true);
    assert_eq!(value2.sadd(v3.clone()).unwrap(), true);

    assert_eq!(value1.sdiff(&vec![&value2]).unwrap().iter().collect::<Vec<_>>(),
            vec![&v2]);
}
<|endoftext|>


<commit_before>//! Completion for cfg

use std::iter;

use ide_db::SymbolKind;
use syntax::SyntaxKind;

use crate::{completions::Completions, context::CompletionContext, CompletionItem};

pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
    let add_completion = |item: &str| {
        let mut completion = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), item);
        completion.insert_text(format!(r#""{}""#, item));
        acc.add(completion.build());
    };

    let previous = iter::successors(ctx.original_token.prev_token(), |t| {
        (matches!(t.kind(), SyntaxKind::EQ) || t.kind().is_trivia())
            .then(|| t.prev_token())
            .flatten()
    })
    .find(|t| matches!(t.kind(), SyntaxKind::IDENT));

    match previous.as_ref().map(|p| p.text()) {
        Some("target_arch") => KNOWN_ARCH.iter().copied().for_each(add_completion),
        Some("target_env") => KNOWN_ENV.iter().copied().for_each(add_completion),
        Some("target_os") => KNOWN_OS.iter().copied().for_each(add_completion),
        Some("target_vendor") => KNOWN_VENDOR.iter().copied().for_each(add_completion),
        Some("target_endian") => ["little", "big"].into_iter().for_each(add_completion),
        Some(name) => ctx.krate.potential_cfg(ctx.db).get_cfg_values(name).cloned().for_each(|s| {
            let insert_text = format!(r#""{}""#, s);
            let mut item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
            item.insert_text(insert_text);

            acc.add(item.build());
        }),
        None => ctx.krate.potential_cfg(ctx.db).get_cfg_keys().cloned().for_each(|s| {
            let item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
            acc.add(item.build());
        }),
    };
}

const KNOWN_ARCH: [&str; 19] = [
    "aarch64",
    "arm",
    "avr",
    "hexagon",
    "mips",
    "mips64",
    "msp430",
    "nvptx64",
    "powerpc",
    "powerpc64",
    "riscv32",
    "riscv64",
    "s390x",
    "sparc",
    "sparc64",
    "wasm32",
    "wasm64",
    "x86",
    "x86_64",
];

const KNOWN_ENV: [&str; 7] = ["eabihf", "gnu", "gnueabihf", "msvc", "relibc", "sgx", "uclibc"];

const KNOWN_OS: [&str; 20] = [
    "cuda",
    "dragonfly",
    "emscripten",
    "freebsd",
    "fuchsia",
    "haiku",
    "hermit",
    "illumos",
    "l4re",
    "linux",
    "netbsd",
    "none",
    "openbsd",
    "psp",
    "redox",
    "solaris",
    "uefi",
    "unknown",
    "vxworks",
    "windows",
];

const KNOWN_VENDOR: [&str; 8] =
    ["apple", "fortanix", "nvidia", "pc", "sony", "unknown", "wrs", "uwp"];
<commit_msg>Auto merge of #12642 - weirdsmiley:master, r=Veykril<commit_after>//! Completion for cfg

use std::iter;

use ide_db::SymbolKind;
use itertools::Itertools;
use syntax::SyntaxKind;

use crate::{completions::Completions, context::CompletionContext, CompletionItem};

pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
    let add_completion = |item: &str| {
        let mut completion = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), item);
        completion.insert_text(format!(r#""{}""#, item));
        acc.add(completion.build());
    };

    let previous = iter::successors(ctx.original_token.prev_token(), |t| {
        (matches!(t.kind(), SyntaxKind::EQ) || t.kind().is_trivia())
            .then(|| t.prev_token())
            .flatten()
    })
    .find(|t| matches!(t.kind(), SyntaxKind::IDENT));

    match previous.as_ref().map(|p| p.text()) {
        Some("target_arch") => KNOWN_ARCH.iter().copied().for_each(add_completion),
        Some("target_env") => KNOWN_ENV.iter().copied().for_each(add_completion),
        Some("target_os") => KNOWN_OS.iter().copied().for_each(add_completion),
        Some("target_vendor") => KNOWN_VENDOR.iter().copied().for_each(add_completion),
        Some("target_endian") => ["little", "big"].into_iter().for_each(add_completion),
        Some(name) => ctx.krate.potential_cfg(ctx.db).get_cfg_values(name).cloned().for_each(|s| {
            let insert_text = format!(r#""{}""#, s);
            let mut item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
            item.insert_text(insert_text);

            acc.add(item.build());
        }),
        None => ctx.krate.potential_cfg(ctx.db).get_cfg_keys().cloned().unique().for_each(|s| {
            let item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
            acc.add(item.build());
        }),
    };
}

const KNOWN_ARCH: [&str; 19] = [
    "aarch64",
    "arm",
    "avr",
    "hexagon",
    "mips",
    "mips64",
    "msp430",
    "nvptx64",
    "powerpc",
    "powerpc64",
    "riscv32",
    "riscv64",
    "s390x",
    "sparc",
    "sparc64",
    "wasm32",
    "wasm64",
    "x86",
    "x86_64",
];

const KNOWN_ENV: [&str; 7] = ["eabihf", "gnu", "gnueabihf", "msvc", "relibc", "sgx", "uclibc"];

const KNOWN_OS: [&str; 20] = [
    "cuda",
    "dragonfly",
    "emscripten",
    "freebsd",
    "fuchsia",
    "haiku",
    "hermit",
    "illumos",
    "l4re",
    "linux",
    "netbsd",
    "none",
    "openbsd",
    "psp",
    "redox",
    "solaris",
    "uefi",
    "unknown",
    "vxworks",
    "windows",
];

const KNOWN_VENDOR: [&str; 8] =
    ["apple", "fortanix", "nvidia", "pc", "sony", "unknown", "wrs", "uwp"];
<|endoftext|>