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

#[test]
fn test_ls_ls() {
    new_ucmd!().succeeds();
}

#[test]
fn test_ls_ls_i() {
    new_ucmd!().arg("-i").succeeds();
    new_ucmd!().arg("-il").succeeds();
}

#[test]
fn test_ls_non_existing() {
    new_ucmd!().arg("doesntexist").fails();
}

#[test]
fn test_ls_files_dirs() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("a");
    at.mkdir("a/b");
    at.mkdir("a/b/c");
    at.mkdir("z");
    at.touch(&at.plus_as_string("a/a"));
    at.touch(&at.plus_as_string("a/b/b"));

    scene.ucmd().arg("a").succeeds();
    scene.ucmd().arg("a/a").succeeds();
    scene.ucmd().arg("a").arg("z").succeeds();

    let result = scene.ucmd().arg("doesntexist").fails();
    // Doesn't exist
    assert!(result
        .stderr
        .contains("error: 'doesntexist': No such file or directory"));

    let result = scene.ucmd().arg("a").arg("doesntexist").fails();
    // One exists, the other doesn't
    assert!(result
        .stderr
        .contains("error: 'doesntexist': No such file or directory"));
    assert!(result.stdout.contains("a:"));
}

#[test]
fn test_ls_recursive() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("a");
    at.mkdir("a/b");
    at.mkdir("a/b/c");
    at.mkdir("z");
    at.touch(&at.plus_as_string("a/a"));
    at.touch(&at.plus_as_string("a/b/b"));

    scene.ucmd().arg("a").succeeds();
    scene.ucmd().arg("a/a").succeeds();
    let result = scene
        .ucmd()
        .arg("--color=never")
        .arg("-R")
        .arg("a")
        .arg("z")
        .succeeds();

    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    if cfg!(target_os = "windows") {
        assert!(result.stdout.contains("a\\b:\nb"));
    } else {
        assert!(result.stdout.contains("a/b:\nb"));
    }
}

#[test]
fn test_ls_ls_color() {
    new_ucmd!().arg("--color").succeeds();
    new_ucmd!().arg("--color=always").succeeds();
    new_ucmd!().arg("--color=never").succeeds();
}
<commit_msg>test(ls): add more ls tests<commit_after>use crate::common::util::*;

extern crate regex;
use self::regex::Regex;

use std::thread::sleep;
use std::time::Duration;

#[cfg(not(windows))]
extern crate libc;
#[cfg(not(windows))]
use self::libc::umask;
#[cfg(not(windows))]
use std::sync::Mutex;

#[cfg(not(windows))]
lazy_static! {
    static ref UMASK_MUTEX: Mutex<()> = Mutex::new(());
}

#[test]
fn test_ls_ls() {
    new_ucmd!().succeeds();
}

#[test]
fn test_ls_i() {
    new_ucmd!().arg("-i").succeeds();
    new_ucmd!().arg("-il").succeeds();
}

#[test]
fn test_ls_a() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.touch(".test-1");

    let result = scene.ucmd().run();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    assert!(result.success);
    assert!(!result.stdout.contains(".test-1"));
    assert!(!result.stdout.contains(".."));

    let result = scene.ucmd().arg("-a").run();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    assert!(result.success);
    assert!(result.stdout.contains(".test-1"));
    assert!(result.stdout.contains(".."));

    let result = scene.ucmd().arg("-A").run();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    assert!(result.success);
    assert!(result.stdout.contains(".test-1"));
    assert!(!result.stdout.contains(".."));
}

#[test]
fn test_ls_long() {
    #[cfg(not(windows))]
    let mut last;
    #[cfg(not(windows))]
    {
        let _guard = UMASK_MUTEX.lock();
        last = unsafe { umask(0) };

        unsafe {
            umask(0o002);
        }
    }

    let (at, mut ucmd) = at_and_ucmd!();
    at.touch(&at.plus_as_string("test-long"));
    let result = ucmd.arg("-l").arg("test-long").succeeds();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    #[cfg(not(windows))]
    assert!(result.stdout.contains("-rw-rw-r--"));

    #[cfg(windows)]
    assert!(result.stdout.contains("---------- 1 somebody somegroup"));

    #[cfg(not(windows))]
    {
        unsafe {
            umask(last);
        }
    }
}

#[test]
fn test_ls_deref() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    let path_regexp = r"(.*)test-long.link -> (.*)test-long(.*)";
    let re = Regex::new(path_regexp).unwrap();

    at.touch(&at.plus_as_string("test-long"));
    at.symlink_file("test-long", "test-long.link");
    assert!(at.is_symlink("test-long.link"));

    let result = scene
        .ucmd()
        .arg("-l")
        .arg("--color=never")
        .arg("test-long")
        .arg("test-long.link")
        .run();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    assert!(result.success);
    assert!(re.is_match(&result.stdout.trim()));

    let result = scene
        .ucmd()
        .arg("-L")
        .arg("--color=never")
        .arg("test-long")
        .arg("test-long.link")
        .run();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    assert!(result.success);
    assert!(!re.is_match(&result.stdout.trim()));
}

#[test]
fn test_ls_order_size() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("test-1");
    at.append("test-1", "1");

    at.touch("test-2");
    at.append("test-2", "22");
    at.touch("test-3");
    at.append("test-3", "333");
    at.touch("test-4");
    at.append("test-4", "4444");

    let result = scene.ucmd().arg("-al").run();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    assert!(result.success);

    let result = scene.ucmd().arg("-S").run();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    assert!(result.success);
    #[cfg(not(windows))]
    assert_eq!(result.stdout, "test-4\ntest-3\ntest-2\ntest-1\n");
    #[cfg(windows)]
    assert_eq!(result.stdout, "test-4  test-3  test-2  test-1\n");

    let result = scene.ucmd().arg("-S").arg("-r").run();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    assert!(result.success);
    #[cfg(not(windows))]
    assert_eq!(result.stdout, "test-1\ntest-2\ntest-3\ntest-4\n");
    #[cfg(windows)]
    assert_eq!(result.stdout, "test-1  test-2  test-3  test-4\n");
}

#[test]
fn test_ls_order_creation() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("test-1");
    at.append("test-1", "1");
    sleep(Duration::from_millis(500));
    at.touch("test-2");
    at.append("test-2", "22");
    sleep(Duration::from_millis(500));
    at.touch("test-3");
    at.append("test-3", "333");
    sleep(Duration::from_millis(500));
    at.touch("test-4");
    at.append("test-4", "4444");

    let result = scene.ucmd().arg("-al").run();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    assert!(result.success);

    let result = scene.ucmd().arg("-t").run();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    assert!(result.success);
    #[cfg(not(windows))]
    assert_eq!(result.stdout, "test-4\ntest-3\ntest-2\ntest-1\n");
    #[cfg(windows)]
    assert_eq!(result.stdout, "test-4  test-3  test-2  test-1\n");

    let result = scene.ucmd().arg("-t").arg("-r").run();
    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    assert!(result.success);
    #[cfg(not(windows))]
    assert_eq!(result.stdout, "test-1\ntest-2\ntest-3\ntest-4\n");
    #[cfg(windows)]
    assert_eq!(result.stdout, "test-1  test-2  test-3  test-4\n");
}

#[test]
fn test_ls_non_existing() {
    new_ucmd!().arg("doesntexist").fails();
}

#[test]
fn test_ls_files_dirs() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("a");
    at.mkdir("a/b");
    at.mkdir("a/b/c");
    at.mkdir("z");
    at.touch(&at.plus_as_string("a/a"));
    at.touch(&at.plus_as_string("a/b/b"));

    scene.ucmd().arg("a").succeeds();
    scene.ucmd().arg("a/a").succeeds();
    scene.ucmd().arg("a").arg("z").succeeds();

    let result = scene.ucmd().arg("doesntexist").fails();
    // Doesn't exist
    assert!(result
        .stderr
        .contains("error: 'doesntexist': No such file or directory"));

    let result = scene.ucmd().arg("a").arg("doesntexist").fails();
    // One exists, the other doesn't
    assert!(result
        .stderr
        .contains("error: 'doesntexist': No such file or directory"));
    assert!(result.stdout.contains("a:"));
}

#[test]
fn test_ls_recursive() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("a");
    at.mkdir("a/b");
    at.mkdir("a/b/c");
    at.mkdir("z");
    at.touch(&at.plus_as_string("a/a"));
    at.touch(&at.plus_as_string("a/b/b"));

    scene.ucmd().arg("a").succeeds();
    scene.ucmd().arg("a/a").succeeds();
    let result = scene
        .ucmd()
        .arg("--color=never")
        .arg("-R")
        .arg("a")
        .arg("z")
        .succeeds();

    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);
    #[cfg(not(windows))]
    assert!(result.stdout.contains("a/b:\nb"));
    #[cfg(windows)]
    assert!(result.stdout.contains("a\\b:\nb"));
}

#[test]
fn test_ls_ls_color() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    at.mkdir("a");
    at.mkdir("z");
    at.touch(&at.plus_as_string("a/a"));
    scene.ucmd().arg("--color").succeeds();
    scene.ucmd().arg("--color=always").succeeds();
    scene.ucmd().arg("--color=never").succeeds();
    scene.ucmd().arg("--color").arg("a").succeeds();
    scene.ucmd().arg("--color=always").arg("a/a").succeeds();
    scene.ucmd().arg("--color=never").arg("z").succeeds();
}
<|endoftext|>


<commit_before><commit_msg>an empy message<commit_after><|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(parse_generics_poc)]
#[macro_use] extern crate custom_derive;

use std::iter::once;
use std::marker::PhantomData;

macro_rules! Iterator {
    (
        () $(pub)* struct $name:ident $($tail:tt)*
    ) => {
        parse_generics! {
            then Iterator!(@with_generics () struct $name,),
            $($tail)*
        }
    };

    (
        @with_generics
        () struct $name:ident,
        $generics:tt,
        ($($body:tt)*)
        $($tail:tt)*
    ) => {
        parse_where! {
            then Iterator!(@with_where () struct $name, $generics,),
            $($tail)* ($($body)*)
        }
    };

    (
        @with_where
        () struct $name:ident,
        $generics:tt,
        $preds:tt,
        ; ($(pub)* $fty:ty)
    ) => {
        Iterator! {
            @with_where
            () struct $name,
            $generics,
            $preds,
            ; ($fty,)
        }
    };

    (
        @with_where
        () struct $name:ident,
        {
            constr: [$($constr:tt)*],
            ltimes: [$($ltimes:tt)*],
            params: [$($params:tt)*]
        },
        {
            preds: [$($preds:tt)*]
        },
        ; ($(pub)* $fty:ty, $(PhantomData<$_phtys:ty>),* $(,)*)
    ) => {
        Iterator! {
            @as_items
            impl<$($constr)*> Iterator for $name<$($ltimes)* $($params)*>
            where $fty: Iterator, $($preds)* {
                type Item = <$fty as Iterator>::Item;
                fn next(&mut self) -> Option<Self::Item> {
                    Iterator::next(&mut self.0)
                }
                fn size_hint(&self) -> (usize, Option<usize>) {
                    Iterator::size_hint(&self.0)
                }
            }
        }
    };

    (@as_items $($its:item)*) => { $($its)* };
}

custom_derive! {
    #[derive(Iterator)]
    struct IterA(Box<Iterator<Item=&'static str>>);
}

#[test]
fn test_iter_a() {
    let mut it = IterA(Box::new(once("upon a time")));
    assert_eq!(it.next(), Some("upon a time"));
    assert_eq!(it.next(), None);
}

custom_derive! {
    #[derive(Iterator)]
    struct IterB<'a>(Box<Iterator<Item=&'a str> + 'a>);
}

#[test]
fn test_iter_b() {
    let mut it = IterB::<'static>(Box::new(once("upon a time")));
    assert_eq!(it.next(), Some("upon a time"));
    assert_eq!(it.next(), None);
}

custom_derive! {
    #[derive(Iterator)]
    struct IterC<'a, T: ?Sized + 'a>(Box<Iterator<Item=&'a T> + 'a>);
}

#[test]
fn test_iter_c() {
    let mut it = IterC::<'static, str>(Box::new(once("upon a time")));
    assert_eq!(it.next(), Some("upon a time"));
    assert_eq!(it.next(), None);
}

custom_derive! {
    #[derive(Iterator)]
    struct IterD<'a, T: ?Sized + 'a>(Box<Iterator<Item=&'a T> + 'a>)
    where T: Copy;
}

#[test]
fn test_iter_d() {
    const S: &'static &'static str = &"times in our lives";
    let mut it = IterD(Box::new(once(S)));
    assert_eq!(it.next(), Some(&"times in our lives"));
    assert_eq!(it.next(), None);
}

custom_derive! {
    #[derive(Iterator)]
    struct IterE<T>(Box<Iterator<Item=T>>, PhantomData<T>)
    where T: Copy + Clone;
}

#[test]
fn test_iter_e() {
    const S: &'static &'static str = &"times in our lives";
    let mut it = IterE(Box::new(once(S)), PhantomData);
    assert_eq!(it.next(), Some(&"times in our lives"));
    assert_eq!(it.next(), None);
}
<commit_msg>Added more Iterator tests.<commit_after>#![feature(plugin)]
#![plugin(parse_generics_poc)]
#[macro_use] extern crate custom_derive;

use std::iter::once;
use std::marker::PhantomData;

macro_rules! Iterator {
    (
        () $(pub)* struct $name:ident $($tail:tt)*
    ) => {
        parse_generics! {
            then Iterator!(@with_generics () struct $name,),
            $($tail)*
        }
    };

    (
        @with_generics
        () struct $name:ident,
        $generics:tt,
        ($($body:tt)*)
        $($tail:tt)*
    ) => {
        parse_where! {
            then Iterator!(@with_where () struct $name, $generics,),
            $($tail)* ($($body)*)
        }
    };

    (
        @with_where
        () struct $name:ident,
        $generics:tt,
        $preds:tt,
        ; ($(pub)* $fty:ty)
    ) => {
        Iterator! {
            @with_where
            () struct $name,
            $generics,
            $preds,
            ; ($fty,)
        }
    };

    (
        @with_where
        () struct $name:ident,
        {
            constr: [$($constr:tt)*],
            ltimes: [$($ltimes:tt)*],
            params: [$($params:tt)*]
        },
        {
            preds: [$($preds:tt)*]
        },
        ; ($(pub)* $fty:ty, $(PhantomData<$_phtys:ty>),* $(,)*)
    ) => {
        Iterator! {
            @as_items
            impl<$($constr)*> Iterator for $name<$($ltimes)* $($params)*>
            where $fty: Iterator, $($preds)* {
                type Item = <$fty as Iterator>::Item;
                fn next(&mut self) -> Option<Self::Item> {
                    Iterator::next(&mut self.0)
                }
                fn size_hint(&self) -> (usize, Option<usize>) {
                    Iterator::size_hint(&self.0)
                }
            }
        }
    };

    (@as_items $($its:item)*) => { $($its)* };
}

custom_derive! {
    #[derive(Iterator)]
    struct IterA(Box<Iterator<Item=&'static str>>);
}

#[test]
fn test_iter_a() {
    let mut it = IterA(Box::new(once("upon a time")));
    assert_eq!(it.next(), Some("upon a time"));
    assert_eq!(it.next(), None);
}

custom_derive! {
    #[derive(Iterator)]
    struct IterB<'a>(Box<Iterator<Item=&'a str> + 'a>);
}

#[test]
fn test_iter_b() {
    let mut it = IterB::<'static>(Box::new(once("upon a time")));
    assert_eq!(it.next(), Some("upon a time"));
    assert_eq!(it.next(), None);
}

custom_derive! {
    #[derive(Iterator)]
    struct IterC<'a, T: ?Sized + 'a>(Box<Iterator<Item=&'a T> + 'a>);
}

#[test]
fn test_iter_c() {
    let mut it = IterC::<'static, str>(Box::new(once("upon a time")));
    assert_eq!(it.next(), Some("upon a time"));
    assert_eq!(it.next(), None);
}

custom_derive! {
    #[derive(Iterator)]
    struct IterD<'a, T: ?Sized + 'a>(Box<Iterator<Item=&'a T> + 'a>)
    where T: Copy;
}

#[test]
fn test_iter_d() {
    const S: &'static &'static str = &"times in our lives";
    let mut it = IterD(Box::new(once(S)));
    assert_eq!(it.next(), Some(&"times in our lives"));
    assert_eq!(it.next(), None);
}

custom_derive! {
    #[derive(Iterator)]
    struct IterE<T>(Box<Iterator<Item=T>>, PhantomData<T>)
    where T: Copy + Clone;
}

#[test]
fn test_iter_e() {
    const S: &'static &'static str = &"times in our lives";
    let mut it = IterE(Box::new(once(S)), PhantomData);
    assert_eq!(it.next(), Some(&"times in our lives"));
    assert_eq!(it.next(), None);
}

custom_derive! {
    #[derive(Iterator)]
    struct IterF<I: Iterator>(I);
}

#[test]
fn test_iter_f() {
    let mut it = IterF(once("you pop"));
    for e in it {
        assert!(e != "stop");
    }
}

custom_derive! {
    #[derive(Iterator)]
    struct IterG<I>(I) where I: Iterator;
}

#[test]
fn test_iter_g() {
    let mut it = IterG(once("you pop"));
    for e in it {
        assert!(e != "stop");
    }
}
<|endoftext|>


<commit_before>//! String processing utilities

/// Split a long line into multiple lines that fit a given width.
///
/// Will treat newlines in the input as regular whitespace, you probably want to split your input
/// at newlines before using `split_line` on the individual lines.
pub fn split_line<'a, F>(text: &'a str, char_width: F, max_width: f32) -> LineSplit<'a, F>
    where F: Fn(char) -> f32
{
    LineSplit {
        remain: text,
        char_width: char_width,
        max_width: max_width,
        finished: false,
    }
}

pub struct LineSplit<'a, F> {
    remain: &'a str,
    char_width: F,
    max_width: f32,
    finished: bool,
}

impl<'a, F> Iterator for LineSplit<'a, F>
    where F: Fn(char) -> f32
{
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if self.finished {
            return None;
        }

        struct State {
            total_width: f32,
            clip_pos: usize,
            last_word_break: Option<(usize, f32)>,
            prev: char,
        }

        impl State {
            fn new() -> State {
                State {
                    total_width: 0.0,
                    clip_pos: 0,
                    last_word_break: None,
                    prev: 'A',
                }
            }

            fn update<F: Fn(char) -> f32>(
                &mut self,
                char_width: &F,
                c: char
            ) -> Option<(usize, f32)> {
                if c.is_whitespace() && !self.prev.is_whitespace() {
                    self.last_word_break = Some((self.clip_pos, self.total_width));
                }
                self.clip_pos += c.len_utf8();
                self.total_width += char_width(c);
                self.prev = c;

                // Return the cut in the current word if there is no last_word_break set yet.
                Some(self.last_word_break.unwrap_or((self.clip_pos, self.total_width)))
            }
        }

        let end_pos = {
            self.remain
                .chars()
                .chain(Some(' ')) // Makes the ending of the last word in line show up.
                .scan(State::new(), |s, c| s.update(&self.char_width, c))
                .scan(true, |is_first, (i, w)| {
                    // Always return at least one element.
                    // Past that return the last element that fits in the space.
                    if *is_first {
                        *is_first = false;
                        Some(i)
                    } else {
                        if w <= self.max_width { Some(i) } else { None }
                    }
                })
                .last()
                .unwrap_or(0)
        };

        let ret = &self.remain[..end_pos];

        self.remain = &self.remain[end_pos..];
        // Strip whitespace between this line and the next.
        let start_pos = self.remain
                            .chars()
                            .take_while(|&c| c.is_whitespace())
                            .map(|c| c.len_utf8())
                            .sum();
        self.remain = &self.remain[start_pos..];
        if self.remain.is_empty() {
            self.finished = true;
        }

        Some(ret)
    }
}

pub struct Map2DIterator<T> {
    /// Input iterator
    iter: T,
    x: i32,
    y: i32,
}

impl<T: Iterator<Item = char>> Iterator for Map2DIterator<T> {
    type Item = (char, i32, i32);

    fn next(&mut self) -> Option<(char, i32, i32)> {
        loop {
            match self.iter.next() {
                None => return None,
                Some(c) if c == '\n' => {
                    self.y += 1;
                    self.x = 0;
                }
                Some(c) if (c as u32) < 32 => {}
                Some(c) => {
                    self.x += 1;
                    return Some((c, self.x - 1, self.y));
                }
            }
        }
    }
}

pub trait Map2DUtil: Sized {
    /// Convert an input value into a sequence of 2D coordinates associated
    /// with a subvalue.
    ///
    /// Used for converting a string of ASCII art into characters and their
    /// coordinates.
    fn map2d(self) -> Map2DIterator<Self>;
}

impl<T: Iterator<Item = char>> Map2DUtil for T {
    fn map2d(self) -> Map2DIterator<T> {
        Map2DIterator {
            iter: self,
            x: 0,
            y: 0,
        }
    }
}
<commit_msg>Command parser generator macro<commit_after>//! String processing utilities

/// Split a long line into multiple lines that fit a given width.
///
/// Will treat newlines in the input as regular whitespace, you probably want to split your input
/// at newlines before using `split_line` on the individual lines.
pub fn split_line<'a, F>(text: &'a str, char_width: F, max_width: f32) -> LineSplit<'a, F>
    where F: Fn(char) -> f32
{
    LineSplit {
        remain: text,
        char_width: char_width,
        max_width: max_width,
        finished: false,
    }
}

pub struct LineSplit<'a, F> {
    remain: &'a str,
    char_width: F,
    max_width: f32,
    finished: bool,
}

impl<'a, F> Iterator for LineSplit<'a, F>
    where F: Fn(char) -> f32
{
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if self.finished {
            return None;
        }

        struct State {
            total_width: f32,
            clip_pos: usize,
            last_word_break: Option<(usize, f32)>,
            prev: char,
        }

        impl State {
            fn new() -> State {
                State {
                    total_width: 0.0,
                    clip_pos: 0,
                    last_word_break: None,
                    prev: 'A',
                }
            }

            fn update<F: Fn(char) -> f32>(
                &mut self,
                char_width: &F,
                c: char
            ) -> Option<(usize, f32)> {
                if c.is_whitespace() && !self.prev.is_whitespace() {
                    self.last_word_break = Some((self.clip_pos, self.total_width));
                }
                self.clip_pos += c.len_utf8();
                self.total_width += char_width(c);
                self.prev = c;

                // Return the cut in the current word if there is no last_word_break set yet.
                Some(self.last_word_break.unwrap_or((self.clip_pos, self.total_width)))
            }
        }

        let end_pos = {
            self.remain
                .chars()
                .chain(Some(' ')) // Makes the ending of the last word in line show up.
                .scan(State::new(), |s, c| s.update(&self.char_width, c))
                .scan(true, |is_first, (i, w)| {
                    // Always return at least one element.
                    // Past that return the last element that fits in the space.
                    if *is_first {
                        *is_first = false;
                        Some(i)
                    } else {
                        if w <= self.max_width { Some(i) } else { None }
                    }
                })
                .last()
                .unwrap_or(0)
        };

        let ret = &self.remain[..end_pos];

        self.remain = &self.remain[end_pos..];
        // Strip whitespace between this line and the next.
        let start_pos = self.remain
                            .chars()
                            .take_while(|&c| c.is_whitespace())
                            .map(|c| c.len_utf8())
                            .sum();
        self.remain = &self.remain[start_pos..];
        if self.remain.is_empty() {
            self.finished = true;
        }

        Some(ret)
    }
}

pub struct Map2DIterator<T> {
    /// Input iterator
    iter: T,
    x: i32,
    y: i32,
}

impl<T: Iterator<Item = char>> Iterator for Map2DIterator<T> {
    type Item = (char, i32, i32);

    fn next(&mut self) -> Option<(char, i32, i32)> {
        loop {
            match self.iter.next() {
                None => return None,
                Some(c) if c == '\n' => {
                    self.y += 1;
                    self.x = 0;
                }
                Some(c) if (c as u32) < 32 => {}
                Some(c) => {
                    self.x += 1;
                    return Some((c, self.x - 1, self.y));
                }
            }
        }
    }
}

pub trait Map2DUtil: Sized {
    /// Convert an input value into a sequence of 2D coordinates associated with a subvalue.
    ///
    /// Used for converting a string of ASCII art into characters and their
    /// coordinates.
    fn map2d(self) -> Map2DIterator<Self>;
}

impl<T: Iterator<Item = char>> Map2DUtil for T {
    fn map2d(self) -> Map2DIterator<T> {
        Map2DIterator {
            iter: self,
            x: 0,
            y: 0,
        }
    }
}

/// Parser method generator.
///
/// Invoke inside an impl block. Declare a list of signatures of methods callable on `&mut self`.
/// The macro constructs a `parse(&mut self, input: &str) -> Result<(), String>` method that parses
/// input strings like "method_name 4 foo" into calls of `self.method_name(FromStr::from_str("4")?,
/// FromStr::from_str("foo")?)`.
///
///     # #[macro_use] extern crate calx_alg;
///     # fn main() {
///
///     struct Adder {
///         pub num: u32,
///     }
///
///     impl Adder {
///         fn add(&mut self, amount: u32) {
///             self.num += amount;
///         }
///
///         command_parser!{
///             fn add(&mut self, amount: u32);
///         }
///     }
///
///     let mut a = Adder { num: 1 };
///     a.add(2);
///     assert_eq!(a.num, 3);
///
///     assert!(a.parse("foobie bletch").is_err());
///     assert!(a.parse("add").is_err());       // Too few arguments
///     assert!(a.parse("add derp").is_err());  // Arguments won't parse to unsigned integer.
///     assert!(a.parse("add -1").is_err());
///     assert!(a.parse("add 1.0").is_err());
///
///     // NB: Due to limits of the macro implementation, trailing arguments
///     // are ignored instead of causing an error.
///     // assert!(a.parse("add 1 2").is_err());   // Too many arguments
///
///     assert_eq!(a.num, 3);
///
///     assert!(a.parse("add 3").is_ok());
///     assert_eq!(a.num, 6);
///
///     # }
#[macro_export]
macro_rules! command_parser {
    {
        $(fn $method:ident(&mut self$(, $argname:ident: $argtype:ty)*);)+
    } => {
        fn parse(&mut self, input: &str) -> Result<(), Box<::std::error::Error>> {
            #[derive(Debug)]
            struct ParseError(String);

            impl ::std::fmt::Display for ParseError {
                fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                    self.0.fmt(fmt)
                }
            }

            impl ::std::error::Error for ParseError {
                fn description(&self) -> &str { &self.0 }
            }

            fn ParseErr(s: String) -> Result<(), Box<::std::error::Error>> {
                Err(Box::new(ParseError(s)))
            }

            use ::std::str::FromStr;
            let mut elts = input.split(" ");
            let cmd = elts.next();
            if let Some(cmd) = cmd {
                match cmd {
                    $(
                    stringify!($method) => {
                        self.$method(
                            $({
                                if let Some(arg) = elts.next() {
                                    let param: $argtype = FromStr::from_str(arg)?;
                                    param
                                } else {
                                    return ParseErr(format!("Too few arguments"));
                                }
                            }),*
                        );
                        Ok(())
                    }
                    )+
                    x => ParseErr(format!("Unknown command {}", x)),
                }
            } else {
                return ParseErr(format!("No input"));
            }
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name="CSVProvider"]
#![crate_type="dylib"]

// why doesn't "lib" work?

// rustc 0.11.0-pre (b47f2226a25654c5b781d27a91f2fa5274b3a347 2014-06-28 14:31:37 +0000)

#![feature(globs, macro_rules, quote, managed_boxes, plugin_registrar)]

#![allow(unused_imports)]
#![allow(unused_variable)]
#![allow(uppercase_variables)]
#![allow(unnecessary_parens)]

extern crate syntax;
extern crate rustc;

use syntax::ast::{
   Name,
   TokenTree,
   Expr,
   ExprLit,
   ExprVec,
   LitStr,
   Ident,
   DUMMY_NODE_ID,
   MutImmutable
};
use syntax::codemap::Span;
use syntax::ext::base::{
   SyntaxExtension,
   BasicMacroExpander,
   ExtCtxt,
   MacResult,
   MacPat,
   MacItem,
   DummyResult,
   MacExpr,
   NormalTT
};
use std::gc::Gc;
use syntax::ext::quote::{
   //expand_parse_call
};
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::{InternedString, COMMA, EOF};

use std::io;
use std::io::fs;
use std::os;
use std::str;
use std::io::Process;
use syntax::ast;
use syntax::ast::Name;

use syntax::util::small_vector::SmallVector;

use std::collections::HashMap;
use std::gc::{Gc, GC};

use rustc::plugin::Registry;

#[plugin_registrar]
pub fn macro_registrar(reg: &mut Registry) {
   reg.register_macro("ProvideCSV_labels", provide_csv_given_labels);
}

#[deriving(Clone)]
struct Entry {
   str: InternedString,
   expr: Gc<Expr>
}

// see https://github.com/sfackler/syntax-ext-talk/blob/gh-pages/simple-ext/lib.rs
fn parse_entries(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
   let mut parser = parse::new_parser_from_tts(
       cx.parse_sess(),
       cx.cfg(),
       tts.iter()
          .map(|x| (*x).clone())
          .collect()
   );

   let mut entries: Vec<Entry> = Vec::new();

   let mut error = false;
   while parser.token != EOF {
      let entry = parser.parse_expr();

      let entry_str = match entry.node {
         ExprLit(lit) => {
            match lit.node {
               LitStr(ref s, _) => s.clone(),
               _ => {
                  cx.span_err(entry.span, "expected string literal (1)");
                  error = true;
                  InternedString::new("")
               }
            }
         }
         _ => {
                cx.span_err(entry.span, "expected string literal (2)");
                error = true;
                InternedString::new("")
         }
      };

      entries.push(Entry { str: entry_str, expr: entry });

      if !parser.eat(&COMMA) && parser.token != EOF {
         cx.span_err(parser.span, "expected `,`");
         return None;
      }
    }

   if error {
      return None;
   }

   Some(entries)
}

pub struct MacItems {
   items: Vec<Gc<ast::Item>>
}
impl MacItems {
   pub fn new(items: Vec<Gc<ast::Item>>) -> Box<MacResult> {
      box MacItems { items: items } as Box<MacResult>
   }
}
impl MacResult for MacItems {
   fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
      Some(SmallVector::many(self.items.clone()))
   }
}

fn parse_csv_row(raw: &str, expected_columns: Option<uint>) -> Option<Vec<&str>> {
   let data: Vec<&str> = raw.split_str(",").collect();

   match expected_columns {
      Some(count) => {
         if (count != data.len()) {
            println!("parse_csv_row: wrong length!");
            return None;
         }
         else {
            return Some(data);
         }
      },
      None => {
         return Some(data);
      }
   }
}

fn provide_csv_given_labels(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult> {
   let mut entries = match parse_entries(cx, tts) {
      Some(entries) => entries,
      None => return DummyResult::expr(sp),
   };

   let icx : &ExtCtxt = cx;  // an immutable borrow

   let raw_name   : Entry = entries.remove(0).expect("should be given a type name");
   let raw_path   : Entry = entries.remove(0).expect("should be given a CSV file path");
   let raw_labels : Entry = entries.remove(0).expect("should be given column labels");

   let name   : InternedString = raw_name.str;
   let path   : InternedString = raw_path.str;
   let labels : InternedString = raw_labels.str;

   println!("provide_csv_given_labels: name:   {}", name);
   println!("provide_csv_given_labels: path:   {}", path);
   println!("provide_csv_given_labels: labels: {}", labels);

   // PENDING
   // read the CSV and try to get the type of data in it
   // create a type with
   //  * this name,
   //  * these labeled columns,
   //  * discovered type of data
   //  * a constructor which reads the whole file

   fn interned_to_ident(xx: InternedString) -> Ident {
      let yy: String = format!("{}", xx);
      let zz: &str = yy.as_slice();
      return token::str_to_ident(zz);
   }

   fn interned_to_ident_with_suffix(xx: InternedString, suff: &str) -> Ident {
      let yy: String = format!("{}{}", xx, suff);
      let zz: &str = yy.as_slice();
      return token::str_to_ident(zz);
   }

   let MyCsv    = interned_to_ident(name.clone());
   let MyCsvRow = interned_to_ident_with_suffix(name, "Row");
   let col0     = interned_to_ident(labels.clone());

   println!("Parsing given labels...");

   let labels1 = format!("{}", labels);
   let labels_iter = parse_csv_row(labels1.as_slice(), None);

   println!("Defining items in the CSV provider...");

   // TODO: iterate through call columns
   let item0 = quote_item!(icx,
      pub struct $MyCsvRow {
         pub $col0: String,
      }
   );

   let item1: Option<Gc<syntax::ast::Item>> = quote_item!(icx,
      pub struct $MyCsv {
         pub data: Vec<$MyCsvRow>,
      }
   );

   let item2: Option<Gc<syntax::ast::Item>> = quote_item!(icx,
      impl $MyCsv {
         pub fn new() -> $MyCsv {
            println!("HMMMMMM.");
            return $MyCsv {
               data: (vec![
                  $MyCsvRow { $col0: "zero".to_string() },
                  $MyCsvRow { $col0:  "one".to_string() },
                  $MyCsvRow { $col0:  "two".to_string() },
               ]),
            };
         }
      }
   );

   let items = vec![item0.expect("Should be able to make struct MyCsvRow"),
                    item1.expect("Should be able to make struct MyCsv."),
                    item2.expect("Should be able to implement MyCsv.")];

   println!("OK");

   return MacItems::new(items);
}

<commit_msg>parse the labels given (crudely)<commit_after>#![crate_name="CSVProvider"]
#![crate_type="dylib"]

#![feature(globs, macro_rules, quote, managed_boxes, plugin_registrar)]

#![allow(unused_imports)]
#![allow(unused_variable)]
#![allow(uppercase_variables)]
#![allow(unnecessary_parens)]

extern crate syntax;
extern crate rustc;

use syntax::ast::{
   Name,
   TokenTree,
   Expr,
   ExprLit,
   ExprVec,
   LitStr,
   Ident,
   DUMMY_NODE_ID,
   MutImmutable
};
use syntax::codemap::Span;
use syntax::ext::base::{
   SyntaxExtension,
   BasicMacroExpander,
   ExtCtxt,
   MacResult,
   MacPat,
   MacItem,
   DummyResult,
   MacExpr,
   NormalTT
};
use std::gc::Gc;
use syntax::ext::quote::{
   //expand_parse_call
};
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::{InternedString, COMMA, EOF};

use std::io;
use std::io::fs;
use std::os;
use std::str;
use std::io::Process;
use syntax::ast;
use syntax::ast::Name;

use syntax::util::small_vector::SmallVector;

use std::collections::HashMap;
use std::gc::{Gc, GC};

use rustc::plugin::Registry;

#[plugin_registrar]
pub fn macro_registrar(reg: &mut Registry) {
   reg.register_macro("ProvideCSV_labels", provide_csv_given_labels);
}

#[deriving(Clone)]
struct Entry {
   str: InternedString,
   expr: Gc<Expr>
}

// see https://github.com/sfackler/syntax-ext-talk/blob/gh-pages/simple-ext/lib.rs
fn parse_entries(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
   let mut parser = parse::new_parser_from_tts(
       cx.parse_sess(),
       cx.cfg(),
       tts.iter()
          .map(|x| (*x).clone())
          .collect()
   );

   let mut entries: Vec<Entry> = Vec::new();

   let mut error = false;
   while parser.token != EOF {
      let entry = parser.parse_expr();

      let entry_str = match entry.node {
         ExprLit(lit) => {
            match lit.node {
               LitStr(ref s, _) => s.clone(),
               _ => {
                  cx.span_err(entry.span, "expected string literal (1)");
                  error = true;
                  InternedString::new("")
               }
            }
         }
         _ => {
                cx.span_err(entry.span, "expected string literal (2)");
                error = true;
                InternedString::new("")
         }
      };

      entries.push(Entry { str: entry_str, expr: entry });

      if !parser.eat(&COMMA) && parser.token != EOF {
         cx.span_err(parser.span, "expected `,`");
         return None;
      }
    }

   if error {
      return None;
   }

   Some(entries)
}

pub struct MacItems {
   items: Vec<Gc<ast::Item>>
}
impl MacItems {
   pub fn new(items: Vec<Gc<ast::Item>>) -> Box<MacResult> {
      box MacItems { items: items } as Box<MacResult>
   }
}
impl MacResult for MacItems {
   fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
      Some(SmallVector::many(self.items.clone()))
   }
}

fn parse_csv_row(raw: &str, expected_columns: Option<uint>) -> Option<Vec<&str>> {
   let data: Vec<&str> = raw.split_str(",").collect();

   match expected_columns {
      Some(count) => {
         if (count != data.len()) {
            println!("parse_csv_row: wrong length!");
            return None;
         }
         else {
            return Some(data);
         }
      },
      None => {
         return Some(data);
      }
   }
}

fn provide_csv_given_labels(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult> {
   let mut entries = match parse_entries(cx, tts) {
      Some(entries) => entries,
      None => return DummyResult::expr(sp),
   };

   let icx : &ExtCtxt = cx;  // an immutable borrow

   let raw_name   : Entry = entries.remove(0).expect("should be given a type name");
   let raw_path   : Entry = entries.remove(0).expect("should be given a CSV file path");
   let raw_labels : Entry = entries.remove(0).expect("should be given column labels");

   let name   : InternedString = raw_name.str;
   let path   : InternedString = raw_path.str;
   //let labels : InternedString = raw_labels.str;

   println!("provide_csv_given_labels: name:   {}", name);
   println!("provide_csv_given_labels: path:   {}", path);
   //println!("provide_csv_given_labels: labels: {}", labels);

   // PENDING
   // read the CSV and try to get the type of data in it
   // create a type with
   //  * this name,
   //  * these labeled columns,
   //  * discovered type of data
   //  * a constructor which reads the whole file

   fn interned_to_ident(xx: InternedString) -> Ident {
      let yy: String = format!("{}", xx);
      let zz: &str = yy.as_slice();
      return token::str_to_ident(zz);
   }

   fn interned_to_ident_with_suffix(xx: InternedString, suff: &str) -> Ident {
      let yy: String = format!("{}{}", xx, suff);
      let zz: &str = yy.as_slice();
      return token::str_to_ident(zz);
   }

   let MyCsv    = interned_to_ident(name.clone());
   let MyCsvRow = interned_to_ident_with_suffix(name, "Row");

   println!("Parsing given labels...");

   let labels1 = format!("{}", raw_labels.str);
   let labels = parse_csv_row(labels1.as_slice(), None).expect("should be able to parse the row of labels");
   let col0 = token::str_to_ident(labels[0]);

   println!("Defining items in the CSV provider...");

   // TODO: iterate through call columns
   let item0 = quote_item!(icx,
      pub struct $MyCsvRow {
         pub $col0: String,
      }
   );

   let item1: Option<Gc<syntax::ast::Item>> = quote_item!(icx,
      pub struct $MyCsv {
         pub data: Vec<$MyCsvRow>,
      }
   );

   let item2: Option<Gc<syntax::ast::Item>> = quote_item!(icx,
      impl $MyCsv {
         pub fn new() -> $MyCsv {
            println!("HMMMMMM.");
            return $MyCsv {
               data: (vec![
                  $MyCsvRow { $col0: "zero".to_string() },
                  $MyCsvRow { $col0:  "one".to_string() },
                  $MyCsvRow { $col0:  "two".to_string() },
               ]),
            };
         }
      }
   );

   let items = vec![item0.expect("Should be able to make struct MyCsvRow"),
                    item1.expect("Should be able to make struct MyCsv."),
                    item2.expect("Should be able to implement MyCsv.")];

   println!("OK");

   return MacItems::new(items);
}

<|endoftext|>


<commit_before>// compile-flags: -Zmiri-seed=
#![feature(allocator_api)]

use std::ptr::NonNull;
use std::alloc::{Global, Alloc, Layout, System};
use std::slice;

fn check_alloc<T: Alloc>(mut allocator: T) { unsafe {
    for &align in &[4, 8, 16, 32] {
        let layout = Layout::from_size_align(20, align).unwrap();

        for _ in 0..32 {
            let a = allocator.alloc(layout).unwrap();
            assert_eq!(a.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
            allocator.dealloc(a, layout);
        }

        let p1 = allocator.alloc_zeroed(layout).unwrap();
        assert_eq!(p1.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");

        let p2 = allocator.realloc(p1, layout, 40).unwrap();
        let layout = Layout::from_size_align(40, align).unwrap();
        assert_eq!(p2.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
        let slice = slice::from_raw_parts(p2.as_ptr(), 20);
        assert_eq!(&slice, &[0_u8; 20]);

        // old size == new size
        let p3 = allocator.realloc(p2, layout, 40).unwrap();
        assert_eq!(p3.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
        let slice = slice::from_raw_parts(p3.as_ptr(), 20);
        assert_eq!(&slice, &[0_u8; 20]);

        // old size > new size
        let p4 = allocator.realloc(p3, layout, 10).unwrap();
        let layout = Layout::from_size_align(10, align).unwrap();
        assert_eq!(p4.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
        let slice = slice::from_raw_parts(p4.as_ptr(), 10);
        assert_eq!(&slice, &[0_u8; 10]);

        allocator.dealloc(p4, layout);
    }
} }

fn check_overalign_requests<T: Alloc>(mut allocator: T) {
    for &size in &[2, 8, 64] { // size less than and bigger than alignment
        for &align in &[4, 8, 16, 32] { // Be sure to cover less than and bigger than `MIN_ALIGN` for all architectures
            let iterations = 32;
            unsafe {
                let pointers: Vec<_> = (0..iterations).map(|_| {
                    allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
                }).collect();
                for &ptr in &pointers {
                    assert_eq!((ptr.as_ptr() as usize) % align, 0,
                            "Got a pointer less aligned than requested")
                }

                // Clean up.
                for &ptr in &pointers {
                    allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap())
                }
            }
        }
    }
}

fn global_to_box() {
    type T = [i32; 4];
    let l = Layout::new::<T>();
    // allocate manually with global allocator, then turn into Box and free there
    unsafe {
        let ptr = Global.alloc(l).unwrap().as_ptr() as *mut T;
        let b = Box::from_raw(ptr);
        drop(b);
    }
}

fn box_to_global() {
    type T = [i32; 4];
    let l = Layout::new::<T>();
    // allocate with the Box, then deallocate manually with global allocator
    unsafe {
        let b = Box::new(T::default());
        let ptr = Box::into_raw(b);
        Global.dealloc(NonNull::new(ptr as *mut u8).unwrap(), l);
    }
}

fn main() {
    check_alloc(System);
    check_alloc(Global);
    check_overalign_requests(System);
    check_overalign_requests(Global);
    global_to_box();
    box_to_global();
}
<commit_msg>Auto merge of #819 - RalfJung:test-name, r=RalfJung<commit_after>// compile-flags: -Zmiri-seed=
#![feature(allocator_api)]

use std::ptr::NonNull;
use std::alloc::{Global, Alloc, Layout, System};
use std::slice;

fn check_alloc<T: Alloc>(mut allocator: T) { unsafe {
    for &align in &[4, 8, 16, 32] {
        let layout = Layout::from_size_align(20, align).unwrap();

        for _ in 0..32 {
            let a = allocator.alloc(layout).unwrap();
            assert_eq!(a.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
            allocator.dealloc(a, layout);
        }

        let p1 = allocator.alloc_zeroed(layout).unwrap();
        assert_eq!(p1.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");

        let p2 = allocator.realloc(p1, layout, 40).unwrap();
        let layout = Layout::from_size_align(40, align).unwrap();
        assert_eq!(p2.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
        let slice = slice::from_raw_parts(p2.as_ptr(), 20);
        assert_eq!(&slice, &[0_u8; 20]);

        // old size == new size
        let p3 = allocator.realloc(p2, layout, 40).unwrap();
        assert_eq!(p3.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
        let slice = slice::from_raw_parts(p3.as_ptr(), 20);
        assert_eq!(&slice, &[0_u8; 20]);

        // old size > new size
        let p4 = allocator.realloc(p3, layout, 10).unwrap();
        let layout = Layout::from_size_align(10, align).unwrap();
        assert_eq!(p4.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
        let slice = slice::from_raw_parts(p4.as_ptr(), 10);
        assert_eq!(&slice, &[0_u8; 10]);

        allocator.dealloc(p4, layout);
    }
} }

fn check_align_requests<T: Alloc>(mut allocator: T) {
    for &size in &[2, 8, 64] { // size less than and bigger than alignment
        for &align in &[4, 8, 16, 32] { // Be sure to cover less than and bigger than `MIN_ALIGN` for all architectures
            let iterations = 32;
            unsafe {
                let pointers: Vec<_> = (0..iterations).map(|_| {
                    allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
                }).collect();
                for &ptr in &pointers {
                    assert_eq!((ptr.as_ptr() as usize) % align, 0,
                            "Got a pointer less aligned than requested")
                }

                // Clean up.
                for &ptr in &pointers {
                    allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap())
                }
            }
        }
    }
}

fn global_to_box() {
    type T = [i32; 4];
    let l = Layout::new::<T>();
    // allocate manually with global allocator, then turn into Box and free there
    unsafe {
        let ptr = Global.alloc(l).unwrap().as_ptr() as *mut T;
        let b = Box::from_raw(ptr);
        drop(b);
    }
}

fn box_to_global() {
    type T = [i32; 4];
    let l = Layout::new::<T>();
    // allocate with the Box, then deallocate manually with global allocator
    unsafe {
        let b = Box::new(T::default());
        let ptr = Box::into_raw(b);
        Global.dealloc(NonNull::new(ptr as *mut u8).unwrap(), l);
    }
}

fn main() {
    check_alloc(System);
    check_alloc(Global);
    check_align_requests(System);
    check_align_requests(Global);
    global_to_box();
    box_to_global();
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Common functionality for the x86 and x86_64 Interrupt Descriptor Table.

use core::fmt;
use core::fmt::Write;

use super::super::{DTablePtr, control_regs};
use io::term::CONSOLE;

use vga::Color;

pub type Handler = unsafe extern "C" fn() -> ();
pub const IDT_ENTRIES: usize = 256;

/// x86 interrupt gate types.
///
/// Bit-and this with the attribute half-byte to produce the
/// `type_attr` field for a `Gate`
#[repr(u8)]
#[derive(Copy,Clone,Debug)]
pub enum GateType { Absent    = 0b0000_0000
                  , Interrupt = 0b1000_1110
                  , Call      = 0b1000_1100
                  , Trap      = 0b1000_1111
                  }

impl fmt::Display for GateType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self { &GateType::Absent    => write!(f, "Absent")
                   , &GateType::Interrupt => write!(f, "Interrupt")
                   , &GateType::Call      => write!(f, "Call")
                   , &GateType::Trap      => write!(f, "Trap")
                   }
    }
}

#[derive(Debug)]
pub struct ExceptionInfo { pub name: &'static str
                         , pub mnemonic: &'static str
                         , pub irq_type: &'static str
                         , pub source: &'static str
                         }

/// x86 exceptions.
///
/// Taken from the list at
/// [http://wiki.osdev.org/Exceptions](http://wiki.osdev.org/Exceptions)
pub static EXCEPTIONS: [ExceptionInfo; 20]
    = [ ExceptionInfo { name: "Divide-By-Zero Error"
                      , mnemonic: "#DE", irq_type: "Fault"
                      , source: "DIV or IDIV instruction" }
      , ExceptionInfo { name: "RESERVED"
                      , mnemonic: "#DB", irq_type: "Fault/trap"
                      , source: "Reserved for Intel use" }
      , ExceptionInfo { name: "Non-Maskable Interrupt"
                      , mnemonic: "NMI", irq_type: "Interrupt"
                      , source: "Non-maskable external interrupt" }
      , ExceptionInfo { name: "Breakpoint"
                      , mnemonic: "#BP", irq_type: "Trap"
                      , source: "INT 3 instruction" }
      , ExceptionInfo { name: "Overflow"
                      , mnemonic: "#OF", irq_type: "Trap"
                      , source: "INTO instruction" }
      , ExceptionInfo { name: "BOUND Range Exceeded"
                      , mnemonic: "#BR", irq_type: "Fault"
                      , source: "BOUND instruction" }
      , ExceptionInfo { name: "Undefined Opcode"
                     , mnemonic: "#UD", irq_type: "Fault"
                     , source: "UD2 instruction or reserved opcode" }
      , ExceptionInfo { name: "Device Not Available"
                      , mnemonic: "#NM", irq_type: "Fault"
                      , source: "Floating-point or WAIT/FWAIT instruction\
                                 (no math coprocessor)" }
      , ExceptionInfo { name: "Double Fault"
                      , mnemonic: "#DF", irq_type: "Abort"
                      , source: "Any instruction that can generate an\
                                 exception, a NMI, or an INTR" }
      , ExceptionInfo { name: "Coprocessor Segment Overrun"
                      , mnemonic: "", irq_type: "Fault"
                      , source: "Any floating-point instruction" }
      , ExceptionInfo { name: "Invalid TSS"
                      , mnemonic: "#TS", irq_type: "Fault"
                      , source: "Task switch or TSS access" }
      , ExceptionInfo { name: "Segment Not Present"
                      , mnemonic: "#NP", irq_type: "Fault"
                      , source: "Loading segment registers or accessing\
                                 system segments" }
      , ExceptionInfo { name: "Stack-Segment Fault"
                      , mnemonic: "#SS", irq_type: "Fault"
                      , source: "Stack operations and SS register loads" }
      , ExceptionInfo { name: "General Protection"
                      , mnemonic: "#GP", irq_type: "Fault"
                      , source: "Any memory reference or other protection\
                                 checks" }
      , ExceptionInfo { name: "Page Fault"
                      , mnemonic: "#PF", irq_type: "Fault"
                      , source: "Any memory reference" }
      , ExceptionInfo { name: "RESERVED"
                      , mnemonic: "", irq_type: ""
                      , source: "RESERVED FOR INTEL USE \n This should never \
                                 happen. Something is very wrong." }
      , ExceptionInfo { name: "x87 FPU Floating-Point Error (Math Fault)"
                      , mnemonic: "#MF", irq_type: "Fault"
                      , source: "x87 FPU floating-point or WAIT/FWAIT\
                                 instruction" }
      , ExceptionInfo { name: "Alignment Check"
                      , mnemonic: "#AC", irq_type: "Fault"
                      , source: "Any data reference in memory" }
      , ExceptionInfo { name: "Machine Check"
                      , mnemonic: "#MC", irq_type: "Abort"
                      , source: "Model-dependent" }
      , ExceptionInfo { name: "SIMD Floating-Point Exception"
                      , mnemonic: "#XM", irq_type: "Fault"
                      , source: "SSE/SSE2/SSE3 floating-point instructions" }
       ];

pub trait Gate {
    fn from_handler(handler: Handler) -> Self;
    unsafe fn from_raw(handler: *const u8) -> Self;
}

// /// This is the format that `lidt` expects for the pointer to the IDT.
// /// ...apparently.
// #[repr(C, packed)]
// pub struct IdtPtr<I>
// where I: Idt { pub limit: u16
//              , pub base: *const I
//              }
//
// pub trait IdtPtrOps {
//     unsafe fn load(&self);
// }

pub trait InterruptContext {
    type Registers: fmt::Debug;

    fn err_no(&self) -> u32;
    fn int_id(&self) -> u32;
    fn registers(&self) -> Self::Registers;

    #[inline]
    fn exception(&self) -> &ExceptionInfo {
        &EXCEPTIONS[self.int_id() as usize]
    }

}

pub trait Idt: Sized {
    type Ctx: InterruptContext;
    type GateSize: Gate;
    type PtrSize;

    /// Get the IDT pointer struct to pass to `lidt`
    fn get_ptr(&self) -> DTablePtr<Self::PtrSize>;
    //
    // /// This is just a wrapper for prettiness reasons.
    // #[inline]
    // unsafe fn load(&self) {
    //     self.get_ptr()
    //         .load()
    // }

    /// Enable interrupts
    unsafe fn enable_interrupts() { asm!("sti") }
    /// Disable interrupts
    unsafe fn disable_interrupts() { asm!("cli") }

    /// Add a new interrupt gate pointing to the given handler
    fn add_gate(&mut self, idx: usize, handler: Handler);

    #[allow(unused_must_use)]
    unsafe fn handle_cpu_exception(state: &Self::Ctx) -> ! {
        let ex_info = state.exception();
        let cr_state = control_regs::dump();
        write!(CONSOLE.lock()
                      .set_colors(Color::White, Color::Blue)
                    //   .clear()
              , "CPU EXCEPTION {}: {}\n\
                 {} on vector {} with error code {:#x}\n\
                 Source: {}.\nThis is fine.\n\n"
              , ex_info.mnemonic, ex_info.name
              , ex_info.irq_type, state.int_id(), state.err_no()
              , ex_info.source );

        // TODO: parse error codes
        match state.int_id() {
            14 => unimplemented!() //TODO: special handling for page faults
           , _ => write!( CONSOLE.lock()
                                 .set_colors(Color::White, Color::Blue)
                        , "Registers:\n{:?}\n    {}\n"
                        , state.registers()
                        , cr_state
                        )
        };

        loop { }
    }

    unsafe extern "C" fn handle_interrupt(state: &Self::Ctx);
}
<commit_msg>[x86_all] Fix & patterns in pattern match<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Common functionality for the x86 and x86_64 Interrupt Descriptor Table.

use core::fmt;
use core::fmt::Write;

use super::super::{DTablePtr, control_regs};
use io::term::CONSOLE;

use vga::Color;

pub type Handler = unsafe extern "C" fn() -> ();
pub const IDT_ENTRIES: usize = 256;

/// x86 interrupt gate types.
///
/// Bit-and this with the attribute half-byte to produce the
/// `type_attr` field for a `Gate`
#[repr(u8)]
#[derive(Copy,Clone,Debug)]
pub enum GateType { Absent    = 0b0000_0000
                  , Interrupt = 0b1000_1110
                  , Call      = 0b1000_1100
                  , Trap      = 0b1000_1111
                  }

impl fmt::Display for GateType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self { GateType::Absent    => write!(f, "Absent")
                    , GateType::Interrupt => write!(f, "Interrupt")
                    , GateType::Call      => write!(f, "Call")
                    , GateType::Trap      => write!(f, "Trap")
                    }
    }
}

#[derive(Debug)]
pub struct ExceptionInfo { pub name: &'static str
                         , pub mnemonic: &'static str
                         , pub irq_type: &'static str
                         , pub source: &'static str
                         }

/// x86 exceptions.
///
/// Taken from the list at
/// [http://wiki.osdev.org/Exceptions](http://wiki.osdev.org/Exceptions)
pub static EXCEPTIONS: [ExceptionInfo; 20]
    = [ ExceptionInfo { name: "Divide-By-Zero Error"
                      , mnemonic: "#DE", irq_type: "Fault"
                      , source: "DIV or IDIV instruction" }
      , ExceptionInfo { name: "RESERVED"
                      , mnemonic: "#DB", irq_type: "Fault/trap"
                      , source: "Reserved for Intel use" }
      , ExceptionInfo { name: "Non-Maskable Interrupt"
                      , mnemonic: "NMI", irq_type: "Interrupt"
                      , source: "Non-maskable external interrupt" }
      , ExceptionInfo { name: "Breakpoint"
                      , mnemonic: "#BP", irq_type: "Trap"
                      , source: "INT 3 instruction" }
      , ExceptionInfo { name: "Overflow"
                      , mnemonic: "#OF", irq_type: "Trap"
                      , source: "INTO instruction" }
      , ExceptionInfo { name: "BOUND Range Exceeded"
                      , mnemonic: "#BR", irq_type: "Fault"
                      , source: "BOUND instruction" }
      , ExceptionInfo { name: "Undefined Opcode"
                     , mnemonic: "#UD", irq_type: "Fault"
                     , source: "UD2 instruction or reserved opcode" }
      , ExceptionInfo { name: "Device Not Available"
                      , mnemonic: "#NM", irq_type: "Fault"
                      , source: "Floating-point or WAIT/FWAIT instruction\
                                 (no math coprocessor)" }
      , ExceptionInfo { name: "Double Fault"
                      , mnemonic: "#DF", irq_type: "Abort"
                      , source: "Any instruction that can generate an\
                                 exception, a NMI, or an INTR" }
      , ExceptionInfo { name: "Coprocessor Segment Overrun"
                      , mnemonic: "", irq_type: "Fault"
                      , source: "Any floating-point instruction" }
      , ExceptionInfo { name: "Invalid TSS"
                      , mnemonic: "#TS", irq_type: "Fault"
                      , source: "Task switch or TSS access" }
      , ExceptionInfo { name: "Segment Not Present"
                      , mnemonic: "#NP", irq_type: "Fault"
                      , source: "Loading segment registers or accessing\
                                 system segments" }
      , ExceptionInfo { name: "Stack-Segment Fault"
                      , mnemonic: "#SS", irq_type: "Fault"
                      , source: "Stack operations and SS register loads" }
      , ExceptionInfo { name: "General Protection"
                      , mnemonic: "#GP", irq_type: "Fault"
                      , source: "Any memory reference or other protection\
                                 checks" }
      , ExceptionInfo { name: "Page Fault"
                      , mnemonic: "#PF", irq_type: "Fault"
                      , source: "Any memory reference" }
      , ExceptionInfo { name: "RESERVED"
                      , mnemonic: "", irq_type: ""
                      , source: "RESERVED FOR INTEL USE \n This should never \
                                 happen. Something is very wrong." }
      , ExceptionInfo { name: "x87 FPU Floating-Point Error (Math Fault)"
                      , mnemonic: "#MF", irq_type: "Fault"
                      , source: "x87 FPU floating-point or WAIT/FWAIT\
                                 instruction" }
      , ExceptionInfo { name: "Alignment Check"
                      , mnemonic: "#AC", irq_type: "Fault"
                      , source: "Any data reference in memory" }
      , ExceptionInfo { name: "Machine Check"
                      , mnemonic: "#MC", irq_type: "Abort"
                      , source: "Model-dependent" }
      , ExceptionInfo { name: "SIMD Floating-Point Exception"
                      , mnemonic: "#XM", irq_type: "Fault"
                      , source: "SSE/SSE2/SSE3 floating-point instructions" }
       ];

pub trait Gate {
    fn from_handler(handler: Handler) -> Self;
    unsafe fn from_raw(handler: *const u8) -> Self;
}

// /// This is the format that `lidt` expects for the pointer to the IDT.
// /// ...apparently.
// #[repr(C, packed)]
// pub struct IdtPtr<I>
// where I: Idt { pub limit: u16
//              , pub base: *const I
//              }
//
// pub trait IdtPtrOps {
//     unsafe fn load(&self);
// }

pub trait InterruptContext {
    type Registers: fmt::Debug;

    fn err_no(&self) -> u32;
    fn int_id(&self) -> u32;
    fn registers(&self) -> Self::Registers;

    #[inline]
    fn exception(&self) -> &ExceptionInfo {
        &EXCEPTIONS[self.int_id() as usize]
    }

}

pub trait Idt: Sized {
    type Ctx: InterruptContext;
    type GateSize: Gate;
    type PtrSize;

    /// Get the IDT pointer struct to pass to `lidt`
    fn get_ptr(&self) -> DTablePtr<Self::PtrSize>;
    //
    // /// This is just a wrapper for prettiness reasons.
    // #[inline]
    // unsafe fn load(&self) {
    //     self.get_ptr()
    //         .load()
    // }

    /// Enable interrupts
    unsafe fn enable_interrupts() { asm!("sti") }
    /// Disable interrupts
    unsafe fn disable_interrupts() { asm!("cli") }

    /// Add a new interrupt gate pointing to the given handler
    fn add_gate(&mut self, idx: usize, handler: Handler);

    #[allow(unused_must_use)]
    unsafe fn handle_cpu_exception(state: &Self::Ctx) -> ! {
        let ex_info = state.exception();
        let cr_state = control_regs::dump();
        write!(CONSOLE.lock()
                      .set_colors(Color::White, Color::Blue)
                    //   .clear()
              , "CPU EXCEPTION {}: {}\n\
                 {} on vector {} with error code {:#x}\n\
                 Source: {}.\nThis is fine.\n\n"
              , ex_info.mnemonic, ex_info.name
              , ex_info.irq_type, state.int_id(), state.err_no()
              , ex_info.source );

        // TODO: parse error codes
        match state.int_id() {
            14 => unimplemented!() //TODO: special handling for page faults
           , _ => write!( CONSOLE.lock()
                                 .set_colors(Color::White, Color::Blue)
                        , "Registers:\n{:?}\n    {}\n"
                        , state.registers()
                        , cr_state
                        )
        };

        loop { }
    }

    unsafe extern "C" fn handle_interrupt(state: &Self::Ctx);
}
<|endoftext|>


<commit_before>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use serde::{Deserialize, Serialize};
use serde_generate::{cpp, python3, rust, test_utils};
use serde_reflection::{Registry, Result, Samples, Tracer, TracerConfig};
use std::fs::File;
use std::io::Write;
use std::process::Command;
use tempfile::tempdir;

#[derive(Serialize, Deserialize)]
struct Test {
    a: Vec<u32>,
    b: (i64, u64),
    c: Choice,
}

#[derive(Serialize, Deserialize)]
enum Choice {
    A,
    B(u64),
    C { x: u8 },
}

fn get_local_registry() -> Result<Registry> {
    let mut tracer = Tracer::new(TracerConfig::default());
    let samples = Samples::new();
    tracer.trace_type::<Test>(&samples)?;
    tracer.trace_type::<Choice>(&samples)?;
    Ok(tracer.registry()?)
}

#[test]
fn test_python_bincode_runtime_on_simple_data() {
    let registry = get_local_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.py");
    let mut source = File::create(&source_path).unwrap();
    python3::output(&mut source, &registry).unwrap();

    let reference = bincode::serialize(&Test {
        a: vec![4, 6],
        b: (3, 5),
        c: Choice::C { x: 7 },
    })
    .unwrap();
    writeln!(
        source,
        r#"
import bincode

value = Test([4, 6], (3, 5), Choice__C(7))

s = bincode.serialize(value, Test)
assert s == bytes.fromhex("{}")

v, buffer = bincode.deserialize(s, Test)
assert len(buffer) == 0
assert v == value
assert v.c.x == 7

v.b = (3, 0)
t = bincode.serialize(v, Test)
assert len(t) == len(s)
assert t != s
"#,
        hex::encode(&reference),
    )
    .unwrap();

    let python_path = std::env::var("PYTHONPATH").unwrap_or_default() + ":runtime/python";
    let output = Command::new("python3")
        .arg(source_path)
        .env("PYTHONPATH", python_path)
        .output()
        .unwrap();

    std::io::stdout().write_all(&output.stdout).unwrap();
    std::io::stderr().write_all(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}

#[test]
fn test_python_bincode_runtime_on_all_supported_types() {
    let registry = test_utils::get_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.py");
    let mut source = File::create(&source_path).unwrap();
    python3::output(&mut source, &registry).unwrap();

    let values = test_utils::get_sample_values();
    let hex_encodings: Vec<_> = values
        .iter()
        .map(|v| format!("'{}'", hex::encode(&bincode::serialize(&v).unwrap())))
        .collect();

    writeln!(
        source,
        r#"
import bincode

encodings = [bytes.fromhex(s) for s in [{}]]

for encoding in encodings:
    v, buffer = bincode.deserialize(encoding, SerdeData)
    assert len(buffer) == 0

    s = bincode.serialize(v, SerdeData)
    assert s == encoding
"#,
        hex_encodings.join(", ")
    )
    .unwrap();

    let python_path = format!(
        "{}:runtime/python",
        std::env::var("PYTHONPATH").unwrap_or_default()
    );
    let output = Command::new("python3")
        .arg(source_path)
        .env("PYTHONPATH", python_path)
        .output()
        .unwrap();

    std::io::stdout().write_all(&output.stdout).unwrap();
    std::io::stderr().write_all(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}

// Full test using cargo. This may take a while.
#[test]
fn test_rust_bincode_runtime() {
    let registry = test_utils::get_registry().unwrap();
    let dir = tempdir().unwrap();
    std::fs::write(
        dir.path().join("Cargo.toml"),
        r#"[package]
name = "testing2"
version = "0.1.0"
edition = "2018"

[dependencies]
hex = "0.4.2"
serde = { version = "1.0", features = ["derive"] }
serde_bytes = "0.11"
bincode = "1.2"

[workspace]
"#,
    )
    .unwrap();
    std::fs::create_dir(dir.path().join("src")).unwrap();
    let source_path = dir.path().join("src/main.rs");
    let mut source = File::create(&source_path).unwrap();
    rust::output(&mut source, /* with_derive_macros */ true, &registry).unwrap();

    let values = test_utils::get_sample_values();
    let hex_encodings: Vec<_> = values
        .iter()
        .map(|v| format!("\"{}\"", hex::encode(&bincode::serialize(&v).unwrap())))
        .collect();

    writeln!(
        source,
        r#"
fn main() {{
    let hex_encodings = vec![{}];

    for hex_encoding in hex_encodings {{
        let encoding = hex::decode(hex_encoding).unwrap();
        let value = bincode::deserialize::<SerdeData>(&encoding).unwrap();

        let s = bincode::serialize(&value).unwrap();
        assert_eq!(s, encoding);
    }}
}}
"#,
        hex_encodings.join(", ")
    )
    .unwrap();

    // Use a stable `target` dir to avoid downloading and recompiling crates everytime.
    let target_dir = std::env::current_dir().unwrap().join("../target");
    let output = Command::new("cargo")
        .current_dir(dir.path())
        .arg("run")
        .arg("--target-dir")
        .arg(target_dir)
        .output()
        .unwrap();

    std::io::stdout().write_all(&output.stdout).unwrap();
    std::io::stderr().write_all(&output.stderr).unwrap();
    assert!(output.status.success());
}

#[test]
fn test_rust_documentation_on_simple_data() {
    let registry = get_local_registry().unwrap();
    let definitions = rust::quote_container_definitions(&registry).unwrap();
    assert_eq!(definitions.len(), 2);
    assert!(definitions.get("Test").unwrap().starts_with("struct Test"));
    assert!(definitions
        .get("Choice")
        .unwrap()
        .starts_with("enum Choice"));
}

#[test]
fn test_cpp_bincode_runtime_on_simple_date() {
    let registry = get_local_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.cpp");
    let mut source = File::create(&source_path).unwrap();
    cpp::output(&mut source, &registry).unwrap();

    let reference = bincode::serialize(&Test {
        a: vec![4, 6],
        b: (-3, 5),
        c: Choice::C { x: 7 },
    })
    .unwrap();

    writeln!(
        source,
        r#"
#include "bincode.hpp"

int main() {{
    std::vector<uint8_t> input = {{{}}};

    auto deserializer = BincodeDeserializer(input);
    auto test = Deserializable<Test>::deserialize(deserializer);

    auto a = std::vector<uint32_t> {{4, 6}};
    auto b = std::tuple<int64_t, uint64_t> {{-3, 5}};
    auto c = Choice {{ Choice::C {{ 7 }} }};
    auto test2 = Test {{a, b, c}};

    assert(test == test2);

    auto serializer = BincodeSerializer();
    Serializable<Test>::serialize(test2, serializer);
    auto output = std::move(serializer).bytes();

    assert(input == output);

    return 0;
}}
"#,
        reference
            .iter()
            .map(|x| format!("0x{:02x}", x))
            .collect::<Vec<_>>()
            .join(", ")
    )
    .unwrap();

    let output = Command::new("clang++")
        .arg("--std=c++17")
        .arg("-o")
        .arg(dir.path().join("test"))
        .arg("-I")
        .arg("runtime/cpp")
        .arg(source_path)
        .output()
        .unwrap();
    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());

    let output = Command::new(dir.path().join("test")).output().unwrap();
    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}

#[test]
fn test_cpp_bincode_runtime_on_supported_types() {
    let registry = test_utils::get_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.cpp");
    let mut source = File::create(&source_path).unwrap();
    cpp::output(&mut source, &registry).unwrap();

    let values = test_utils::get_sample_values();
    let encodings = values
        .iter()
        .map(|v| {
            let bytes = bincode::serialize(&v).unwrap();
            format!(
                "std::vector<uint8_t>{{{}}}",
                bytes
                    .iter()
                    .map(|x| format!("0x{:02x}", x))
                    .collect::<Vec<_>>()
                    .join(", ")
            )
        })
        .collect::<Vec<_>>()
        .join(", ");

    writeln!(
        source,
        r#"
#include "bincode.hpp"

int main() {{
    std::vector<std::vector<uint8_t>> inputs = {{{}}};

    for (auto input: inputs) {{
        auto deserializer = BincodeDeserializer(input);
        auto test = Deserializable<SerdeData>::deserialize(deserializer);

        auto serializer = BincodeSerializer();
        Serializable<SerdeData>::serialize(test, serializer);
        auto output = std::move(serializer).bytes();

        assert(input == output);
    }}

    return 0;
}}
"#,
        encodings
    )
    .unwrap();

    let output = Command::new("clang++")
        .arg("--std=c++17")
        .arg("-g")
        .arg("-o")
        .arg(dir.path().join("test"))
        .arg("-I")
        .arg("runtime/cpp")
        .arg(source_path)
        .output()
        .unwrap();
    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());

    let output = Command::new(dir.path().join("test")).output().unwrap();
    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}
<commit_msg>[serde generate] fix test in CircleCI<commit_after>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use serde::{Deserialize, Serialize};
use serde_generate::{cpp, python3, rust, test_utils};
use serde_reflection::{Registry, Result, Samples, Tracer, TracerConfig};
use std::fs::File;
use std::io::Write;
use std::process::Command;
use tempfile::tempdir;

#[derive(Serialize, Deserialize)]
struct Test {
    a: Vec<u32>,
    b: (i64, u64),
    c: Choice,
}

#[derive(Serialize, Deserialize)]
enum Choice {
    A,
    B(u64),
    C { x: u8 },
}

fn get_local_registry() -> Result<Registry> {
    let mut tracer = Tracer::new(TracerConfig::default());
    let samples = Samples::new();
    tracer.trace_type::<Test>(&samples)?;
    tracer.trace_type::<Choice>(&samples)?;
    Ok(tracer.registry()?)
}

#[test]
fn test_python_bincode_runtime_on_simple_data() {
    let registry = get_local_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.py");
    let mut source = File::create(&source_path).unwrap();
    python3::output(&mut source, &registry).unwrap();

    let reference = bincode::serialize(&Test {
        a: vec![4, 6],
        b: (3, 5),
        c: Choice::C { x: 7 },
    })
    .unwrap();
    writeln!(
        source,
        r#"
import bincode

value = Test([4, 6], (3, 5), Choice__C(7))

s = bincode.serialize(value, Test)
assert s == bytes.fromhex("{}")

v, buffer = bincode.deserialize(s, Test)
assert len(buffer) == 0
assert v == value
assert v.c.x == 7

v.b = (3, 0)
t = bincode.serialize(v, Test)
assert len(t) == len(s)
assert t != s
"#,
        hex::encode(&reference),
    )
    .unwrap();

    let python_path = std::env::var("PYTHONPATH").unwrap_or_default() + ":runtime/python";
    let output = Command::new("python3")
        .arg(source_path)
        .env("PYTHONPATH", python_path)
        .output()
        .unwrap();

    std::io::stdout().write_all(&output.stdout).unwrap();
    std::io::stderr().write_all(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}

#[test]
fn test_python_bincode_runtime_on_all_supported_types() {
    let registry = test_utils::get_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.py");
    let mut source = File::create(&source_path).unwrap();
    python3::output(&mut source, &registry).unwrap();

    let values = test_utils::get_sample_values();
    let hex_encodings: Vec<_> = values
        .iter()
        .map(|v| format!("'{}'", hex::encode(&bincode::serialize(&v).unwrap())))
        .collect();

    writeln!(
        source,
        r#"
import bincode

encodings = [bytes.fromhex(s) for s in [{}]]

for encoding in encodings:
    v, buffer = bincode.deserialize(encoding, SerdeData)
    assert len(buffer) == 0

    s = bincode.serialize(v, SerdeData)
    assert s == encoding
"#,
        hex_encodings.join(", ")
    )
    .unwrap();

    let python_path = format!(
        "{}:runtime/python",
        std::env::var("PYTHONPATH").unwrap_or_default()
    );
    let output = Command::new("python3")
        .arg(source_path)
        .env("PYTHONPATH", python_path)
        .output()
        .unwrap();

    std::io::stdout().write_all(&output.stdout).unwrap();
    std::io::stderr().write_all(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}

// Full test using cargo. This may take a while.
#[test]
fn test_rust_bincode_runtime() {
    let registry = test_utils::get_registry().unwrap();
    let dir = tempdir().unwrap();
    std::fs::write(
        dir.path().join("Cargo.toml"),
        r#"[package]
name = "testing2"
version = "0.1.0"
edition = "2018"

[dependencies]
hex = "0.4.2"
serde = { version = "1.0", features = ["derive"] }
serde_bytes = "0.11"
bincode = "1.2"

[workspace]
"#,
    )
    .unwrap();
    std::fs::create_dir(dir.path().join("src")).unwrap();
    let source_path = dir.path().join("src/main.rs");
    let mut source = File::create(&source_path).unwrap();
    rust::output(&mut source, /* with_derive_macros */ true, &registry).unwrap();

    let values = test_utils::get_sample_values();
    let hex_encodings: Vec<_> = values
        .iter()
        .map(|v| format!("\"{}\"", hex::encode(&bincode::serialize(&v).unwrap())))
        .collect();

    writeln!(
        source,
        r#"
fn main() {{
    let hex_encodings = vec![{}];

    for hex_encoding in hex_encodings {{
        let encoding = hex::decode(hex_encoding).unwrap();
        let value = bincode::deserialize::<SerdeData>(&encoding).unwrap();

        let s = bincode::serialize(&value).unwrap();
        assert_eq!(s, encoding);
    }}
}}
"#,
        hex_encodings.join(", ")
    )
    .unwrap();

    // Use a stable `target` dir to avoid downloading and recompiling crates everytime.
    let target_dir = std::env::current_dir().unwrap().join("../target");
    let output = Command::new("cargo")
        .current_dir(dir.path())
        .arg("run")
        .arg("--target-dir")
        .arg(target_dir)
        .output()
        .unwrap();

    std::io::stdout().write_all(&output.stdout).unwrap();
    std::io::stderr().write_all(&output.stderr).unwrap();
    assert!(output.status.success());
}

#[test]
fn test_rust_documentation_on_simple_data() {
    let registry = get_local_registry().unwrap();
    let definitions = rust::quote_container_definitions(&registry).unwrap();
    assert_eq!(definitions.len(), 2);
    assert!(definitions.get("Test").unwrap().starts_with("struct Test"));
    assert!(definitions
        .get("Choice")
        .unwrap()
        .starts_with("enum Choice"));
}

#[test]
fn test_cpp_bincode_runtime_on_simple_date() {
    let registry = get_local_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.cpp");
    let mut source = File::create(&source_path).unwrap();
    cpp::output(&mut source, &registry).unwrap();

    let reference = bincode::serialize(&Test {
        a: vec![4, 6],
        b: (-3, 5),
        c: Choice::C { x: 7 },
    })
    .unwrap();

    writeln!(
        source,
        r#"
#include <cassert>
#include "bincode.hpp"

int main() {{
    std::vector<uint8_t> input = {{{}}};

    auto deserializer = BincodeDeserializer(input);
    auto test = Deserializable<Test>::deserialize(deserializer);

    auto a = std::vector<uint32_t> {{4, 6}};
    auto b = std::tuple<int64_t, uint64_t> {{-3, 5}};
    auto c = Choice {{ Choice::C {{ 7 }} }};
    auto test2 = Test {{a, b, c}};

    assert(test == test2);

    auto serializer = BincodeSerializer();
    Serializable<Test>::serialize(test2, serializer);
    auto output = std::move(serializer).bytes();

    assert(input == output);

    return 0;
}}
"#,
        reference
            .iter()
            .map(|x| format!("0x{:02x}", x))
            .collect::<Vec<_>>()
            .join(", ")
    )
    .unwrap();

    let output = Command::new("clang++")
        .arg("--std=c++17")
        .arg("-o")
        .arg(dir.path().join("test"))
        .arg("-I")
        .arg("runtime/cpp")
        .arg(source_path)
        .output()
        .unwrap();
    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());

    let output = Command::new(dir.path().join("test")).output().unwrap();
    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}

#[test]
fn test_cpp_bincode_runtime_on_supported_types() {
    let registry = test_utils::get_registry().unwrap();
    let dir = tempdir().unwrap();
    let source_path = dir.path().join("test.cpp");
    let mut source = File::create(&source_path).unwrap();
    cpp::output(&mut source, &registry).unwrap();

    let values = test_utils::get_sample_values();
    let encodings = values
        .iter()
        .map(|v| {
            let bytes = bincode::serialize(&v).unwrap();
            format!(
                "std::vector<uint8_t>{{{}}}",
                bytes
                    .iter()
                    .map(|x| format!("0x{:02x}", x))
                    .collect::<Vec<_>>()
                    .join(", ")
            )
        })
        .collect::<Vec<_>>()
        .join(", ");

    writeln!(
        source,
        r#"
#include <cassert>
#include "bincode.hpp"

int main() {{
    std::vector<std::vector<uint8_t>> inputs = {{{}}};

    for (auto input: inputs) {{
        auto deserializer = BincodeDeserializer(input);
        auto test = Deserializable<SerdeData>::deserialize(deserializer);

        auto serializer = BincodeSerializer();
        Serializable<SerdeData>::serialize(test, serializer);
        auto output = std::move(serializer).bytes();

        assert(input == output);
    }}

    return 0;
}}
"#,
        encodings
    )
    .unwrap();

    let output = Command::new("clang++")
        .arg("--std=c++17")
        .arg("-g")
        .arg("-o")
        .arg(dir.path().join("test"))
        .arg("-I")
        .arg("runtime/cpp")
        .arg(source_path)
        .output()
        .unwrap();
    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());

    let output = Command::new(dir.path().join("test")).output().unwrap();
    std::io::stdout().write(&output.stdout).unwrap();
    std::io::stderr().write(&output.stderr).unwrap();
    assert_eq!(String::new(), String::from_utf8_lossy(&output.stderr));
    assert!(output.status.success());
}
<|endoftext|>


<commit_before>extern crate inkwell;

use self::inkwell::OptimizationLevel::Aggressive;
use self::inkwell::context::Context;
use self::inkwell::passes::{PassManagerBuilder, PassManager, PassRegistry};

#[test]
fn test_init_all_passes_for_module() {
    let context = Context::create();
    let module = context.create_module("my_module");
    let pass_manager = PassManager::create(());

    pass_manager.add_argument_promotion_pass();
    pass_manager.add_constant_merge_pass();
    pass_manager.add_dead_arg_elimination_pass();
    pass_manager.add_function_attrs_pass();
    pass_manager.add_function_inlining_pass();
    pass_manager.add_always_inliner_pass();
    pass_manager.add_global_dce_pass();
    pass_manager.add_global_optimizer_pass();
    pass_manager.add_prune_eh_pass();
    pass_manager.add_ipsccp_pass();
    pass_manager.add_internalize_pass(true);
    pass_manager.add_strip_dead_prototypes_pass();
    pass_manager.add_strip_symbol_pass();
    #[cfg(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9", feature = "llvm4-0"))]
    pass_manager.add_bb_vectorize_pass();
    pass_manager.add_loop_vectorize_pass();
    pass_manager.add_slp_vectorize_pass();
    pass_manager.add_aggressive_dce_pass();
    #[cfg(not(feature = "llvm3-6"))]
    pass_manager.add_bit_tracking_dce_pass();
    pass_manager.add_alignment_from_assumptions_pass();
    pass_manager.add_cfg_simplification_pass();
    pass_manager.add_dead_store_elimination_pass();
    pass_manager.add_scalarizer_pass();
    pass_manager.add_merged_load_store_motion_pass();
    pass_manager.add_gvn_pass();
    pass_manager.add_ind_var_simplify_pass();
    pass_manager.add_instruction_combining_pass();
    pass_manager.add_jump_threading_pass();
    pass_manager.add_licm_pass();
    pass_manager.add_loop_deletion_pass();
    pass_manager.add_loop_idiom_pass();
    pass_manager.add_loop_rotate_pass();
    pass_manager.add_loop_reroll_pass();
    pass_manager.add_loop_unroll_pass();
    pass_manager.add_loop_unswitch_pass();
    pass_manager.add_memcpy_optimize_pass();
    pass_manager.add_partially_inline_lib_calls_pass();
    pass_manager.add_lower_switch_pass();
    pass_manager.add_promote_memory_to_register_pass();
    pass_manager.add_reassociate_pass();
    pass_manager.add_sccp_pass();
    pass_manager.add_scalar_repl_aggregates_pass();
    pass_manager.add_scalar_repl_aggregates_pass_ssa();
    pass_manager.add_scalar_repl_aggregates_pass_with_threshold(1);
    pass_manager.add_simplify_lib_calls_pass();
    pass_manager.add_tail_call_elimination_pass();
    pass_manager.add_demote_memory_to_register_pass();
    pass_manager.add_verifier_pass();
    pass_manager.add_correlated_value_propagation_pass();
    pass_manager.add_early_cse_pass();
    pass_manager.add_lower_expect_intrinsic_pass();
    pass_manager.add_type_based_alias_analysis_pass();
    pass_manager.add_scoped_no_alias_aa_pass();
    pass_manager.add_basic_alias_analysis_pass();

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9")))]
    {
        pass_manager.add_early_cse_mem_ssa_pass();
        pass_manager.add_new_gvn_pass();
    }

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))]
    {
        pass_manager.add_aggressive_inst_combiner_pass();
        pass_manager.add_loop_unroll_and_jam_pass();
    }

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0", feature = "llvm7-0")))]
    {
        pass_manager.add_coroutine_early_pass();
        pass_manager.add_coroutine_split_pass();
        pass_manager.add_coroutine_elide_pass();
        pass_manager.add_coroutine_cleanup_pass();
    }

    #[cfg(not(any(feature = "llvm12-0")))]
    {
        pass_manager.add_constant_propagation_pass();
        pass_manager.add_ip_constant_propagation_pass();
    }

    pass_manager.run_on(&module);
}

#[test]
fn test_pass_manager_builder() {
    let pass_manager_builder = PassManagerBuilder::create();

    pass_manager_builder.set_optimization_level(Aggressive);
    pass_manager_builder.set_size_level(2);
    pass_manager_builder.set_inliner_with_threshold(42);
    pass_manager_builder.set_disable_unit_at_a_time(true);
    pass_manager_builder.set_disable_unroll_loops(true);
    pass_manager_builder.set_disable_simplify_lib_calls(true);

    let context = Context::create();
    let module = context.create_module("my_module");

    let fn_pass_manager = PassManager::create(&module);

    pass_manager_builder.populate_function_pass_manager(&fn_pass_manager);

    let void_type = context.void_type();
    let fn_type = void_type.fn_type(&[], false);
    let fn_value = module.add_function("my_fn", fn_type, None);
    let builder = context.create_builder();
    let entry = context.append_basic_block(fn_value, "entry");

    builder.position_at_end(entry);
    builder.build_return(None);

    #[cfg(not(feature = "llvm3-7"))]
    assert!(!fn_pass_manager.initialize());
    #[cfg(feature = "llvm3-7")]
    fn_pass_manager.initialize();

    // TODO: Test with actual changes? Would be true in that case
    // REVIEW: Segfaults in 4.0
    #[cfg(not(feature = "llvm4-0"))]
    assert!(!fn_pass_manager.run_on(&fn_value));

    assert!(!fn_pass_manager.finalize());

    let module_pass_manager = PassManager::create(());

    pass_manager_builder.populate_module_pass_manager(&module_pass_manager);

    let module2 = module.clone();

    // TODOC: In 3.6, 3.8, & 3.9 it returns false. Seems like a LLVM bug?
    #[cfg(not(any(feature = "llvm3-7", feature = "llvm6-0", feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", feature = "llvm11-0")))]
    assert!(!module_pass_manager.run_on(&module));
    #[cfg(any(feature = "llvm3-7", feature = "llvm6-0", feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", feature = "llvm11-0"))]
    assert!(module_pass_manager.run_on(&module));

    let lto_pass_manager = PassManager::create(());

    pass_manager_builder.populate_lto_pass_manager(&lto_pass_manager, false, false);

    assert!(lto_pass_manager.run_on(&module2));
}

#[test]
fn test_pass_registry() {
    let pass_registry = PassRegistry::get_global();

    pass_registry.initialize_core();
    pass_registry.initialize_transform_utils();
    pass_registry.initialize_scalar_opts();
    pass_registry.initialize_obj_carc_opts();
    pass_registry.initialize_vectorization();
    pass_registry.initialize_inst_combine();
    pass_registry.initialize_ipo();
    pass_registry.initialize_instrumentation();
    pass_registry.initialize_analysis();
    pass_registry.initialize_ipa();
    pass_registry.initialize_codegen();
    pass_registry.initialize_target();
    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))]
    pass_registry.initialize_aggressive_inst_combiner();
}
<commit_msg>fix pass manager test<commit_after>extern crate inkwell;

use self::inkwell::OptimizationLevel::Aggressive;
use self::inkwell::context::Context;
use self::inkwell::passes::{PassManagerBuilder, PassManager, PassRegistry};

#[test]
fn test_init_all_passes_for_module() {
    let context = Context::create();
    let module = context.create_module("my_module");
    let pass_manager = PassManager::create(());

    pass_manager.add_argument_promotion_pass();
    pass_manager.add_constant_merge_pass();
    pass_manager.add_dead_arg_elimination_pass();
    pass_manager.add_function_attrs_pass();
    pass_manager.add_function_inlining_pass();
    pass_manager.add_always_inliner_pass();
    pass_manager.add_global_dce_pass();
    pass_manager.add_global_optimizer_pass();
    #[cfg(not(feature = "llvm12-0"))]
    pass_manager.add_ip_constant_propagation_pass();
    pass_manager.add_prune_eh_pass();
    pass_manager.add_ipsccp_pass();
    pass_manager.add_internalize_pass(true);
    pass_manager.add_strip_dead_prototypes_pass();
    pass_manager.add_strip_symbol_pass();
    #[cfg(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9", feature = "llvm4-0"))]
    pass_manager.add_bb_vectorize_pass();
    pass_manager.add_loop_vectorize_pass();
    pass_manager.add_slp_vectorize_pass();
    pass_manager.add_aggressive_dce_pass();
    #[cfg(not(feature = "llvm3-6"))]
    pass_manager.add_bit_tracking_dce_pass();
    pass_manager.add_alignment_from_assumptions_pass();
    pass_manager.add_cfg_simplification_pass();
    pass_manager.add_dead_store_elimination_pass();
    pass_manager.add_scalarizer_pass();
    pass_manager.add_merged_load_store_motion_pass();
    pass_manager.add_gvn_pass();
    pass_manager.add_ind_var_simplify_pass();
    pass_manager.add_instruction_combining_pass();
    pass_manager.add_jump_threading_pass();
    pass_manager.add_licm_pass();
    pass_manager.add_loop_deletion_pass();
    pass_manager.add_loop_idiom_pass();
    pass_manager.add_loop_rotate_pass();
    pass_manager.add_loop_reroll_pass();
    pass_manager.add_loop_unroll_pass();
    pass_manager.add_loop_unswitch_pass();
    pass_manager.add_memcpy_optimize_pass();
    pass_manager.add_partially_inline_lib_calls_pass();
    pass_manager.add_lower_switch_pass();
    pass_manager.add_promote_memory_to_register_pass();
    pass_manager.add_reassociate_pass();
    pass_manager.add_sccp_pass();
    pass_manager.add_scalar_repl_aggregates_pass();
    pass_manager.add_scalar_repl_aggregates_pass_ssa();
    pass_manager.add_scalar_repl_aggregates_pass_with_threshold(1);
    pass_manager.add_simplify_lib_calls_pass();
    pass_manager.add_tail_call_elimination_pass();
    #[cfg(not(feature = "llvm12-0"))]
    pass_manager.add_constant_propagation_pass();
    pass_manager.add_demote_memory_to_register_pass();
    pass_manager.add_verifier_pass();
    pass_manager.add_correlated_value_propagation_pass();
    pass_manager.add_early_cse_pass();
    pass_manager.add_lower_expect_intrinsic_pass();
    pass_manager.add_type_based_alias_analysis_pass();
    pass_manager.add_scoped_no_alias_aa_pass();
    pass_manager.add_basic_alias_analysis_pass();

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9")))]
    {
        pass_manager.add_early_cse_mem_ssa_pass();
        pass_manager.add_new_gvn_pass();
    }

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))]
    {
        pass_manager.add_aggressive_inst_combiner_pass();
        pass_manager.add_loop_unroll_and_jam_pass();
    }

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0", feature = "llvm7-0")))]
    {
        pass_manager.add_coroutine_early_pass();
        pass_manager.add_coroutine_split_pass();
        pass_manager.add_coroutine_elide_pass();
        pass_manager.add_coroutine_cleanup_pass();
    }

    pass_manager.run_on(&module);
}

#[test]
fn test_pass_manager_builder() {
    let pass_manager_builder = PassManagerBuilder::create();

    pass_manager_builder.set_optimization_level(Aggressive);
    pass_manager_builder.set_size_level(2);
    pass_manager_builder.set_inliner_with_threshold(42);
    pass_manager_builder.set_disable_unit_at_a_time(true);
    pass_manager_builder.set_disable_unroll_loops(true);
    pass_manager_builder.set_disable_simplify_lib_calls(true);

    let context = Context::create();
    let module = context.create_module("my_module");

    let fn_pass_manager = PassManager::create(&module);

    pass_manager_builder.populate_function_pass_manager(&fn_pass_manager);

    let void_type = context.void_type();
    let fn_type = void_type.fn_type(&[], false);
    let fn_value = module.add_function("my_fn", fn_type, None);
    let builder = context.create_builder();
    let entry = context.append_basic_block(fn_value, "entry");

    builder.position_at_end(entry);
    builder.build_return(None);

    #[cfg(not(feature = "llvm3-7"))]
    assert!(!fn_pass_manager.initialize());
    #[cfg(feature = "llvm3-7")]
    fn_pass_manager.initialize();

    // TODO: Test with actual changes? Would be true in that case
    // REVIEW: Segfaults in 4.0
    #[cfg(not(feature = "llvm4-0"))]
    assert!(!fn_pass_manager.run_on(&fn_value));

    assert!(!fn_pass_manager.finalize());

    let module_pass_manager = PassManager::create(());

    pass_manager_builder.populate_module_pass_manager(&module_pass_manager);

    let module2 = module.clone();

    // TODOC: In 3.6, 3.8, & 3.9 it returns false. Seems like a LLVM bug?
    #[cfg(not(any(feature = "llvm3-7", feature = "llvm6-0", feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", feature = "llvm11-0", feature = "llvm12-0")))]
    assert!(!module_pass_manager.run_on(&module));
    #[cfg(any(feature = "llvm3-7", feature = "llvm6-0", feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", feature = "llvm11-0", feature = "llvm12-0"))]
    assert!(module_pass_manager.run_on(&module));

    let lto_pass_manager = PassManager::create(());

    pass_manager_builder.populate_lto_pass_manager(&lto_pass_manager, false, false);

    assert!(lto_pass_manager.run_on(&module2));
}

#[test]
fn test_pass_registry() {
    let pass_registry = PassRegistry::get_global();

    pass_registry.initialize_core();
    pass_registry.initialize_transform_utils();
    pass_registry.initialize_scalar_opts();
    pass_registry.initialize_obj_carc_opts();
    pass_registry.initialize_vectorization();
    pass_registry.initialize_inst_combine();
    pass_registry.initialize_ipo();
    pass_registry.initialize_instrumentation();
    pass_registry.initialize_analysis();
    pass_registry.initialize_ipa();
    pass_registry.initialize_codegen();
    pass_registry.initialize_target();
    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))]
    pass_registry.initialize_aggressive_inst_combiner();
}
<|endoftext|>