<commit_before>
#[macro_use]
extern crate collect_mac;
extern crate env_logger;
extern crate futures;
extern crate gluon;

use std::sync::{Arc, Mutex};
use std::collections::BTreeMap;

use futures::{Async, Future};

use gluon::base::pos::Line;
use gluon::base::types::{ArcType, Type};
use gluon::{new_vm, Compiler};
use gluon::vm::compiler::UpvarInfo;
use gluon::vm::thread::{ThreadInternal, CALL_FLAG, LINE_FLAG};

const SIMPLE_EXPR: &'static str = r#"
    let f x = x

    let g x = f x
    g 1
    "#;

#[test]
fn function_hook() {
    let _ = env_logger::init();

    let thread = new_vm();
    let functions = Arc::new(Mutex::new(Vec::new()));
    {
        let functions = functions.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_context| {
            functions.lock().unwrap().push(
                debug_context
                    .stack_info(0)
                    .unwrap()
                    .function_name()
                    .expect("function_name")
                    .to_string(),
            );
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(CALL_FLAG);
    }
    Compiler::new()
        .implicit_prelude(false)
        .run_expr::<i32>(&thread, "test", SIMPLE_EXPR)
        .unwrap();

    assert_eq!(
        *functions.lock().unwrap(),
        vec!["test".to_string(), "g".to_string(), "f".to_string()]
    );
}

fn run_line_hook_test(source: &str) -> Vec<Line> {
    let thread = new_vm();
    {
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, _| Ok(Async::NotReady))));
        context.set_hook_mask(LINE_FLAG);
    }
    let mut execute = Compiler::new()
        .implicit_prelude(false)
        .run_expr_async::<i32>(&thread, "test", source)
        .map(|_| ());
    let mut result = Ok(Async::NotReady);

    let mut lines = Vec::new();
    loop {
        match result {
            Ok(Async::Ready(())) => break,
            Ok(Async::NotReady) => {
                let context = thread.context();
                let debug_info = context.debug_info();
                lines.push(
                    debug_info
                        .stack_info(0)
                        .expect("stack info")
                        .line()
                        .expect("expected line"),
                );
            }
            Err(err) => panic!("{}", err),
        }
        result = execute.poll();
    }
    lines
}

#[test]
fn line_hook() {
    let _ = env_logger::init();

    let lines = run_line_hook_test(SIMPLE_EXPR);
    assert_eq!(
        lines,
        vec![1, 3, 4, 3, 1]
            .into_iter()
            .map(Line::from)
            .collect::<Vec<_>>()
    );
}

#[test]
fn line_hook_recursive_functions() {
    let _ = env_logger::init();

    let expr = r#"
let f x = x
and g y = f
1
    "#;

    let lines = run_line_hook_test(expr);
    assert_eq!(
        lines,
        vec![1, 2, 3]
            .into_iter()
            .map(Line::from)
            .collect::<Vec<_>>()
    );
}

#[test]
fn line_hook_after_call() {
    let _ = env_logger::init();

    let thread = new_vm();
    {
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, _| Ok(Async::NotReady))));
        context.set_hook_mask(LINE_FLAG);
    }

    let expr = r#"
        let id x = x
        id 0
        1
    "#;
    let mut execute = Compiler::new()
        .implicit_prelude(false)
        .run_expr_async::<i32>(&thread, "test", expr)
        .map(|_| ());
    let mut result = Ok(Async::NotReady);

    let mut lines = Vec::new();
    loop {
        match result {
            Ok(Async::Ready(())) => break,
            Ok(Async::NotReady) => {
                let context = thread.context();
                let debug_info = context.debug_info();
                lines.push(debug_info.stack_info(0).unwrap().line().unwrap());
            }
            Err(err) => panic!("{}", err),
        }
        result = execute.poll();
    }

    assert_eq!(
        lines,
        vec![1, 2, 1, 3]
            .into_iter()
            .map(Line::from)
            .collect::<Vec<_>>()
    );
}

#[test]
fn implicit_prelude_lines_not_counted() {
    let _ = env_logger::init();

    let thread = new_vm();
    {
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_info| {
            if debug_info.stack_info(0).unwrap().source_name() == "test" {
                Ok(Async::NotReady)
            } else {
                Ok(Async::Ready(()))
            }
        })));
        context.set_hook_mask(LINE_FLAG);
    }
    let mut execute = Compiler::new()
        .run_expr_async::<i32>(&thread, "test", "1")
        .map(|_| ());
    let mut result = Ok(Async::NotReady);

    let mut lines = Vec::new();
    loop {
        match result {
            Ok(Async::Ready(())) => break,
            Ok(Async::NotReady) => {
                let context = thread.context();
                let debug_info = context.debug_info();
                let stack_info = debug_info.stack_info(0).unwrap();
                lines.push(stack_info.line().unwrap());
            }
            Err(err) => panic!("{}", err),
        }
        result = execute.poll();
    }

    assert_eq!(lines, vec![Line::from(0)]);
}

#[test]
fn read_variables() {
    let _ = env_logger::init();

    let thread = new_vm();
    let result = Arc::new(Mutex::new(BTreeMap::new()));
    {
        let result = result.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_context| {
            let stack_info = debug_context.stack_info(0).unwrap();
            result.lock().unwrap().insert(
                stack_info.line().unwrap().to_usize(),
                stack_info
                    .locals()
                    .map(|local| {
                        (local.name.declared_name().to_string(), local.typ.clone())
                    })
                    .collect::<Vec<_>>(),
            );
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(LINE_FLAG);
    }
    let expr = r#"
    let x = 1
    let y =
        let y2 = ""
        ()

    ()
    let z = 1.0
    1
    "#;
    Compiler::new()
        .implicit_prelude(false)
        .run_expr::<i32>(&thread, "test", expr)
        .unwrap();

    let map = result.lock().unwrap();
    assert_eq!(
        *map,
        collect![
            (1, vec![]),
            (3, vec![("x".to_string(), Type::int())]),
            (
                4,
                vec![
                    ("x".to_string(), Type::int()),
                    ("y2".to_string(), Type::string()),
                ]
            ),
            (
                6,
                vec![
                    ("x".to_string(), Type::int()),
                    ("y".to_string(), Type::unit()),
                ]
            ),
            (
                7,
                vec![
                    ("x".to_string(), Type::int()),
                    ("y".to_string(), Type::unit()),
                ]
            ),
            (
                8,
                vec![
                    ("x".to_string(), Type::int()),
                    ("y".to_string(), Type::unit()),
                    ("z".to_string(), Type::float()),
                ]
            ),
        ]
    );
}

#[test]
fn argument_types() {
    let _ = env_logger::init();

    let thread = new_vm();
    let result = Arc::new(Mutex::new(Vec::new()));
    {
        let result = result.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_context| {
            let stack_info = debug_context.stack_info(0).unwrap();
            result.lock().unwrap().push((
                stack_info.line().unwrap().to_usize(),
                stack_info
                    .locals()
                    .map(|local| {
                        (local.name.declared_name().to_string(), local.typ.clone())
                    })
                    .collect::<Vec<_>>(),
            ));
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(LINE_FLAG);
    }
    let expr = r#"
    let int_function x: Int -> Int = x
    let g = \y -> int_function y
    let f z = g z
    f 1
    "#;
    Compiler::new()
        .implicit_prelude(false)
        .run_expr::<i32>(&thread, "test", expr)
        .unwrap();

    let int_function: ArcType = Type::function(vec![Type::int()], Type::int());

    let map = result.lock().unwrap();
    assert_eq!(
        *map,
        vec![
            (1, vec![]),
            (2, vec![("int_function".to_string(), int_function.clone())]),
            (
                3,
                vec![
                    ("int_function".to_string(), int_function.clone()),
                    ("g".to_string(), int_function.clone()),
                ],
            ),
            (
                4,
                vec![
                    ("int_function".to_string(), int_function.clone()),
                    ("g".to_string(), int_function.clone()),
                    ("f".to_string(), int_function.clone()),
                ],
            ),
            (3, vec![("z".to_string(), Type::int())]),
            (2, vec![("y".to_string(), Type::int())]),
            (1, vec![("x".to_string(), Type::int())]),
        ]
    );
}

#[test]
fn source_name() {
    let _ = env_logger::init();

    let thread = new_vm();
    let result = Arc::new(Mutex::new(String::new()));
    {
        let result = result.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_context| {
            let stack_info = debug_context.stack_info(0).unwrap();
            *result.lock().unwrap() = stack_info.source_name().to_string();
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(LINE_FLAG);
    }
    let expr = r#"
    let x = 1
    let y =
        let y2 = ""
        ()

    ()
    let z = { x }
    1
    "#;
    Compiler::new()
        .implicit_prelude(false)
        .run_expr::<i32>(&thread, "test", expr)
        .unwrap();

    let name = result.lock().unwrap();
    assert_eq!(*name, "test");
}

#[test]
fn upvars() {
    let _ = env_logger::init();

    let thread = new_vm();
    let result = Arc::new(Mutex::new(Vec::new()));
    {
        let result = result.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_info| {
            let stack_info = debug_info.stack_info(0).unwrap();
            if stack_info.source_name() == "test" {
                result.lock().unwrap().push(stack_info.upvars().to_owned());
            }
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(CALL_FLAG);
    }
    let expr = r#"
    let x = 1
    let y = 2
    let f z =
        let g w = x
        g x + y + z
    f 3
    "#;
    Compiler::new()
        .run_expr::<i32>(&thread, "test", expr)
        .unwrap();

    assert_eq!(
        *result.lock().unwrap(),
        vec![
            vec![],
            vec![
                UpvarInfo {
                    name: "x".to_string(),
                    typ: Type::int(),
                },
                UpvarInfo {
                    name: "+".to_string(),
                    typ: Type::function(vec![Type::int(), Type::int()], Type::int()),
                },
                UpvarInfo {
                    name: "y".to_string(),
                    typ: Type::int(),
                },
            ],
            vec![
                UpvarInfo {
                    name: "x".to_string(),
                    typ: Type::int(),
                },
            ],
        ]
    );
}

#[test]
fn implicit_prelude_variable_names() {
    let _ = env_logger::init();

    let thread = new_vm();
    let functions = Arc::new(Mutex::new(Vec::<ArcType>::new()));
    {
        let functions = functions.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_context| {
            let stack_info = debug_context.stack_info(0).unwrap();
            functions.lock().unwrap().extend(
                stack_info
                    .locals()
                    .filter(|local| local.name.declared_name() == "__implicit_prelude")
                    .map(|local| local.typ.clone()),
            );
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(LINE_FLAG);
    }
    Compiler::new()
        .run_expr::<i32>(&thread, "test", "\n1")
        .unwrap();
    let f = functions.lock().unwrap();
    match *f[0] {
        Type::Record(ref row) => {
            assert!(
                row.row_iter()
                    .any(|field| { field.name.declared_name() == "make_Semigroup" })
            );
        }
        _ => panic!(),
    }
}
<commit_msg>Fix tests<commit_after>
#[macro_use]
extern crate collect_mac;
extern crate env_logger;
extern crate futures;
extern crate gluon;

use std::sync::{Arc, Mutex};
use std::collections::BTreeMap;

use futures::{Async, Future};

use gluon::base::pos::Line;
use gluon::base::types::{ArcType, Type};
use gluon::{new_vm, Compiler};
use gluon::vm::compiler::UpvarInfo;
use gluon::vm::thread::{ThreadInternal, CALL_FLAG, LINE_FLAG};

const SIMPLE_EXPR: &'static str = r#"
    let f x = x

    let g x = f x
    g 1
    "#;

#[test]
fn function_hook() {
    let _ = env_logger::init();

    let thread = new_vm();
    let functions = Arc::new(Mutex::new(Vec::new()));
    {
        let functions = functions.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_context| {
            functions.lock().unwrap().push(
                debug_context
                    .stack_info(0)
                    .unwrap()
                    .function_name()
                    .expect("function_name")
                    .to_string(),
            );
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(CALL_FLAG);
    }
    Compiler::new()
        .implicit_prelude(false)
        .run_expr::<i32>(&thread, "test", SIMPLE_EXPR)
        .unwrap();

    assert_eq!(
        *functions.lock().unwrap(),
        vec!["test".to_string(), "g".to_string(), "f".to_string()]
    );
}

fn run_line_hook_test(source: &str) -> Vec<Line> {
    let thread = new_vm();
    {
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, _| Ok(Async::NotReady))));
        context.set_hook_mask(LINE_FLAG);
    }
    let mut execute = Compiler::new()
        .implicit_prelude(false)
        .run_expr_async::<i32>(&thread, "test", source)
        .map(|_| ());
    let mut result = Ok(Async::NotReady);

    let mut lines = Vec::new();
    loop {
        match result {
            Ok(Async::Ready(())) => break,
            Ok(Async::NotReady) => {
                let context = thread.context();
                let debug_info = context.debug_info();
                lines.push(
                    debug_info
                        .stack_info(0)
                        .expect("stack info")
                        .line()
                        .expect("expected line"),
                );
            }
            Err(err) => panic!("{}", err),
        }
        result = execute.poll();
    }
    lines
}

#[test]
fn line_hook() {
    let _ = env_logger::init();

    let lines = run_line_hook_test(SIMPLE_EXPR);
    assert_eq!(
        lines,
        vec![1, 3, 4, 3, 1]
            .into_iter()
            .map(Line::from)
            .collect::<Vec<_>>()
    );
}

#[test]
fn line_hook_recursive_functions() {
    let _ = env_logger::init();

    let expr = r#"
let f x = x
and g y = f
1
    "#;

    let lines = run_line_hook_test(expr);
    assert_eq!(
        lines,
        vec![1, 2, 3]
            .into_iter()
            .map(Line::from)
            .collect::<Vec<_>>()
    );
}

#[test]
fn line_hook_after_call() {
    let _ = env_logger::init();

    let thread = new_vm();
    {
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, _| Ok(Async::NotReady))));
        context.set_hook_mask(LINE_FLAG);
    }

    let expr = r#"
        let id x = x
        id 0
        1
    "#;
    let mut execute = Compiler::new()
        .implicit_prelude(false)
        .run_expr_async::<i32>(&thread, "test", expr)
        .map(|_| ());
    let mut result = Ok(Async::NotReady);

    let mut lines = Vec::new();
    loop {
        match result {
            Ok(Async::Ready(())) => break,
            Ok(Async::NotReady) => {
                let context = thread.context();
                let debug_info = context.debug_info();
                lines.push(debug_info.stack_info(0).unwrap().line().unwrap());
            }
            Err(err) => panic!("{}", err),
        }
        result = execute.poll();
    }

    assert_eq!(
        lines,
        vec![1, 2, 1, 3]
            .into_iter()
            .map(Line::from)
            .collect::<Vec<_>>()
    );
}

#[test]
// FIXME
#[ignore]
fn implicit_prelude_lines_not_counted() {
    let _ = env_logger::init();

    let thread = new_vm();
    {
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_info| {
            if debug_info.stack_info(0).unwrap().source_name() == "test" {
                Ok(Async::NotReady)
            } else {
                Ok(Async::Ready(()))
            }
        })));
        context.set_hook_mask(LINE_FLAG);
    }
    let mut execute = Compiler::new()
        .run_expr_async::<i32>(&thread, "test", "1")
        .map(|_| ());
    let mut result = Ok(Async::NotReady);

    let mut lines = Vec::new();
    loop {
        match result {
            Ok(Async::Ready(())) => break,
            Ok(Async::NotReady) => {
                let context = thread.context();
                let debug_info = context.debug_info();
                let stack_info = debug_info.stack_info(0).unwrap();
                lines.push(stack_info.line().unwrap());
            }
            Err(err) => panic!("{}", err),
        }
        result = execute.poll();
    }

    assert_eq!(lines, vec![Line::from(0)]);
}

#[test]
fn read_variables() {
    let _ = env_logger::init();

    let thread = new_vm();
    let result = Arc::new(Mutex::new(BTreeMap::new()));
    {
        let result = result.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_context| {
            let stack_info = debug_context.stack_info(0).unwrap();
            result.lock().unwrap().insert(
                stack_info.line().unwrap().to_usize(),
                stack_info
                    .locals()
                    .map(|local| {
                        (local.name.declared_name().to_string(), local.typ.clone())
                    })
                    .collect::<Vec<_>>(),
            );
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(LINE_FLAG);
    }
    let expr = r#"
    let x = 1
    let y =
        let y2 = ""
        ()

    ()
    let z = 1.0
    1
    "#;
    Compiler::new()
        .implicit_prelude(false)
        .run_expr::<i32>(&thread, "test", expr)
        .unwrap();

    let map = result.lock().unwrap();
    assert_eq!(
        *map,
        collect![
            (1, vec![]),
            (3, vec![("x".to_string(), Type::int())]),
            (
                4,
                vec![
                    ("x".to_string(), Type::int()),
                    ("y2".to_string(), Type::string()),
                ]
            ),
            (
                6,
                vec![
                    ("x".to_string(), Type::int()),
                    ("y".to_string(), Type::unit()),
                ]
            ),
            (
                7,
                vec![
                    ("x".to_string(), Type::int()),
                    ("y".to_string(), Type::unit()),
                ]
            ),
            (
                8,
                vec![
                    ("x".to_string(), Type::int()),
                    ("y".to_string(), Type::unit()),
                    ("z".to_string(), Type::float()),
                ]
            ),
        ]
    );
}

#[test]
fn argument_types() {
    let _ = env_logger::init();

    let thread = new_vm();
    let result = Arc::new(Mutex::new(Vec::new()));
    {
        let result = result.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_context| {
            let stack_info = debug_context.stack_info(0).unwrap();
            result.lock().unwrap().push((
                stack_info.line().unwrap().to_usize(),
                stack_info
                    .locals()
                    .map(|local| {
                        (local.name.declared_name().to_string(), local.typ.clone())
                    })
                    .collect::<Vec<_>>(),
            ));
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(LINE_FLAG);
    }
    let expr = r#"
    let int_function x: Int -> Int = x
    let g = \y -> int_function y
    let f z = g z
    f 1
    "#;
    Compiler::new()
        .implicit_prelude(false)
        .run_expr::<i32>(&thread, "test", expr)
        .unwrap();

    let int_function: ArcType = Type::function(vec![Type::int()], Type::int());

    let map = result.lock().unwrap();
    assert_eq!(
        *map,
        vec![
            (1, vec![]),
            (2, vec![("int_function".to_string(), int_function.clone())]),
            (
                3,
                vec![
                    ("int_function".to_string(), int_function.clone()),
                    ("g".to_string(), int_function.clone()),
                ],
            ),
            (
                4,
                vec![
                    ("int_function".to_string(), int_function.clone()),
                    ("g".to_string(), int_function.clone()),
                    ("f".to_string(), int_function.clone()),
                ],
            ),
            (3, vec![("z".to_string(), Type::int())]),
            (2, vec![("y".to_string(), Type::int())]),
            (1, vec![("x".to_string(), Type::int())]),
        ]
    );
}

#[test]
fn source_name() {
    let _ = env_logger::init();

    let thread = new_vm();
    let result = Arc::new(Mutex::new(String::new()));
    {
        let result = result.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_context| {
            let stack_info = debug_context.stack_info(0).unwrap();
            *result.lock().unwrap() = stack_info.source_name().to_string();
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(LINE_FLAG);
    }
    let expr = r#"
    let x = 1
    let y =
        let y2 = ""
        ()

    ()
    let z = { x }
    1
    "#;
    Compiler::new()
        .implicit_prelude(false)
        .run_expr::<i32>(&thread, "test", expr)
        .unwrap();

    let name = result.lock().unwrap();
    assert_eq!(*name, "test");
}

#[test]
fn upvars() {
    let _ = env_logger::init();

    let thread = new_vm();
    let result = Arc::new(Mutex::new(Vec::new()));
    {
        let result = result.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_info| {
            let stack_info = debug_info.stack_info(0).unwrap();
            if stack_info.source_name() == "test" {
                result.lock().unwrap().push(stack_info.upvars().to_owned());
            }
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(CALL_FLAG);
    }
    let expr = r#"
    let x = 1
    let y = 2
    let f z =
        let g w = x
        g x #Int+ y #Int+ z
    f 3
    "#;
    Compiler::new()
        .implicit_prelude(false)
        .run_expr::<i32>(&thread, "test", expr)
        .unwrap();

    assert_eq!(
        *result.lock().unwrap(),
        vec![
            vec![],
            vec![
                UpvarInfo {
                    name: "x".to_string(),
                    typ: Type::int(),
                },
                UpvarInfo {
                    name: "y".to_string(),
                    typ: Type::int(),
                },
            ],
            vec![
                UpvarInfo {
                    name: "x".to_string(),
                    typ: Type::int(),
                },
            ],
        ]
    );
}

#[test]
fn implicit_prelude_variable_names() {
    let _ = env_logger::init();

    let thread = new_vm();
    let functions = Arc::new(Mutex::new(Vec::<ArcType>::new()));
    {
        let functions = functions.clone();
        let mut context = thread.context();
        context.set_hook(Some(Box::new(move |_, debug_context| {
            let stack_info = debug_context.stack_info(0).unwrap();
            functions.lock().unwrap().extend(
                stack_info
                    .locals()
                    .filter(|local| local.name.declared_name() == "__implicit_prelude")
                    .map(|local| local.typ.clone()),
            );
            Ok(Async::Ready(()))
        })));
        context.set_hook_mask(LINE_FLAG);
    }
    Compiler::new()
        .run_expr::<i32>(&thread, "test", "\n1")
        .unwrap();
    let f = functions.lock().unwrap();
    match *f[0] {
        Type::Record(ref row) => {
            assert!(
                row.row_iter()
                    .any(|field| { field.name.declared_name() == "make_Semigroup" })
            );
        }
        _ => panic!(),
    }
}
<|endoftext|>


<commit_before>#![cfg(unix)]

extern crate curl;
extern crate mio;

use std::collections::HashMap;
use std::io::{Read, Cursor};
use std::time::Duration;

use curl::easy::{Easy, List};
use curl::multi::Multi;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
    })
}

use server::Server;
mod server;

#[test]
fn smoke() {
    let m = Multi::new();
    let mut e = Easy::new();

    let s = Server::new();
    s.receive("\
GET / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
\r\n");
    s.send("HTTP/1.1 200 OK\r\n\r\n");

    t!(e.url(&s.url("/")));
    let _e = t!(m.add(e));
    while t!(m.perform()) > 0 {
        t!(m.wait(&mut [], Duration::from_secs(1)));
    }
}

#[test]
fn smoke2() {
    let m = Multi::new();

    let s1 = Server::new();
    s1.receive("\
GET / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
\r\n");
    s1.send("HTTP/1.1 200 OK\r\n\r\n");

    let s2 = Server::new();
    s2.receive("\
GET / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
\r\n");
    s2.send("HTTP/1.1 200 OK\r\n\r\n");

    let mut e1 = Easy::new();
    t!(e1.url(&s1.url("/")));
    let _e1 = t!(m.add(e1));
    let mut e2 = Easy::new();
    t!(e2.url(&s2.url("/")));
    let _e2 = t!(m.add(e2));

    while t!(m.perform()) > 0 {
        t!(m.wait(&mut [], Duration::from_secs(1)));
    }

    let mut done = 0;
    m.messages(|msg| {
        msg.result().unwrap().unwrap();
        done += 1;
    });
    assert_eq!(done, 2);
}

#[test]
fn upload_lots() {
    use curl::multi::{Socket, SocketEvents, Events};

    #[derive(Debug)]
    enum Message {
        Timeout(Option<Duration>),
        Wait(Socket, SocketEvents, usize),
    }

    let mut m = Multi::new();
    let poll = t!(mio::Poll::new());
    let (tx, rx) = mio::channel::channel();
    let tx2 = tx.clone();
    t!(m.socket_function(move |socket, events, token| {
        t!(tx2.send(Message::Wait(socket, events, token)));
    }));
    t!(m.timer_function(move |dur| {
        t!(tx.send(Message::Timeout(dur)));
        true
    }));

    let s = Server::new();
    s.receive(&format!("\
PUT / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
Content-Length: 131072\r\n\
\r\n\
{}\n", vec!["a"; 128 * 1024 - 1].join("")));
    s.send("\
HTTP/1.1 200 OK\r\n\
\r\n");

    let mut data = vec![b'a'; 128 * 1024 - 1];
    data.push(b'\n');
    let mut data = Cursor::new(data);
    let mut list = List::new();
    t!(list.append("Expect:"));
    let mut h = Easy::new();
    t!(h.url(&s.url("/")));
    t!(h.put(true));
    t!(h.read_function(move |buf| {
        Ok(data.read(buf).unwrap())
    }));
    t!(h.in_filesize(128 * 1024));
    t!(h.upload(true));
    t!(h.http_headers(list));

    t!(poll.register(&rx,
                     mio::Token(0),
                     mio::Ready::all(),
                     mio::PollOpt::level()));

    let e = t!(m.add(h));

    assert!(t!(m.perform()) > 0);
    let mut next_token = 1;
    let mut token_map = HashMap::new();
    let mut cur_timeout = None;
    let mut events = mio::Events::with_capacity(128);
    let mut running = true;

    while running {
        let n = t!(poll.poll(&mut events, cur_timeout));

        if n == 0 {
            if t!(m.timeout()) == 0 {
                running = false;
            }
        }

        for event in events.iter() {
            while event.token() == mio::Token(0) {
                match rx.try_recv() {
                    Ok(Message::Timeout(dur)) => cur_timeout = dur,
                    Ok(Message::Wait(socket, events, token)) => {
                        let evented = mio::unix::EventedFd(&socket);
                        if events.remove() {
                            token_map.remove(&token).unwrap();
                        } else {
                            let mut e = mio::Ready::none();
                            if events.input() {
                                e = e | mio::Ready::readable();
                            }
                            if events.output() {
                                e = e | mio::Ready::writable();
                            }
                            if token == 0 {
                                let token = next_token;
                                next_token += 1;
                                t!(m.assign(socket, token));
                                token_map.insert(token, socket);
                                t!(poll.register(&evented,
                                                 mio::Token(token),
                                                 e,
                                                 mio::PollOpt::level()));
                            } else {
                                t!(poll.reregister(&evented,
                                                   mio::Token(token),
                                                   e,
                                                   mio::PollOpt::level()));
                            }
                        }
                    }
                    Err(_) => break,
                }
            }

            if event.token() == mio::Token(0) {
                continue
            }

            let token = event.token();
            let socket = token_map[&token.into()];
            let mut e = Events::new();
            if event.kind().is_readable() {
                e.input(true);
            }
            if event.kind().is_writable() {
                e.output(true);
            }
            if event.kind().is_error() {
                e.error(true);
            }
            let remaining = t!(m.action(socket, &e));
            if remaining == 0 {
                running = false;
            }
        }
    }

    let mut done = 0;
    m.messages(|m| {
        m.result().unwrap().unwrap();
        done += 1;
    });
    assert_eq!(done, 1);

    let mut e = t!(m.remove(e));
    assert_eq!(t!(e.response_code()), 200);
}

#[cfg(unix)]
#[test]
fn waitfds() {
    use std::fs::File;
    use std::os::unix::io::AsRawFd;
    use curl::multi::WaitFd;

    let filenames = ["/dev/null", "/dev/zero", "/dev/urandom"];
    let files: Vec<File> = filenames.iter()
        .map(|filename| File::open(filename).unwrap())
        .collect();
    let mut waitfds: Vec<WaitFd> = files.iter().map(|f| {
        let mut waitfd = WaitFd::new();
        waitfd.set_fd(f.as_raw_fd());
        waitfd.poll_on_read(true);
        waitfd
    }).collect();

    let m = Multi::new();
    let events = t!(m.wait(&mut waitfds, Duration::from_secs(1)));
    assert_eq!(events, 3);
    for waitfd in waitfds {
        assert!(waitfd.received_read());
    }
}
<commit_msg>Limit the waitfds test to Linux only<commit_after>#![cfg(unix)]

extern crate curl;
extern crate mio;

use std::collections::HashMap;
use std::io::{Read, Cursor};
use std::time::Duration;

use curl::easy::{Easy, List};
use curl::multi::Multi;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
    })
}

use server::Server;
mod server;

#[test]
fn smoke() {
    let m = Multi::new();
    let mut e = Easy::new();

    let s = Server::new();
    s.receive("\
GET / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
\r\n");
    s.send("HTTP/1.1 200 OK\r\n\r\n");

    t!(e.url(&s.url("/")));
    let _e = t!(m.add(e));
    while t!(m.perform()) > 0 {
        t!(m.wait(&mut [], Duration::from_secs(1)));
    }
}

#[test]
fn smoke2() {
    let m = Multi::new();

    let s1 = Server::new();
    s1.receive("\
GET / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
\r\n");
    s1.send("HTTP/1.1 200 OK\r\n\r\n");

    let s2 = Server::new();
    s2.receive("\
GET / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
\r\n");
    s2.send("HTTP/1.1 200 OK\r\n\r\n");

    let mut e1 = Easy::new();
    t!(e1.url(&s1.url("/")));
    let _e1 = t!(m.add(e1));
    let mut e2 = Easy::new();
    t!(e2.url(&s2.url("/")));
    let _e2 = t!(m.add(e2));

    while t!(m.perform()) > 0 {
        t!(m.wait(&mut [], Duration::from_secs(1)));
    }

    let mut done = 0;
    m.messages(|msg| {
        msg.result().unwrap().unwrap();
        done += 1;
    });
    assert_eq!(done, 2);
}

#[test]
fn upload_lots() {
    use curl::multi::{Socket, SocketEvents, Events};

    #[derive(Debug)]
    enum Message {
        Timeout(Option<Duration>),
        Wait(Socket, SocketEvents, usize),
    }

    let mut m = Multi::new();
    let poll = t!(mio::Poll::new());
    let (tx, rx) = mio::channel::channel();
    let tx2 = tx.clone();
    t!(m.socket_function(move |socket, events, token| {
        t!(tx2.send(Message::Wait(socket, events, token)));
    }));
    t!(m.timer_function(move |dur| {
        t!(tx.send(Message::Timeout(dur)));
        true
    }));

    let s = Server::new();
    s.receive(&format!("\
PUT / HTTP/1.1\r\n\
Host: 127.0.0.1:$PORT\r\n\
Accept: */*\r\n\
Content-Length: 131072\r\n\
\r\n\
{}\n", vec!["a"; 128 * 1024 - 1].join("")));
    s.send("\
HTTP/1.1 200 OK\r\n\
\r\n");

    let mut data = vec![b'a'; 128 * 1024 - 1];
    data.push(b'\n');
    let mut data = Cursor::new(data);
    let mut list = List::new();
    t!(list.append("Expect:"));
    let mut h = Easy::new();
    t!(h.url(&s.url("/")));
    t!(h.put(true));
    t!(h.read_function(move |buf| {
        Ok(data.read(buf).unwrap())
    }));
    t!(h.in_filesize(128 * 1024));
    t!(h.upload(true));
    t!(h.http_headers(list));

    t!(poll.register(&rx,
                     mio::Token(0),
                     mio::Ready::all(),
                     mio::PollOpt::level()));

    let e = t!(m.add(h));

    assert!(t!(m.perform()) > 0);
    let mut next_token = 1;
    let mut token_map = HashMap::new();
    let mut cur_timeout = None;
    let mut events = mio::Events::with_capacity(128);
    let mut running = true;

    while running {
        let n = t!(poll.poll(&mut events, cur_timeout));

        if n == 0 {
            if t!(m.timeout()) == 0 {
                running = false;
            }
        }

        for event in events.iter() {
            while event.token() == mio::Token(0) {
                match rx.try_recv() {
                    Ok(Message::Timeout(dur)) => cur_timeout = dur,
                    Ok(Message::Wait(socket, events, token)) => {
                        let evented = mio::unix::EventedFd(&socket);
                        if events.remove() {
                            token_map.remove(&token).unwrap();
                        } else {
                            let mut e = mio::Ready::none();
                            if events.input() {
                                e = e | mio::Ready::readable();
                            }
                            if events.output() {
                                e = e | mio::Ready::writable();
                            }
                            if token == 0 {
                                let token = next_token;
                                next_token += 1;
                                t!(m.assign(socket, token));
                                token_map.insert(token, socket);
                                t!(poll.register(&evented,
                                                 mio::Token(token),
                                                 e,
                                                 mio::PollOpt::level()));
                            } else {
                                t!(poll.reregister(&evented,
                                                   mio::Token(token),
                                                   e,
                                                   mio::PollOpt::level()));
                            }
                        }
                    }
                    Err(_) => break,
                }
            }

            if event.token() == mio::Token(0) {
                continue
            }

            let token = event.token();
            let socket = token_map[&token.into()];
            let mut e = Events::new();
            if event.kind().is_readable() {
                e.input(true);
            }
            if event.kind().is_writable() {
                e.output(true);
            }
            if event.kind().is_error() {
                e.error(true);
            }
            let remaining = t!(m.action(socket, &e));
            if remaining == 0 {
                running = false;
            }
        }
    }

    let mut done = 0;
    m.messages(|m| {
        m.result().unwrap().unwrap();
        done += 1;
    });
    assert_eq!(done, 1);

    let mut e = t!(m.remove(e));
    assert_eq!(t!(e.response_code()), 200);
}

// Tests passing raw file descriptors to Multi::wait. The test is limited to Linux only as the
// semantics of the underlying poll(2) system call used by curl apparently differ on other
// platforms, making the test fail.
#[cfg(target_os = "linux")]
#[test]
fn waitfds() {
    use std::fs::File;
    use std::os::unix::io::AsRawFd;
    use curl::multi::WaitFd;

    let filenames = ["/dev/null", "/dev/zero", "/dev/urandom"];
    let files: Vec<File> = filenames.iter()
        .map(|filename| File::open(filename).unwrap())
        .collect();
    let mut waitfds: Vec<WaitFd> = files.iter().map(|f| {
        let mut waitfd = WaitFd::new();
        waitfd.set_fd(f.as_raw_fd());
        waitfd.poll_on_read(true);
        waitfd
    }).collect();

    let m = Multi::new();
    let events = t!(m.wait(&mut waitfds, Duration::from_secs(1)));
    assert_eq!(events, 3);
    for waitfd in waitfds {
        assert!(waitfd.received_read());
    }
}
<|endoftext|>


<commit_before>extern crate vastatrix;
extern crate futures;
extern crate env_logger;
use futures::{Future,Async};
use vastatrix::{RamStore,Store};
use vastatrix::LogPos;
use vastatrix::{Error,ErrorKind};

#[test]
fn can_append_one() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();
    store.append_entry(current, next, b"foobar".to_vec()).wait().expect("append_entry");
    let (off, val) = store.fetch_next(current).wait().expect("fetch");

    assert_eq!((off, val), (next, b"foobar".to_vec()))
}

#[test]
fn fetching_one_is_lazy() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();
    let mut fetch_f = store.fetch_next(current);
    assert_eq!(fetch_f.poll().expect("poll-notready"), Async::NotReady);

    store.append_entry(current, next, b"foobar".to_vec()).wait().expect("append_entry");

    let (off, val) = fetch_f.wait().expect("fetch");
    assert_eq!((off, val), (next, b"foobar".to_vec()))
}

#[test]
fn writes_are_lazy() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();

    let store_f = store.append_entry(current, next, b"foobar".to_vec());
    let mut fetch_f = store.fetch_next(current);
    assert_eq!(fetch_f.poll().expect("poll-notready"), Async::NotReady);

    store_f.wait().expect("append_entry");

    let (off, val) = fetch_f.wait().expect("fetch");
    assert_eq!((off, val), (next, b"foobar".to_vec()))
}

#[test]
fn can_write_many() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();
    store.append_entry(current, next, b"foo".to_vec()).wait().expect("append_entry 1");
    let current = next; let next = next.next();
    store.append_entry(current, next, b"bar".to_vec()).wait().expect("append_entry 2");

    let fetch_f = store.fetch_next(LogPos::zero())
                  .and_then(|(curr, first)| {
                          store.fetch_next(curr).map(|(_, second)| vec![first, second])
                          });
    let res = fetch_f.wait().expect("fetch");
    assert_eq!(res, vec![b"foo", b"bar"])
}

#[test]
fn cannot_overwrite_item() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();

    store.append_entry(current, next, b"foo".to_vec()).wait().expect("append_entry 1");
    let overwrite_res = store.append_entry(current, next, b"bar".to_vec()).wait();

    let expected_seq = head_from_error(overwrite_res.unwrap_err());
    assert_eq!(expected_seq, Some(next));
}

#[test]
fn cannot_overwrite_history() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();

    store.append_entry(current, next, b"foo".to_vec()).wait().expect("append_entry 1");
    let current = next; let next = next.next();
    store.append_entry(current, next, b"bar".to_vec()).wait().expect("append_entry 1");
    let overwrite_res = store.append_entry(LogPos::zero(), LogPos::zero().next(), b"moo".to_vec()).wait();

    let expected_seq = head_from_error(overwrite_res.unwrap_err());
    assert_eq!(expected_seq, Some(next));
}

#[test]
fn error_feedback_should_indicate_new_head() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();

    store.append_entry(current, next, b"foo".to_vec()).wait().expect("append_entry 1");
    let overwrite_res = store.append_entry(LogPos::zero(), LogPos::zero().next(), b"moo".to_vec()).wait();

    let new_head = head_from_error(overwrite_res.unwrap_err()).expect("current sequence number");

    let final_write = store.append_entry(new_head, new_head.next(), b"moo".to_vec()).wait();
    assert!(final_write.is_ok());
}

#[test]
fn concurrent_writes_should_be_able_to_recover() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();

    // Request a write from a slow client
    let write_1 = store.append_entry(current, next, b"foo".to_vec());
    // A second client gets there first
    store.append_entry(current, next, b"foo".to_vec()).wait().expect("append_entry 1");

    // Wait for the first write to be completed
    let overwrite_res = write_1.wait();

    // Retry the first write
    let new_head = head_from_error(overwrite_res.unwrap_err()).expect("current sequence number");
    let final_write = store.append_entry(new_head, new_head.next(), b"foo".to_vec()).wait();
    assert!(final_write.is_ok());
}

fn head_from_error(error: Error) -> Option<LogPos> {
    if let &ErrorKind::BadSequence(n) = error.kind() {
        Some(n)
    } else {
        None
    }
}
<commit_msg>Run all store tests to run inside tasks.<commit_after>extern crate vastatrix;
extern crate futures;
extern crate env_logger;
use futures::{Future,Async, task};
use vastatrix::{RamStore,Store};
use vastatrix::LogPos;
use vastatrix::{Error,ErrorKind};
use std::sync::Arc;

struct NullUnpark;

impl task::Unpark for NullUnpark {
    fn unpark(&self) {}
}

fn null_parker() -> Arc<task::Unpark> {
    Arc::new(NullUnpark)
}

#[test]
fn can_append_one() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();
    task::spawn(store.append_entry(current, next, b"foobar".to_vec())).wait_future().expect("append_entry");
    let (off, val) = task::spawn(store.fetch_next(current)).wait_future().expect("fetch");

    assert_eq!((off, val), (next, b"foobar".to_vec()))
}

#[test]
fn fetching_one_is_lazy() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();
    let mut fetch_f = task::spawn(store.fetch_next(current));
    assert_eq!(fetch_f.poll_future(null_parker()).expect("poll-notready"), Async::NotReady);

    task::spawn(store.append_entry(current, next, b"foobar".to_vec())).wait_future().expect("append_entry");

    let (off, val) = fetch_f.wait_future().expect("fetch");
    assert_eq!((off, val), (next, b"foobar".to_vec()))
}

#[test]
fn writes_are_lazy() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();

    let mut store_f = task::spawn(store.append_entry(current, next, b"foobar".to_vec()));
    let mut fetch_f = task::spawn(store.fetch_next(current));
    assert_eq!(fetch_f.poll_future(null_parker()).expect("poll-notready"), Async::NotReady);

    store_f.wait_future().expect("append_entry");

    let (off, val) = fetch_f.wait_future().expect("fetch");
    assert_eq!((off, val), (next, b"foobar".to_vec()))
}

#[test]
fn can_write_many() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();
    task::spawn(store.append_entry(current, next, b"foo".to_vec())).wait_future().expect("append_entry 1");
    let current = next; let next = next.next();
    task::spawn(store.append_entry(current, next, b"bar".to_vec())).wait_future().expect("append_entry 2");

    let fetch_f = store.fetch_next(LogPos::zero())
                  .and_then(|(curr, first)| {
                          store.fetch_next(curr).map(|(_, second)| vec![first, second])
                          });
    let res = task::spawn(fetch_f).wait_future().expect("fetch");
    assert_eq!(res, vec![b"foo", b"bar"])
}

#[test]
fn cannot_overwrite_item() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();

    task::spawn(store.append_entry(current, next, b"foo".to_vec())).wait_future().expect("append_entry 1");
    let overwrite_res = task::spawn(store.append_entry(current, next, b"bar".to_vec())).wait_future();

    let expected_seq = head_from_error(overwrite_res.unwrap_err());
    assert_eq!(expected_seq, Some(next));
}

#[test]
fn cannot_overwrite_history() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();

    task::spawn(store.append_entry(current, next, b"foo".to_vec())).wait_future().expect("append_entry 1");
    let current = next; let next = next.next();
    task::spawn(store.append_entry(current, next, b"bar".to_vec())).wait_future().expect("append_entry 1");
    let overwrite_res = task::spawn(store.append_entry(LogPos::zero(), LogPos::zero().next(), b"moo".to_vec())).wait_future();

    let expected_seq = head_from_error(overwrite_res.unwrap_err());
    assert_eq!(expected_seq, Some(next));
}

#[test]
fn error_feedback_should_indicate_new_head() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();

    task::spawn(store.append_entry(current, next, b"foo".to_vec())).wait_future().expect("append_entry 1");
    let overwrite_res = task::spawn(store.append_entry(LogPos::zero(), LogPos::zero().next(), b"moo".to_vec())).wait_future();

    let new_head = head_from_error(overwrite_res.unwrap_err()).expect("current sequence number");

    let final_write = task::spawn(store.append_entry(new_head, new_head.next(), b"moo".to_vec())).wait_future();
    assert!(final_write.is_ok());
}

#[test]
fn concurrent_writes_should_be_able_to_recover() {
    env_logger::init().unwrap_or(());
    let store = RamStore::new();
    let current = LogPos::zero();
    let next = current.next();

    // Request a write from a slow client
    let mut write_1 = task::spawn(store.append_entry(current, next, b"foo".to_vec()));
    // A second client gets there first
    task::spawn(store.append_entry(current, next, b"foo".to_vec())).wait_future().expect("append_entry 1");

    // Wait for the first write to be completed
    let overwrite_res = write_1.wait_future();

    // Retry the first write
    let new_head = head_from_error(overwrite_res.unwrap_err()).expect("current sequence number");
    let final_write = task::spawn(store.append_entry(new_head, new_head.next(), b"foo".to_vec())).wait_future();
    assert!(final_write.is_ok());
}

fn head_from_error(error: Error) -> Option<LogPos> {
    if let &ErrorKind::BadSequence(n) = error.kind() {
        Some(n)
    } else {
        None
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(interpolate_idents)]

macro_rules! define_foo {
    ($x:ident) => ( interpolate_idents! {
        fn [foo_ $x _1]() -> u32 { 1 }

        struct [Foo $x] { [$x _30]: u32 }
        impl [Foo $x] {
            pub fn new() -> [Foo $x] {
                [Foo $x] { [$x _30]: 30 }
            }
        }
    } )
}

define_foo!(bar);

#[test]
fn test_macro() {
    assert_eq!(foo_bar_1(), 1);
    assert_eq!(Foobar::new().bar_30, 30);
}

macro_rules! define_brackets {
    () => ( interpolate_idents! {
        fn brackets() -> Vec<i32> {
            let mut b: Vec<i32> = vec![];
            let c: Vec<i32> = vec![1, 2, 3];
            b.push(c[1]);
            b
        }
    } )
}

define_brackets!();

#[test]
fn test_brackets() {
    assert_eq!(brackets(), vec![2]);
}
<commit_msg>Update test<commit_after>#![feature(plugin)]
#![plugin(interpolate_idents)]

macro_rules! define_foo {
    ($x:ident) => ( interpolate_idents! {
        fn [foo_ $x _1]() -> u32 { 1 }

        struct [Foo $x] { [$x _30]: u32 }
        impl [Foo $x] {
            pub fn new() -> [Foo $x] {
                [Foo $x] { [$x _30]: 30 }
            }
        }
    } )
}

define_foo!(bar);

#[test]
fn test_macro() {
    assert_eq!(foo_bar_1(), 1);
    assert_eq!(Foobar::new().bar_30, 30);
}

macro_rules! define_brackets {
    () => ( interpolate_idents! {
        fn brackets(data: &[i32; 1]) -> Vec<i32> {
            let mut b: Vec<i32> = vec![];
            let c: Vec<i32> = vec![1, 2, 3];
            let d: Vec<i32> = vec![1; 25];
            b.push(c[1]);
            b.push(d[1]);
            b.push(data[0]);
            b
        }
    } )
}

define_brackets!();

#[test]
fn test_brackets() {
    let data = [1; 1];
    assert_eq!(brackets(&data), vec![2, 1, 1]);
}
<|endoftext|>


<commit_before>use gdk_pixbuf::{PixbufLoader, PixbufLoaderExt};
use gio;
use markup5ever::{LocalName, Namespace, QualName};
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::rc::Rc;

use crate::allowed_url::{AllowedUrl, AllowedUrlError, Fragment};
use crate::create_node::create_node;
use crate::css::{cascade, Origin, Stylesheet};
use crate::error::LoadingError;
use crate::handle::LoadOptions;
use crate::io::{self, BinaryData};
use crate::node::{NodeData, NodeType, RsvgNode};
use crate::property_bag::PropertyBag;
use crate::structure::{IntrinsicDimensions, Svg};
use crate::surface_utils::shared_surface::SharedImageSurface;
use crate::text::NodeChars;
use crate::xml::xml_load_from_possibly_compressed_stream;

/// A loaded SVG file and its derived data
///
/// This contains the tree of nodes (SVG elements), the mapping
/// of id to node, and the CSS styles defined for this SVG.
pub struct Document {
    tree: RsvgNode,

    ids: HashMap<String, RsvgNode>,

    // These require interior mutability because we load the extern
    // resources all over the place.  Eventually we'll be able to do this
    // once, at loading time, and keep this immutable.
    externs: RefCell<Resources>,
    images: RefCell<Images>,

    // Once we do not need to load externs, we can drop this as well
    load_options: LoadOptions,
}

impl Document {
    pub fn load_from_stream(
        load_options: &LoadOptions,
        stream: &gio::InputStream,
        cancellable: Option<&gio::Cancellable>,
    ) -> Result<Document, LoadingError> {
        xml_load_from_possibly_compressed_stream(
            DocumentBuilder::new(load_options),
            load_options.unlimited_size,
            stream,
            cancellable,
        )
    }

    pub fn root(&self) -> RsvgNode {
        self.tree.clone()
    }

    pub fn lookup(&self, fragment: &Fragment) -> Result<RsvgNode, LoadingError> {
        if fragment.uri().is_some() {
            self.externs
                .borrow_mut()
                .lookup(&self.load_options, fragment)
        } else {
            self.lookup_node_by_id(fragment.fragment())
                .ok_or(LoadingError::BadUrl)
        }
    }

    pub fn lookup_node_by_id(&self, id: &str) -> Option<RsvgNode> {
        self.ids.get(id).map(|n| (*n).clone())
    }

    pub fn lookup_image(&self, href: &str) -> Result<SharedImageSurface, LoadingError> {
        let aurl = AllowedUrl::from_href(href, self.load_options.base_url.as_ref())
            .map_err(|_| LoadingError::BadUrl)?;

        self.images.borrow_mut().lookup(&self.load_options, &aurl)
    }

    pub fn get_intrinsic_dimensions(&self) -> IntrinsicDimensions {
        let root = self.root();
        let node_data = root.borrow();

        assert!(node_data.get_type() == NodeType::Svg);
        node_data.get_impl::<Svg>().get_intrinsic_dimensions()
    }
}

struct Resources {
    resources: HashMap<AllowedUrl, Result<Rc<Document>, LoadingError>>,
}

impl Resources {
    pub fn new() -> Resources {
        Resources {
            resources: Default::default(),
        }
    }

    pub fn lookup(
        &mut self,
        load_options: &LoadOptions,
        fragment: &Fragment,
    ) -> Result<RsvgNode, LoadingError> {
        if let Some(ref href) = fragment.uri() {
            self.get_extern_document(load_options, href)
                .and_then(|doc| {
                    doc.lookup_node_by_id(fragment.fragment())
                        .ok_or(LoadingError::BadUrl)
                })
        } else {
            unreachable!();
        }
    }

    fn get_extern_document(
        &mut self,
        load_options: &LoadOptions,
        href: &str,
    ) -> Result<Rc<Document>, LoadingError> {
        let aurl = AllowedUrl::from_href(href, load_options.base_url.as_ref())
            .map_err(|_| LoadingError::BadUrl)?;

        match self.resources.entry(aurl) {
            Entry::Occupied(e) => e.get().clone(),
            Entry::Vacant(e) => {
                let aurl = e.key();
                // FIXME: pass a cancellable to these
                let doc = io::acquire_stream(aurl, None)
                    .and_then(|stream| {
                        Document::load_from_stream(
                            &load_options.copy_with_base_url(aurl),
                            &stream,
                            None,
                        )
                    })
                    .map(Rc::new);
                let res = e.insert(doc);
                res.clone()
            }
        }
    }
}

struct Images {
    images: HashMap<AllowedUrl, Result<SharedImageSurface, LoadingError>>,
}

impl Images {
    fn new() -> Images {
        Images {
            images: Default::default(),
        }
    }

    fn lookup(
        &mut self,
        load_options: &LoadOptions,
        aurl: &AllowedUrl,
    ) -> Result<SharedImageSurface, LoadingError> {
        match self.images.entry(aurl.clone()) {
            Entry::Occupied(e) => e.get().clone(),
            Entry::Vacant(e) => {
                let surface = load_image(load_options, e.key());
                let res = e.insert(surface);
                res.clone()
            }
        }
    }
}

fn load_image(
    load_options: &LoadOptions,
    aurl: &AllowedUrl,
) -> Result<SharedImageSurface, LoadingError> {
    let BinaryData {
        data: bytes,
        content_type,
    } = io::acquire_data(&aurl, None)?;

    if bytes.is_empty() {
        return Err(LoadingError::EmptyData);
    }

    let loader = if let Some(ref content_type) = content_type {
        PixbufLoader::new_with_mime_type(content_type)?
    } else {
        PixbufLoader::new()
    };

    loader.write(&bytes)?;
    loader.close()?;

    let pixbuf = loader.get_pixbuf().ok_or(LoadingError::Unknown)?;

    let bytes = if load_options.keep_image_data {
        Some(bytes)
    } else {
        None
    };

    let surface =
        SharedImageSurface::from_pixbuf(&pixbuf, bytes, content_type.as_ref().map(String::as_str))?;

    Ok(surface)
}

pub struct DocumentBuilder {
    load_options: LoadOptions,
    tree: Option<RsvgNode>,
    ids: HashMap<String, RsvgNode>,
    stylesheets: Vec<Stylesheet>,
}

impl DocumentBuilder {
    pub fn new(load_options: &LoadOptions) -> DocumentBuilder {
        DocumentBuilder {
            load_options: load_options.clone(),
            tree: None,
            ids: HashMap::new(),
            stylesheets: Vec::new(),
        }
    }

    pub fn append_stylesheet_from_xml_processing_instruction(
        &mut self,
        alternate: Option<String>,
        type_: Option<String>,
        href: &str,
    ) -> Result<(), LoadingError> {
        if type_.as_ref().map(String::as_str) != Some("text/css")
            || (alternate.is_some() && alternate.as_ref().map(String::as_str) != Some("no"))
        {
            return Err(LoadingError::BadStylesheet);
        }

        // FIXME: handle CSS errors
        if let Ok(stylesheet) =
            Stylesheet::from_href(href, self.load_options.base_url.as_ref(), Origin::Author)
        {
            self.stylesheets.push(stylesheet);
        }

        Ok(())
    }

    pub fn append_element(
        &mut self,
        name: &QualName,
        pbag: &PropertyBag,
        parent: Option<RsvgNode>,
    ) -> RsvgNode {
        let mut node = create_node(name, pbag);

        if let Some(id) = node.borrow().get_id() {
            // This is so we don't overwrite an existing id
            self.ids
                .entry(id.to_string())
                .or_insert_with(|| node.clone());
        }

        node.borrow_mut()
            .set_atts(parent.as_ref().clone(), pbag, self.load_options.locale());

        if let Some(mut parent) = parent {
            parent.append(node.clone());
        } else if self.tree.is_none() {
            self.tree = Some(node.clone());
        } else {
            panic!("The tree root has already been set");
        }

        node
    }

    pub fn append_stylesheet_from_text(&mut self, text: &str) {
        // FIXME: handle CSS errors
        if let Ok(stylesheet) =
            Stylesheet::from_data(text, self.load_options.base_url.as_ref(), Origin::Author)
        {
            self.stylesheets.push(stylesheet);
        }
    }

    pub fn append_characters(&mut self, text: &str, parent: &mut RsvgNode) {
        if !text.is_empty() {
            self.append_chars_to_parent(text, parent);
        }
    }

    fn append_chars_to_parent(&mut self, text: &str, parent: &mut RsvgNode) {
        // When the last child is a Chars node we can coalesce
        // the text and avoid screwing up the Pango layouts
        let chars_node = if let Some(child) = parent
            .last_child()
            .filter(|c| c.borrow().get_type() == NodeType::Chars)
        {
            child
        } else {
            let child = RsvgNode::new(NodeData::new(
                NodeType::Chars,
                &QualName::new(
                    None,
                    Namespace::from("https://wiki.gnome.org/Projects/LibRsvg"),
                    LocalName::from("rsvg-chars"),
                ),
                None,
                None,
                Box::new(NodeChars::new()),
            ));

            parent.append(child.clone());

            child
        };

        chars_node.borrow().get_impl::<NodeChars>().append(text);
    }

    pub fn resolve_href(&self, href: &str) -> Result<AllowedUrl, AllowedUrlError> {
        AllowedUrl::from_href(href, self.load_options.base_url.as_ref())
    }

    pub fn build(self) -> Result<Document, LoadingError> {
        let DocumentBuilder {
            load_options,
            tree,
            ids,
            stylesheets,
            ..
        } = self;

        match tree {
            None => Err(LoadingError::SvgHasNoElements),
            Some(mut root) => {
                if root.borrow().get_type() == NodeType::Svg {
                    cascade(&mut root, &stylesheets);

                    Ok(Document {
                        tree: root.clone(),
                        ids,
                        externs: RefCell::new(Resources::new()),
                        images: RefCell::new(Images::new()),
                        load_options: load_options.clone(),
                    })
                } else {
                    Err(LoadingError::RootElementIsNotSvg)
                }
            }
        }
    }
}
<commit_msg>Docs for the Document struct<commit_after>use gdk_pixbuf::{PixbufLoader, PixbufLoaderExt};
use gio;
use markup5ever::{LocalName, Namespace, QualName};
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::rc::Rc;

use crate::allowed_url::{AllowedUrl, AllowedUrlError, Fragment};
use crate::create_node::create_node;
use crate::css::{cascade, Origin, Stylesheet};
use crate::error::LoadingError;
use crate::handle::LoadOptions;
use crate::io::{self, BinaryData};
use crate::node::{NodeData, NodeType, RsvgNode};
use crate::property_bag::PropertyBag;
use crate::structure::{IntrinsicDimensions, Svg};
use crate::surface_utils::shared_surface::SharedImageSurface;
use crate::text::NodeChars;
use crate::xml::xml_load_from_possibly_compressed_stream;

/// A loaded SVG file and its derived data.
pub struct Document {
    /// Tree of nodes; the root is guaranteed to be an `<svg>` element.
    tree: RsvgNode,

    /// Mapping from `id` attributes to nodes.
    ids: HashMap<String, RsvgNode>,

    // The following two require interior mutability because we load the extern
    // resources all over the place.  Eventually we'll be able to do this
    // once, at loading time, and keep this immutable.

    /// SVG documents referenced from this document.
    externs: RefCell<Resources>,

    /// Image resources referenced from this document.
    images: RefCell<Images>,

    /// Used to load referenced resources.
    load_options: LoadOptions,
}

impl Document {
    /// Constructs a `Document` by loading it from a stream.
    pub fn load_from_stream(
        load_options: &LoadOptions,
        stream: &gio::InputStream,
        cancellable: Option<&gio::Cancellable>,
    ) -> Result<Document, LoadingError> {
        xml_load_from_possibly_compressed_stream(
            DocumentBuilder::new(load_options),
            load_options.unlimited_size,
            stream,
            cancellable,
        )
    }

    /// Gets the root node.  This is guaranteed to be an `<svg>` element.
    pub fn root(&self) -> RsvgNode {
        self.tree.clone()
    }

    /// Looks up an element node by its URL.
    ///
    /// This is also used to find elements in referenced resources, as in
    /// `xlink:href="subresource.svg#element_name".
    pub fn lookup(&self, fragment: &Fragment) -> Result<RsvgNode, LoadingError> {
        if fragment.uri().is_some() {
            self.externs
                .borrow_mut()
                .lookup(&self.load_options, fragment)
        } else {
            self.lookup_node_by_id(fragment.fragment())
                .ok_or(LoadingError::BadUrl)
        }
    }

    /// Looks up a node only in this document fragment by its `id` attribute.
    pub fn lookup_node_by_id(&self, id: &str) -> Option<RsvgNode> {
        self.ids.get(id).map(|n| (*n).clone())
    }

    /// Loads an image by URL, or returns a pre-loaded one.
    pub fn lookup_image(&self, href: &str) -> Result<SharedImageSurface, LoadingError> {
        let aurl = AllowedUrl::from_href(href, self.load_options.base_url.as_ref())
            .map_err(|_| LoadingError::BadUrl)?;

        self.images.borrow_mut().lookup(&self.load_options, &aurl)
    }

    /// Gets the dimension parameters of the toplevel `<svg>`.
    pub fn get_intrinsic_dimensions(&self) -> IntrinsicDimensions {
        let root = self.root();
        let node_data = root.borrow();

        assert!(node_data.get_type() == NodeType::Svg);
        node_data.get_impl::<Svg>().get_intrinsic_dimensions()
    }
}

struct Resources {
    resources: HashMap<AllowedUrl, Result<Rc<Document>, LoadingError>>,
}

impl Resources {
    pub fn new() -> Resources {
        Resources {
            resources: Default::default(),
        }
    }

    pub fn lookup(
        &mut self,
        load_options: &LoadOptions,
        fragment: &Fragment,
    ) -> Result<RsvgNode, LoadingError> {
        if let Some(ref href) = fragment.uri() {
            self.get_extern_document(load_options, href)
                .and_then(|doc| {
                    doc.lookup_node_by_id(fragment.fragment())
                        .ok_or(LoadingError::BadUrl)
                })
        } else {
            unreachable!();
        }
    }

    fn get_extern_document(
        &mut self,
        load_options: &LoadOptions,
        href: &str,
    ) -> Result<Rc<Document>, LoadingError> {
        let aurl = AllowedUrl::from_href(href, load_options.base_url.as_ref())
            .map_err(|_| LoadingError::BadUrl)?;

        match self.resources.entry(aurl) {
            Entry::Occupied(e) => e.get().clone(),
            Entry::Vacant(e) => {
                let aurl = e.key();
                // FIXME: pass a cancellable to these
                let doc = io::acquire_stream(aurl, None)
                    .and_then(|stream| {
                        Document::load_from_stream(
                            &load_options.copy_with_base_url(aurl),
                            &stream,
                            None,
                        )
                    })
                    .map(Rc::new);
                let res = e.insert(doc);
                res.clone()
            }
        }
    }
}

struct Images {
    images: HashMap<AllowedUrl, Result<SharedImageSurface, LoadingError>>,
}

impl Images {
    fn new() -> Images {
        Images {
            images: Default::default(),
        }
    }

    fn lookup(
        &mut self,
        load_options: &LoadOptions,
        aurl: &AllowedUrl,
    ) -> Result<SharedImageSurface, LoadingError> {
        match self.images.entry(aurl.clone()) {
            Entry::Occupied(e) => e.get().clone(),
            Entry::Vacant(e) => {
                let surface = load_image(load_options, e.key());
                let res = e.insert(surface);
                res.clone()
            }
        }
    }
}

fn load_image(
    load_options: &LoadOptions,
    aurl: &AllowedUrl,
) -> Result<SharedImageSurface, LoadingError> {
    let BinaryData {
        data: bytes,
        content_type,
    } = io::acquire_data(&aurl, None)?;

    if bytes.is_empty() {
        return Err(LoadingError::EmptyData);
    }

    let loader = if let Some(ref content_type) = content_type {
        PixbufLoader::new_with_mime_type(content_type)?
    } else {
        PixbufLoader::new()
    };

    loader.write(&bytes)?;
    loader.close()?;

    let pixbuf = loader.get_pixbuf().ok_or(LoadingError::Unknown)?;

    let bytes = if load_options.keep_image_data {
        Some(bytes)
    } else {
        None
    };

    let surface =
        SharedImageSurface::from_pixbuf(&pixbuf, bytes, content_type.as_ref().map(String::as_str))?;

    Ok(surface)
}

pub struct DocumentBuilder {
    load_options: LoadOptions,
    tree: Option<RsvgNode>,
    ids: HashMap<String, RsvgNode>,
    stylesheets: Vec<Stylesheet>,
}

impl DocumentBuilder {
    pub fn new(load_options: &LoadOptions) -> DocumentBuilder {
        DocumentBuilder {
            load_options: load_options.clone(),
            tree: None,
            ids: HashMap::new(),
            stylesheets: Vec::new(),
        }
    }

    pub fn append_stylesheet_from_xml_processing_instruction(
        &mut self,
        alternate: Option<String>,
        type_: Option<String>,
        href: &str,
    ) -> Result<(), LoadingError> {
        if type_.as_ref().map(String::as_str) != Some("text/css")
            || (alternate.is_some() && alternate.as_ref().map(String::as_str) != Some("no"))
        {
            return Err(LoadingError::BadStylesheet);
        }

        // FIXME: handle CSS errors
        if let Ok(stylesheet) =
            Stylesheet::from_href(href, self.load_options.base_url.as_ref(), Origin::Author)
        {
            self.stylesheets.push(stylesheet);
        }

        Ok(())
    }

    pub fn append_element(
        &mut self,
        name: &QualName,
        pbag: &PropertyBag,
        parent: Option<RsvgNode>,
    ) -> RsvgNode {
        let mut node = create_node(name, pbag);

        if let Some(id) = node.borrow().get_id() {
            // This is so we don't overwrite an existing id
            self.ids
                .entry(id.to_string())
                .or_insert_with(|| node.clone());
        }

        node.borrow_mut()
            .set_atts(parent.as_ref().clone(), pbag, self.load_options.locale());

        if let Some(mut parent) = parent {
            parent.append(node.clone());
        } else if self.tree.is_none() {
            self.tree = Some(node.clone());
        } else {
            panic!("The tree root has already been set");
        }

        node
    }

    pub fn append_stylesheet_from_text(&mut self, text: &str) {
        // FIXME: handle CSS errors
        if let Ok(stylesheet) =
            Stylesheet::from_data(text, self.load_options.base_url.as_ref(), Origin::Author)
        {
            self.stylesheets.push(stylesheet);
        }
    }

    pub fn append_characters(&mut self, text: &str, parent: &mut RsvgNode) {
        if !text.is_empty() {
            self.append_chars_to_parent(text, parent);
        }
    }

    fn append_chars_to_parent(&mut self, text: &str, parent: &mut RsvgNode) {
        // When the last child is a Chars node we can coalesce
        // the text and avoid screwing up the Pango layouts
        let chars_node = if let Some(child) = parent
            .last_child()
            .filter(|c| c.borrow().get_type() == NodeType::Chars)
        {
            child
        } else {
            let child = RsvgNode::new(NodeData::new(
                NodeType::Chars,
                &QualName::new(
                    None,
                    Namespace::from("https://wiki.gnome.org/Projects/LibRsvg"),
                    LocalName::from("rsvg-chars"),
                ),
                None,
                None,
                Box::new(NodeChars::new()),
            ));

            parent.append(child.clone());

            child
        };

        chars_node.borrow().get_impl::<NodeChars>().append(text);
    }

    pub fn resolve_href(&self, href: &str) -> Result<AllowedUrl, AllowedUrlError> {
        AllowedUrl::from_href(href, self.load_options.base_url.as_ref())
    }

    pub fn build(self) -> Result<Document, LoadingError> {
        let DocumentBuilder {
            load_options,
            tree,
            ids,
            stylesheets,
            ..
        } = self;

        match tree {
            None => Err(LoadingError::SvgHasNoElements),
            Some(mut root) => {
                if root.borrow().get_type() == NodeType::Svg {
                    cascade(&mut root, &stylesheets);

                    Ok(Document {
                        tree: root.clone(),
                        ids,
                        externs: RefCell::new(Resources::new()),
                        images: RefCell::new(Images::new()),
                        load_options: load_options.clone(),
                    })
                } else {
                    Err(LoadingError::RootElementIsNotSvg)
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate inkwell;

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

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

    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_ip_constant_propagation_pass();
    pass_manager.add_prune_eh_pass();
    pass_manager.add_ipsccp_pass();
    pass_manager.add_interinalize_pass(1);
    pass_manager.add_strip_dead_prototypes_pass();
    pass_manager.add_strip_symbol_pass();
    pass_manager.add_bb_vectorize_pass();
    pass_manager.add_loop_vectorize_pass();
    pass_manager.add_slp_vectorize_pass();
    pass_manager.add_aggressive_dce_pass();
    pass_manager.add_bit_tracking_dce_pass(); // TODO: 3.7+ only
    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_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();

    assert!(!pass_manager.initialize());
    assert!(!pass_manager.finalize());

    pass_manager.run_on_module(&module);

    assert!(!pass_manager.initialize());
    assert!(!pass_manager.finalize());

    // TODO: Test when initialize and finalize are true
}

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

    builder.set_optimization_level(Some(&Aggressive));
    builder.set_size_level(2);
    builder.set_inliner_with_threshold(42);
    builder.set_disable_unit_at_a_time(true);
    builder.set_disable_unroll_loops(true);
    builder.set_disable_simplify_lib_calls(true);

    // TODO: Run on various type of pass managers
}

#[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();
}
<commit_msg>Fleshed out more of the pass manager builder test<commit_after>extern crate inkwell;

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

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

    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_ip_constant_propagation_pass();
    pass_manager.add_prune_eh_pass();
    pass_manager.add_ipsccp_pass();
    pass_manager.add_interinalize_pass(1);
    pass_manager.add_strip_dead_prototypes_pass();
    pass_manager.add_strip_symbol_pass();
    pass_manager.add_bb_vectorize_pass();
    pass_manager.add_loop_vectorize_pass();
    pass_manager.add_slp_vectorize_pass();
    pass_manager.add_aggressive_dce_pass();
    pass_manager.add_bit_tracking_dce_pass(); // TODO: 3.7+ only
    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_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();

    assert!(!pass_manager.initialize());
    assert!(!pass_manager.finalize());

    pass_manager.run_on_module(&module);

    assert!(!pass_manager.initialize());
    assert!(!pass_manager.finalize());

    // TODO: Test when initialize and finalize are true
}

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

    pass_manager_builder.set_optimization_level(Some(&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_for_function(&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);

    // TODO: Test with actual changes? Would be true in that case
    assert!(!fn_pass_manager.run_on_function(&fn_value));

    let module_pass_manager = PassManager::create_for_module();

    pass_manager_builder.populate_module_pass_manager(&module_pass_manager);

    // REVIEW: Seems like no changes were made, why does it return true?
    assert!(module_pass_manager.run_on_module(&module));

    // TODO: Populate LTO pass manager?
}

#[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();
}
<|endoftext|>


<commit_before>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line");

    let guess: u32 = guess.trim().parse()
        .expect("Please type a number!");

    println!("You guessed: {}", guess);

    match guess.cmp(&secret_number) {
        Ordering::Less    => println!("Too small!"),
        Ordering::Greater => println!("Too big!"),
        Ordering::Equal   => println!("You win!"),
    }
}
<commit_msg>Basic loop<commit_after>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    loop
    {
        println!("Please input your guess.");

	let mut guess = String::new();

	io::stdin().read_line(&mut guess)
            .expect("Failed to read line");

	let guess: u32 = guess.trim().parse()
            .expect("Please type a number!");

	println!("You guessed: {}", guess);

	match guess.cmp(&secret_number) {
              Ordering::Less    => println!("Too small!"),
	      Ordering::Greater => println!("Too big!"),
	      Ordering::Equal   => println!("You win!"),
        }
    }
}
<|endoftext|>