<commit_before>use super::super::general::write_vec;
use std::io::{Result, Write};

pub fn begin(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]",
        "#![allow(clippy::approx_constant, clippy::type_complexity, clippy::unreadable_literal)]",
        "#![cfg_attr(feature = \"dox\", feature(doc_cfg))]",
        "",
    ];

    write_vec(w, &v)
}

pub fn after_extern_crates(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "#[allow(unused_imports)]",
        "use libc::{c_int, c_char, c_uchar, c_float, c_uint, c_double,",
        "    c_short, c_ushort, c_long, c_ulong,",
        "    c_void, size_t, ssize_t, intptr_t, uintptr_t, time_t, FILE};",
    ];

    write_vec(w, &v)
}

pub fn use_glib(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "#[allow(unused_imports)]",
        "use glib::{gboolean, gconstpointer, gpointer, GType};",
    ];

    write_vec(w, &v)
}

pub fn only_for_glib(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "pub type gboolean = c_int;",
        "pub const GFALSE:  c_int = 0;",
        "pub const GTRUE:   c_int = 1;",
        "",
        "pub type gconstpointer = *const c_void;",
        "pub type gpointer = *mut c_void;",
        "",
    ];

    write_vec(w, &v)
}

pub fn only_for_gobject(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "pub const G_TYPE_INVALID: GType = 0 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_NONE: GType = 1 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_INTERFACE: GType = 2 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_CHAR: GType = 3 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_UCHAR: GType = 4 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_BOOLEAN: GType = 5 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_INT: GType = 6 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_UINT: GType = 7 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_LONG: GType = 8 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_ULONG: GType = 9 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_INT64: GType = 10 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_UINT64: GType = 11 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_ENUM: GType = 12 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_FLAGS: GType = 13 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_FLOAT: GType = 14 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_DOUBLE: GType = 15 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_STRING: GType = 16 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_POINTER: GType = 17 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_BOXED: GType = 18 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_PARAM: GType = 19 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_OBJECT: GType = 20 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_VARIANT: GType = 21 << G_TYPE_FUNDAMENTAL_SHIFT;",
    ];

    write_vec(w, &v)
}

pub fn only_for_gtk(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "pub const GTK_ENTRY_BUFFER_MAX_SIZE: u16 = ::std::u16::MAX;",
    ];

    write_vec(w, &v)
}
<commit_msg>sys mode: allow clippy warning upper_case_acronyms<commit_after>use super::super::general::write_vec;
use std::io::{Result, Write};

pub fn begin(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]",
        "#![allow(clippy::approx_constant, clippy::type_complexity, clippy::unreadable_literal, clippy::upper_case_acronyms)]",
        "#![cfg_attr(feature = \"dox\", feature(doc_cfg))]",
        "",
    ];

    write_vec(w, &v)
}

pub fn after_extern_crates(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "#[allow(unused_imports)]",
        "use libc::{c_int, c_char, c_uchar, c_float, c_uint, c_double,",
        "    c_short, c_ushort, c_long, c_ulong,",
        "    c_void, size_t, ssize_t, intptr_t, uintptr_t, time_t, FILE};",
    ];

    write_vec(w, &v)
}

pub fn use_glib(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "#[allow(unused_imports)]",
        "use glib::{gboolean, gconstpointer, gpointer, GType};",
    ];

    write_vec(w, &v)
}

pub fn only_for_glib(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "pub type gboolean = c_int;",
        "pub const GFALSE:  c_int = 0;",
        "pub const GTRUE:   c_int = 1;",
        "",
        "pub type gconstpointer = *const c_void;",
        "pub type gpointer = *mut c_void;",
        "",
    ];

    write_vec(w, &v)
}

pub fn only_for_gobject(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "pub const G_TYPE_INVALID: GType = 0 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_NONE: GType = 1 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_INTERFACE: GType = 2 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_CHAR: GType = 3 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_UCHAR: GType = 4 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_BOOLEAN: GType = 5 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_INT: GType = 6 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_UINT: GType = 7 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_LONG: GType = 8 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_ULONG: GType = 9 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_INT64: GType = 10 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_UINT64: GType = 11 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_ENUM: GType = 12 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_FLAGS: GType = 13 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_FLOAT: GType = 14 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_DOUBLE: GType = 15 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_STRING: GType = 16 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_POINTER: GType = 17 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_BOXED: GType = 18 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_PARAM: GType = 19 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_OBJECT: GType = 20 << G_TYPE_FUNDAMENTAL_SHIFT;",
        "pub const G_TYPE_VARIANT: GType = 21 << G_TYPE_FUNDAMENTAL_SHIFT;",
    ];

    write_vec(w, &v)
}

pub fn only_for_gtk(w: &mut dyn Write) -> Result<()> {
    let v = vec![
        "",
        "pub const GTK_ENTRY_BUFFER_MAX_SIZE: u16 = ::std::u16::MAX;",
    ];

    write_vec(w, &v)
}
<|endoftext|>


<commit_before>use specs::{AMQPArgument, AMQPFlagArgument};
use util::*;

use handlebars::{self, Handlebars, Helper, Renderable, RenderContext, RenderError, to_json};
use serde_json::{self};

use std::collections::BTreeMap;

pub type CodeGenerator = Handlebars;

pub trait HandlebarsAMQPExtension {
    fn register_amqp_helpers(self) -> Self;
}

impl HandlebarsAMQPExtension for CodeGenerator {
    fn register_amqp_helpers(mut self) -> CodeGenerator {
        self.register_escape_fn(handlebars::no_escape);
        self.register_helper("camel",         Box::new(camel_helper));
        self.register_helper("snake",         Box::new(snake_helper));
        self.register_helper("each_argument", Box::new(each_argument_helper));
        self.register_helper("each_flag",     Box::new(each_flag_helper));
        self
    }
}

pub fn camel_helper (h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let value = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"camel\""))?;
    let param = value.value().as_str().ok_or_else(|| RenderError::new("Non-string param given to helper \"camel\""))?;
    rc.writer.write(camel_case(param).as_bytes())?;
    Ok(())
}

pub fn snake_helper (h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let value = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"snake\""))?;
    let param = value.value().as_str().ok_or_else(|| RenderError::new("Non-string param given to helper \"snake\""))?;
    rc.writer.write(snake_case(param).as_bytes())?;
    Ok(())
}

pub fn each_argument_helper (h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let value = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"each_argument\""))?;

    if let Some(t) = h.template() {
        rc.promote_local_vars();
        let local_path_root = value.path_root().map(|p| format!("{}/{}", rc.get_path(), p));
        let arguments : Vec<AMQPArgument> = serde_json::from_value(value.value().clone()).map_err(|_| RenderError::new("Param is not a Vec<AMQPArgument> for helper \"each_argument\""))?;
        for (index, argument) in arguments.iter().enumerate() {
            let mut local_rc = rc.derive();
            if let Some(ref p) = local_path_root {
                local_rc.push_local_path_root(p.clone());
            }
            local_rc.set_local_var("@index".to_string(), to_json(&index));
            if let Some(inner_path) = value.path() {
                let new_path = format!("{}/{}.[{}]", local_rc.get_path(), inner_path, index);
                local_rc.set_path(new_path.clone());
            }
            if let Some(block_param) = h.block_param() {
                let mut map = BTreeMap::new();
                match *argument {
                    AMQPArgument::Value(ref v) => {
                        map.insert(block_param.to_string(), to_json(v));
                        map.insert("argument_is_value".to_string(), to_json(&true));
                    },
                    AMQPArgument::Flags(ref f) => {
                        map.insert(block_param.to_string(), to_json(f));
                        map.insert("argument_is_value".to_string(), to_json(&false));
                    },
                };
                local_rc.push_block_context(&map);
            }
            t.render(r, &mut local_rc)?;
            if h.block_param().is_some() {
                local_rc.pop_block_context();
            }
            if local_path_root.is_some() {
                local_rc.pop_local_path_root();
            }
        }
        rc.demote_local_vars();
    }
    Ok(())
}

pub fn each_flag_helper (h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let value = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"each_flag\""))?;

    if let Some(t) = h.template() {
        rc.promote_local_vars();
        let local_path_root = value.path_root().map(|p| format!("{}/{}", rc.get_path(), p));
        let flags : Vec<AMQPFlagArgument> = serde_json::from_value(value.value().clone()).map_err(|_| RenderError::new("Param is not a Vec<AMQPFlagArgument> for helper \"each_flag\""))?;
        for (index, flag) in flags.iter().enumerate() {
            let mut local_rc = rc.derive();
            if let Some(ref p) = local_path_root {
                local_rc.push_local_path_root(p.clone());
            }
            local_rc.set_local_var("@index".to_string(), to_json(&index));
            if let Some(inner_path) = value.path() {
                let new_path = format!("{}/{}.[{}]", local_rc.get_path(), inner_path, index);
                local_rc.set_path(new_path.clone());
            }
            if let Some(block_param) = h.block_param() {
                let mut map = BTreeMap::new();
                map.insert(block_param.to_string(), to_json(flag));
                local_rc.push_block_context(&map);
            }
            t.render(r, &mut local_rc)?;
            if h.block_param().is_some() {
                local_rc.pop_block_context();
            }
            if local_path_root.is_some() {
                local_rc.pop_local_path_root();
            }
        }
        rc.demote_local_vars();
    }
    Ok(())
}

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

    use specs::*;

    use amq_protocol_types::*;

    use std::collections::BTreeMap;

    pub const TEMPLATE: &'static str = r#"
{{protocol.name}} - {{protocol.major_version}}.{{protocol.minor_version}}.{{protocol.revision}}
{{protocol.copyright}}
port {{protocol.port}}
{{#each protocol.domains ~}}
{{@key}}: {{this}}
{{/each ~}}
{{#each protocol.constants as |constant| ~}}
{{constant.name}}({{constant.class}}) = {{constant.value}}
{{/each ~}}
{{#each protocol.classes as |class| ~}}
{{class.id}} - {{class.name}}
{{#each class.properties as |property| ~}}
{{property.name}}: {{property.type}}
{{/each ~}}
{{#each class.methods as |method| ~}}
{{method.id}} - {{method.name}}
synchronous: {{method.synchronous}}
{{#each_argument method.arguments as |argument| ~}}
{{#if argument_is_value ~}}
{{argument.name}}({{argument.domain}}): {{argument.type}}
{{else}}
{{#each_flag argument as |flag| ~}}
{{flag.name}}: {{flag.default_value}}
{{/each_flag ~}}
{{/if ~}}
{{/each_argument ~}}
{{/each ~}}
{{/each ~}}
"#;

    fn specs() -> AMQProtocolDefinition {
        let mut domains = BTreeMap::new();
        domains.insert("domain1".to_string(), AMQPType::LongString);
        AMQProtocolDefinition {
            name:          "AMQP".to_string(),
            major_version: 0,
            minor_version: 9,
            revision:      1,
            port:          5672,
            copyright:     "Copyright 1\nCopyright 2".to_string(),
            domains:       domains,
            constants:     vec![
                AMQPConstant {
                    name:  "constant1".to_string(),
                    value: 128,
                    klass: Some("class1".to_string()),
                }
            ],
            classes:       vec![
                AMQPClass {
                    id:            42,
                    methods:       vec![
                        AMQPMethod {
                            id:          64,
                            arguments:   vec![
                                AMQPArgument::Value(AMQPValueArgument {
                                    amqp_type:     AMQPType::LongString,
                                    name:          "argument1".to_string(),
                                    default_value: Some(AMQPValue::LongString("value1".to_string())),
                                    domain:        Some("domain1".to_string()),
                                }),
                                AMQPArgument::Flags(vec![
                                    AMQPFlagArgument {
                                        name:         "flag1".to_string(),
                                        default_value: true,
                                    },
                                    AMQPFlagArgument {
                                        name:         "flag2".to_string(),
                                        default_value: false,
                                    },
                                ]),
                            ],
                            has_flags:   true,
                            name:        "method1".to_string(),
                            synchronous: true,
                        }
                    ],
                    name:          "class1".to_string(),
                    properties:    vec![
                        AMQPProperty {
                            amqp_type: AMQPType::LongString,
                            name:      "property1".to_string(),
                        }
                    ],
                    is_connection: false,
                }
            ],
        }
    }

    #[test]
    fn main_template() {
        let mut data    = BTreeMap::new();
        let mut codegen = CodeGenerator::new().register_amqp_helpers();
        data.insert("protocol".to_string(), specs());
        codegen.register_template_string("main", TEMPLATE.to_string()).unwrap();
        assert_eq!(codegen.render("main", &data).unwrap(), r#"
AMQP - 0.9.1
Copyright 1
Copyright 2
port 5672
domain1: LongString
constant1(class1) = 128
42 - class1
property1: LongString
64 - method1
synchronous: true
argument1(domain1): LongString

flag1: true
flag2: false

"#);
    }
}
<commit_msg>codegen: add snake_type helper<commit_after>use specs::{AMQPArgument, AMQPFlagArgument};
use util::*;

use amq_protocol_types::AMQPType;
use handlebars::{self, Handlebars, Helper, Renderable, RenderContext, RenderError, to_json};
use serde_json::{self};

use std::collections::BTreeMap;

pub type CodeGenerator = Handlebars;

pub trait HandlebarsAMQPExtension {
    fn register_amqp_helpers(self) -> Self;
}

impl HandlebarsAMQPExtension for CodeGenerator {
    fn register_amqp_helpers(mut self) -> CodeGenerator {
        self.register_escape_fn(handlebars::no_escape);
        self.register_helper("camel",         Box::new(camel_helper));
        self.register_helper("snake",         Box::new(snake_helper));
        self.register_helper("snake_type",    Box::new(snake_type_helper));
        self.register_helper("each_argument", Box::new(each_argument_helper));
        self.register_helper("each_flag",     Box::new(each_flag_helper));
        self
    }
}

pub fn camel_helper (h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let value = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"camel\""))?;
    let param = value.value().as_str().ok_or_else(|| RenderError::new("Non-string param given to helper \"camel\""))?;
    rc.writer.write(camel_case(param).as_bytes())?;
    Ok(())
}

pub fn snake_helper (h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let value = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"snake\""))?;
    let param = value.value().as_str().ok_or_else(|| RenderError::new("Non-string param given to helper \"snake\""))?;
    rc.writer.write(snake_case(param).as_bytes())?;
    Ok(())
}

pub fn snake_type_helper (h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let value           = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"snake\""))?;
    let param: AMQPType = serde_json::from_value(value.value().clone()).map_err(|_| RenderError::new("Param is not an AMQPType for helper \"snake_type\""))?;
    rc.writer.write(snake_case(&param.to_string()).as_bytes())?;
    Ok(())
}

pub fn each_argument_helper (h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let value = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"each_argument\""))?;

    if let Some(t) = h.template() {
        rc.promote_local_vars();
        let local_path_root = value.path_root().map(|p| format!("{}/{}", rc.get_path(), p));
        let arguments : Vec<AMQPArgument> = serde_json::from_value(value.value().clone()).map_err(|_| RenderError::new("Param is not a Vec<AMQPArgument> for helper \"each_argument\""))?;
        for (index, argument) in arguments.iter().enumerate() {
            let mut local_rc = rc.derive();
            if let Some(ref p) = local_path_root {
                local_rc.push_local_path_root(p.clone());
            }
            local_rc.set_local_var("@index".to_string(), to_json(&index));
            if let Some(inner_path) = value.path() {
                let new_path = format!("{}/{}.[{}]", local_rc.get_path(), inner_path, index);
                local_rc.set_path(new_path.clone());
            }
            if let Some(block_param) = h.block_param() {
                let mut map = BTreeMap::new();
                match *argument {
                    AMQPArgument::Value(ref v) => {
                        map.insert(block_param.to_string(), to_json(v));
                        map.insert("argument_is_value".to_string(), to_json(&true));
                    },
                    AMQPArgument::Flags(ref f) => {
                        map.insert(block_param.to_string(), to_json(f));
                        map.insert("argument_is_value".to_string(), to_json(&false));
                    },
                };
                local_rc.push_block_context(&map);
            }
            t.render(r, &mut local_rc)?;
            if h.block_param().is_some() {
                local_rc.pop_block_context();
            }
            if local_path_root.is_some() {
                local_rc.pop_local_path_root();
            }
        }
        rc.demote_local_vars();
    }
    Ok(())
}

pub fn each_flag_helper (h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
    let value = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"each_flag\""))?;

    if let Some(t) = h.template() {
        rc.promote_local_vars();
        let local_path_root = value.path_root().map(|p| format!("{}/{}", rc.get_path(), p));
        let flags : Vec<AMQPFlagArgument> = serde_json::from_value(value.value().clone()).map_err(|_| RenderError::new("Param is not a Vec<AMQPFlagArgument> for helper \"each_flag\""))?;
        for (index, flag) in flags.iter().enumerate() {
            let mut local_rc = rc.derive();
            if let Some(ref p) = local_path_root {
                local_rc.push_local_path_root(p.clone());
            }
            local_rc.set_local_var("@index".to_string(), to_json(&index));
            if let Some(inner_path) = value.path() {
                let new_path = format!("{}/{}.[{}]", local_rc.get_path(), inner_path, index);
                local_rc.set_path(new_path.clone());
            }
            if let Some(block_param) = h.block_param() {
                let mut map = BTreeMap::new();
                map.insert(block_param.to_string(), to_json(flag));
                local_rc.push_block_context(&map);
            }
            t.render(r, &mut local_rc)?;
            if h.block_param().is_some() {
                local_rc.pop_block_context();
            }
            if local_path_root.is_some() {
                local_rc.pop_local_path_root();
            }
        }
        rc.demote_local_vars();
    }
    Ok(())
}

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

    use specs::*;

    use amq_protocol_types::*;

    use std::collections::BTreeMap;

    pub const TEMPLATE: &'static str = r#"
{{protocol.name}} - {{protocol.major_version}}.{{protocol.minor_version}}.{{protocol.revision}}
{{protocol.copyright}}
port {{protocol.port}}
{{#each protocol.domains ~}}
{{@key}}: {{this}}
{{/each ~}}
{{#each protocol.constants as |constant| ~}}
{{constant.name}}({{constant.class}}) = {{constant.value}}
{{/each ~}}
{{#each protocol.classes as |class| ~}}
{{class.id}} - {{class.name}}
{{#each class.properties as |property| ~}}
{{property.name}}: {{property.type}}
{{/each ~}}
{{#each class.methods as |method| ~}}
{{method.id}} - {{method.name}}
synchronous: {{method.synchronous}}
{{#each_argument method.arguments as |argument| ~}}
{{#if argument_is_value ~}}
{{argument.name}}({{argument.domain}}): {{argument.type}}
{{else}}
{{#each_flag argument as |flag| ~}}
{{flag.name}}: {{flag.default_value}}
{{/each_flag ~}}
{{/if ~}}
{{/each_argument ~}}
{{/each ~}}
{{/each ~}}
"#;

    fn specs() -> AMQProtocolDefinition {
        let mut domains = BTreeMap::new();
        domains.insert("domain1".to_string(), AMQPType::LongString);
        AMQProtocolDefinition {
            name:          "AMQP".to_string(),
            major_version: 0,
            minor_version: 9,
            revision:      1,
            port:          5672,
            copyright:     "Copyright 1\nCopyright 2".to_string(),
            domains:       domains,
            constants:     vec![
                AMQPConstant {
                    name:  "constant1".to_string(),
                    value: 128,
                    klass: Some("class1".to_string()),
                }
            ],
            classes:       vec![
                AMQPClass {
                    id:            42,
                    methods:       vec![
                        AMQPMethod {
                            id:          64,
                            arguments:   vec![
                                AMQPArgument::Value(AMQPValueArgument {
                                    amqp_type:     AMQPType::LongString,
                                    name:          "argument1".to_string(),
                                    default_value: Some(AMQPValue::LongString("value1".to_string())),
                                    domain:        Some("domain1".to_string()),
                                }),
                                AMQPArgument::Flags(vec![
                                    AMQPFlagArgument {
                                        name:         "flag1".to_string(),
                                        default_value: true,
                                    },
                                    AMQPFlagArgument {
                                        name:         "flag2".to_string(),
                                        default_value: false,
                                    },
                                ]),
                            ],
                            has_flags:   true,
                            name:        "method1".to_string(),
                            synchronous: true,
                        }
                    ],
                    name:          "class1".to_string(),
                    properties:    vec![
                        AMQPProperty {
                            amqp_type: AMQPType::LongString,
                            name:      "property1".to_string(),
                        }
                    ],
                    is_connection: false,
                }
            ],
        }
    }

    #[test]
    fn main_template() {
        let mut data    = BTreeMap::new();
        let mut codegen = CodeGenerator::new().register_amqp_helpers();
        data.insert("protocol".to_string(), specs());
        codegen.register_template_string("main", TEMPLATE.to_string()).unwrap();
        assert_eq!(codegen.render("main", &data).unwrap(), r#"
AMQP - 0.9.1
Copyright 1
Copyright 2
port 5672
domain1: LongString
constant1(class1) = 128
42 - class1
property1: LongString
64 - method1
synchronous: true
argument1(domain1): LongString

flag1: true
flag2: false

"#);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate criterion;
extern crate fitsio;

use criterion::Criterion;

fn criterion_benchmark(c: &mut Criterion) {
    c.bench_function("opening and closing files", |b| b.iter(|| {
        let filename = "../testdata/full_example.fits";
        {
            let f = fitsio::FitsFile::open(filename).unwrap();
            /* Implicit drop */
        }
    }));
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<commit_msg>Streamline benchmark<commit_after>#[macro_use]
extern crate criterion;
extern crate fitsio;

use criterion::Criterion;

fn criterion_benchmark(c: &mut Criterion) {
    let filename = "../testdata/full_example.fits";
    c.bench_function("opening and closing files", move |b| b.iter(|| {
        {
            let _f = fitsio::FitsFile::open(filename).unwrap();
            /* Implicit drop */
        }
    }));
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate gfx;
extern crate gfx_traits;
extern crate ipc_channel;
#[macro_use]
extern crate log;
extern crate malloc_size_of;
#[macro_use]
extern crate malloc_size_of_derive;
extern crate msg;
extern crate profile_traits;
extern crate script_traits;
extern crate servo_config;
extern crate time;

use gfx::display_list::{DisplayItem, DisplayList};
use gfx_traits::Epoch;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::PipelineId;
use profile_traits::time::{ProfilerChan, ProfilerCategory, send_profile_data};
use profile_traits::time::TimerMetadata;
use script_traits::{ConstellationControlMsg, LayoutMsg, ProgressiveWebMetricType};
use servo_config::opts;
use std::cell::{Cell, RefCell};
use std::cmp::Ordering;
use std::collections::HashMap;
use time::precise_time_ns;

pub trait ProfilerMetadataFactory {
    fn new_metadata(&self) -> Option<TimerMetadata>;
}

pub trait ProgressiveWebMetric {
    fn get_navigation_start(&self) -> Option<f64>;
    fn set_navigation_start(&mut self, time: f64);
    fn get_time_profiler_chan(&self) -> &ProfilerChan;
    fn send_queued_constellation_msg(&self, name: ProgressiveWebMetricType, time: f64);
}

/// maximum task time is 50ms (in ns)
pub const MAX_TASK_NS: u64 = 50000000;
/// 10 second window (in ns)
const INTERACTIVE_WINDOW_SECONDS_IN_NS: u64 = 10000000000;

fn set_metric<U: ProgressiveWebMetric>(
    pwm: &U,
    metadata: Option<TimerMetadata>,
    metric_type: ProgressiveWebMetricType,
    category: ProfilerCategory,
    attr: &Cell<Option<f64>>,
    metric_time: Option<f64>)
{
    let navigation_start = match pwm.get_navigation_start() {
        Some(time) => time,
        None => {
            warn!("Trying to set metric before navigation start");
            return;
        }
    };
    let now = match metric_time {
        Some(time) => time,
        None => precise_time_ns() as f64,
    };
    let time = now - navigation_start;
    attr.set(Some(time));

    // Queue performance observer notification.
    pwm.send_queued_constellation_msg(metric_type, time);

    // Send the metric to the time profiler.
    send_profile_data(
        category,
        metadata,
        &pwm.get_time_profiler_chan(),
        time as u64,
        time as u64,
        0,
        0,
    );

    // Print the metric to console if the print-pwm option was given.
    if opts::get().print_pwm {
        println!("{:?} {:?}", metric_type, time);
    }

}

// https://github.com/GoogleChrome/lighthouse/issues/27
// we can look at three different metrics here:
// navigation start -> visually ready (dom content loaded)
// navigation start -> thread ready (main thread available)
// visually ready -> thread ready
#[derive(MallocSizeOf)]
pub struct InteractiveMetrics {
    /// when we navigated to the page
    navigation_start: Option<f64>,
    /// indicates if the page is visually ready
    dom_content_loaded: Cell<Option<f64>>,
    /// main thread is available -- there's been a 10s window with no tasks longer than 50ms
    main_thread_available: Cell<Option<f64>>,
    // max(main_thread_available, dom_content_loaded)
    time_to_interactive: Cell<Option<f64>>,
    #[ignore_malloc_size_of = "can't measure channels"]
    time_profiler_chan: ProfilerChan,
}

#[derive(Clone, Copy, Debug, MallocSizeOf)]
pub struct InteractiveWindow {
    start: u64,
}

impl InteractiveWindow {
    pub fn new() -> InteractiveWindow {
        InteractiveWindow {
            start: precise_time_ns(),
        }
    }

    // We need to either start or restart the 10s window
    //   start: we've added a new document
    //   restart: there was a task > 50ms
    //   not all documents are interactive
    pub fn start_window(&mut self) {
        self.start = precise_time_ns();
    }

    /// check if 10s has elapsed since start
    pub fn needs_check(&self) -> bool {
        precise_time_ns() - self.start >= INTERACTIVE_WINDOW_SECONDS_IN_NS
    }

    pub fn get_start(&self) -> u64 {
        self.start
    }
}

#[derive(Debug)]
pub enum InteractiveFlag {
    DOMContentLoaded,
    TimeToInteractive(f64),
}

impl InteractiveMetrics {
    pub fn new(time_profiler_chan: ProfilerChan) -> InteractiveMetrics {
        InteractiveMetrics {
            navigation_start: None,
            dom_content_loaded: Cell::new(None),
            main_thread_available: Cell::new(None),
            time_to_interactive: Cell::new(None),
            time_profiler_chan: time_profiler_chan,
        }
    }

    pub fn set_dom_content_loaded(&self) {
        if self.dom_content_loaded.get().is_none() {
            self.dom_content_loaded.set(Some(precise_time_ns() as f64));
        }
    }

    pub fn set_main_thread_available(&self, time: f64) {
        if self.main_thread_available.get().is_none() {
            self.main_thread_available.set(Some(time));
        }
    }

    pub fn get_dom_content_loaded(&self) -> Option<f64> {
        self.dom_content_loaded.get()
    }

    pub fn get_main_thread_available(&self) -> Option<f64> {
        self.main_thread_available.get()
    }

    // can set either dlc or tti first, but both must be set to actually calc metric
    // when the second is set, set_tti is called with appropriate time
    pub fn maybe_set_tti<T>(
        &self,
        profiler_metadata_factory: &T,
        metric: InteractiveFlag,
    ) where
        T: ProfilerMetadataFactory,
    {
        if self.get_tti().is_some() {
            return;
        }
        match metric {
            InteractiveFlag::DOMContentLoaded => self.set_dom_content_loaded(),
            InteractiveFlag::TimeToInteractive(time) => self.set_main_thread_available(time),
        }

        let dcl = self.dom_content_loaded.get();
        let mta = self.main_thread_available.get();
        let (dcl, mta) = match (dcl, mta) {
        (Some(dcl), Some(mta)) => (dcl, mta),
            _ => return,
        };
        let metric_time = match dcl.partial_cmp(&mta) {
            Some(Ordering::Less) => mta,
            Some(_) => dcl,
            None => panic!("no ordering possible. something bad happened"),
        };
        set_metric(
            self,
            profiler_metadata_factory.new_metadata(),
            ProgressiveWebMetricType::TimeToInteractive,
            ProfilerCategory::TimeToInteractive,
            &self.time_to_interactive,
            Some(metric_time));
    }

    pub fn get_tti(&self) -> Option<f64> {
        self.time_to_interactive.get()
    }
}

impl ProgressiveWebMetric for InteractiveMetrics {
    fn get_navigation_start(&self) -> Option<f64> {
        self.navigation_start
    }

    fn set_navigation_start(&mut self, time: f64) {
        self.navigation_start = Some(time);
    }

    fn send_queued_constellation_msg(&self, name: ProgressiveWebMetricType, time: f64) { }

    fn get_time_profiler_chan(&self) -> &ProfilerChan {
        &self.time_profiler_chan
    }
}

pub struct PaintTimeMetrics {
    pending_metrics: RefCell<HashMap<Epoch, (Option<TimerMetadata>, bool)>>,
    navigation_start: Option<f64>,
    first_paint: Cell<Option<f64>>,
    first_contentful_paint: Cell<Option<f64>>,
    pipeline_id: PipelineId,
    time_profiler_chan: ProfilerChan,
    constellation_chan: IpcSender<LayoutMsg>,
    script_chan: IpcSender<ConstellationControlMsg>,
}

impl PaintTimeMetrics {
    pub fn new(
        pipeline_id: PipelineId,
        time_profiler_chan: ProfilerChan,
        constellation_chan: IpcSender<LayoutMsg>,
        script_chan: IpcSender<ConstellationControlMsg>)
            -> PaintTimeMetrics {
        PaintTimeMetrics {
            pending_metrics: RefCell::new(HashMap::new()),
            navigation_start: None,
            first_paint: Cell::new(None),
            first_contentful_paint: Cell::new(None),
            pipeline_id,
            time_profiler_chan,
            constellation_chan,
            script_chan,
        }
    }

    pub fn maybe_set_first_paint<T>(&self, profiler_metadata_factory: &T)
    where
        T: ProfilerMetadataFactory,
    {
        if self.first_paint.get().is_some() {
            return;
        }

        set_metric(
            self,
            profiler_metadata_factory.new_metadata(),
            ProgressiveWebMetricType::FirstPaint,
            ProfilerCategory::TimeToFirstPaint,
            &self.first_paint,
            None,
        );
    }

    pub fn maybe_observe_paint_time<T>(
        &self,
        profiler_metadata_factory: &T,
        epoch: Epoch,
        display_list: &DisplayList)
    where T: ProfilerMetadataFactory {
        if self.first_paint.get().is_some() && self.first_contentful_paint.get().is_some() {
            // If we already set all paint metrics, we just bail out.
            return;
        }

        let mut is_contentful = false;
        // Analyze the display list to figure out if this may be the first
        // contentful paint (i.e. the display list contains items of type text,
        // image, non-white canvas or SVG).
        for item in &display_list.list {
            match item {
                &DisplayItem::Text(_) |
                &DisplayItem::Image(_) => {
                    is_contentful = true;
                    break;
                }
                _ => (),
            }
        }

        self.pending_metrics.borrow_mut().insert(epoch, (
            profiler_metadata_factory.new_metadata(),
            is_contentful,
        ));

        // Send the pending metric information to the compositor thread.
        // The compositor will record the current time after painting the
        // frame with the given ID and will send the metric back to us.
        let msg = LayoutMsg::PendingPaintMetric(self.pipeline_id, epoch);
        if let Err(e) = self.constellation_chan.send(msg) {
            warn!("Failed to send PendingPaintMetric {:?}", e);
        }
    }

    pub fn maybe_set_metric(&self, epoch: Epoch, paint_time: f64) {
        if self.first_paint.get().is_some() && self.first_contentful_paint.get().is_some() ||
            self.navigation_start.is_none() {
            // If we already set all paint metrics or we have not set navigation start yet,
            // we just bail out.
            return;
        }

        if let Some(pending_metric) = self.pending_metrics.borrow_mut().remove(&epoch) {
            let profiler_metadata = pending_metric.0;
            set_metric(
                self,
                profiler_metadata.clone(),
                ProgressiveWebMetricType::FirstPaint,
                ProfilerCategory::TimeToFirstPaint,
                &self.first_paint,
                Some(paint_time),
            );

            if pending_metric.1 {
                set_metric(
                    self,
                    profiler_metadata,
                    ProgressiveWebMetricType::FirstContentfulPaint,
                    ProfilerCategory::TimeToFirstContentfulPaint,
                    &self.first_contentful_paint,
                    Some(paint_time),
                );
            }
        }
    }

    pub fn get_first_paint(&self) -> Option<f64> {
        self.first_paint.get()
    }

    pub fn get_first_contentful_paint(&self) -> Option<f64> {
        self.first_contentful_paint.get()
    }
}

impl ProgressiveWebMetric for PaintTimeMetrics {
    fn get_navigation_start(&self) -> Option<f64> {
        self.navigation_start
    }

    fn set_navigation_start(&mut self, time: f64) {
        self.navigation_start = Some(time);
    }

    fn send_queued_constellation_msg(&self, name: ProgressiveWebMetricType, time: f64) {
        let msg = ConstellationControlMsg::PaintMetric(self.pipeline_id, name, time);
        if let Err(e) = self.script_chan.send(msg) {
            warn!("Sending metric to script thread failed ({}).", e);
        }
    }

    fn get_time_profiler_chan(&self) -> &ProfilerChan {
        &self.time_profiler_chan
    }
}
<commit_msg>Auto merge of #19078 - outkaj:master, r=KiChjang<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate gfx;
extern crate gfx_traits;
extern crate ipc_channel;
#[macro_use]
extern crate log;
extern crate malloc_size_of;
#[macro_use]
extern crate malloc_size_of_derive;
extern crate msg;
extern crate profile_traits;
extern crate script_traits;
extern crate servo_config;
extern crate time;

use gfx::display_list::{DisplayItem, DisplayList};
use gfx_traits::Epoch;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::PipelineId;
use profile_traits::time::{ProfilerChan, ProfilerCategory, send_profile_data};
use profile_traits::time::TimerMetadata;
use script_traits::{ConstellationControlMsg, LayoutMsg, ProgressiveWebMetricType};
use servo_config::opts;
use std::cell::{Cell, RefCell};
use std::cmp::Ordering;
use std::collections::HashMap;
use time::precise_time_ns;

pub trait ProfilerMetadataFactory {
    fn new_metadata(&self) -> Option<TimerMetadata>;
}

pub trait ProgressiveWebMetric {
    fn get_navigation_start(&self) -> Option<f64>;
    fn set_navigation_start(&mut self, time: f64);
    fn get_time_profiler_chan(&self) -> &ProfilerChan;
    fn send_queued_constellation_msg(&self, name: ProgressiveWebMetricType, time: f64);
}

/// maximum task time is 50ms (in ns)
pub const MAX_TASK_NS: u64 = 50000000;
/// 10 second window (in ns)
const INTERACTIVE_WINDOW_SECONDS_IN_NS: u64 = 10000000000;

fn set_metric<U: ProgressiveWebMetric>(
    pwm: &U,
    metadata: Option<TimerMetadata>,
    metric_type: ProgressiveWebMetricType,
    category: ProfilerCategory,
    attr: &Cell<Option<f64>>,
    metric_time: Option<f64>)
{
    let navigation_start = match pwm.get_navigation_start() {
        Some(time) => time,
        None => {
            warn!("Trying to set metric before navigation start");
            return;
        }
    };
    let now = match metric_time {
        Some(time) => time,
        None => precise_time_ns() as f64,
    };
    let time = now - navigation_start;
    attr.set(Some(time));

    // Queue performance observer notification.
    pwm.send_queued_constellation_msg(metric_type, time);

    // Send the metric to the time profiler.
    send_profile_data(
        category,
        metadata,
        &pwm.get_time_profiler_chan(),
        time as u64,
        time as u64,
        0,
        0,
    );

    // Print the metric to console if the print-pwm option was given.
    if opts::get().print_pwm {
        println!("{:?} {:?}", metric_type, time);
    }

}

// https://github.com/GoogleChrome/lighthouse/issues/27
// we can look at three different metrics here:
// navigation start -> visually ready (dom content loaded)
// navigation start -> thread ready (main thread available)
// visually ready -> thread ready
#[derive(MallocSizeOf)]
pub struct InteractiveMetrics {
    /// when we navigated to the page
    navigation_start: Option<f64>,
    /// indicates if the page is visually ready
    dom_content_loaded: Cell<Option<f64>>,
    /// main thread is available -- there's been a 10s window with no tasks longer than 50ms
    main_thread_available: Cell<Option<f64>>,
    // max(main_thread_available, dom_content_loaded)
    time_to_interactive: Cell<Option<f64>>,
    #[ignore_malloc_size_of = "can't measure channels"]
    time_profiler_chan: ProfilerChan,
}

#[derive(Clone, Copy, Debug, MallocSizeOf)]
pub struct InteractiveWindow {
    start: u64,
}

impl InteractiveWindow {
    pub fn new() -> InteractiveWindow {
        InteractiveWindow {
            start: precise_time_ns(),
        }
    }

    // We need to either start or restart the 10s window
    //   start: we've added a new document
    //   restart: there was a task > 50ms
    //   not all documents are interactive
    pub fn start_window(&mut self) {
        self.start = precise_time_ns();
    }

    /// check if 10s has elapsed since start
    pub fn needs_check(&self) -> bool {
        precise_time_ns() - self.start >= INTERACTIVE_WINDOW_SECONDS_IN_NS
    }

    pub fn get_start(&self) -> u64 {
        self.start
    }
}

#[derive(Debug)]
pub enum InteractiveFlag {
    DOMContentLoaded,
    TimeToInteractive(f64),
}

impl InteractiveMetrics {
    pub fn new(time_profiler_chan: ProfilerChan) -> InteractiveMetrics {
        InteractiveMetrics {
            navigation_start: None,
            dom_content_loaded: Cell::new(None),
            main_thread_available: Cell::new(None),
            time_to_interactive: Cell::new(None),
            time_profiler_chan: time_profiler_chan,
        }
    }

    pub fn set_dom_content_loaded(&self) {
        if self.dom_content_loaded.get().is_none() {
            self.dom_content_loaded.set(Some(precise_time_ns() as f64));
        }
    }

    pub fn set_main_thread_available(&self, time: f64) {
        if self.main_thread_available.get().is_none() {
            self.main_thread_available.set(Some(time));
        }
    }

    pub fn get_dom_content_loaded(&self) -> Option<f64> {
        self.dom_content_loaded.get()
    }

    pub fn get_main_thread_available(&self) -> Option<f64> {
        self.main_thread_available.get()
    }

    // can set either dlc or tti first, but both must be set to actually calc metric
    // when the second is set, set_tti is called with appropriate time
    pub fn maybe_set_tti<T>(
        &self,
        profiler_metadata_factory: &T,
        metric: InteractiveFlag,
    ) where
        T: ProfilerMetadataFactory,
    {
        if self.get_tti().is_some() {
            return;
        }
        match metric {
            InteractiveFlag::DOMContentLoaded => self.set_dom_content_loaded(),
            InteractiveFlag::TimeToInteractive(time) => self.set_main_thread_available(time),
        }

        let dcl = self.dom_content_loaded.get();
        let mta = self.main_thread_available.get();
        let (dcl, mta) = match (dcl, mta) {
        (Some(dcl), Some(mta)) => (dcl, mta),
            _ => return,
        };
        let metric_time = match dcl.partial_cmp(&mta) {
            Some(Ordering::Less) => mta,
            Some(_) => dcl,
            None => panic!("no ordering possible. something bad happened"),
        };
        set_metric(
            self,
            profiler_metadata_factory.new_metadata(),
            ProgressiveWebMetricType::TimeToInteractive,
            ProfilerCategory::TimeToInteractive,
            &self.time_to_interactive,
            Some(metric_time));
    }

    pub fn get_tti(&self) -> Option<f64> {
        self.time_to_interactive.get()
    }
}

impl ProgressiveWebMetric for InteractiveMetrics {
    fn get_navigation_start(&self) -> Option<f64> {
        self.navigation_start
    }

    fn set_navigation_start(&mut self, time: f64) {
        self.navigation_start = Some(time);
    }

    fn send_queued_constellation_msg(&self, _name: ProgressiveWebMetricType, _time: f64) { }

    fn get_time_profiler_chan(&self) -> &ProfilerChan {
        &self.time_profiler_chan
    }
}

pub struct PaintTimeMetrics {
    pending_metrics: RefCell<HashMap<Epoch, (Option<TimerMetadata>, bool)>>,
    navigation_start: Option<f64>,
    first_paint: Cell<Option<f64>>,
    first_contentful_paint: Cell<Option<f64>>,
    pipeline_id: PipelineId,
    time_profiler_chan: ProfilerChan,
    constellation_chan: IpcSender<LayoutMsg>,
    script_chan: IpcSender<ConstellationControlMsg>,
}

impl PaintTimeMetrics {
    pub fn new(
        pipeline_id: PipelineId,
        time_profiler_chan: ProfilerChan,
        constellation_chan: IpcSender<LayoutMsg>,
        script_chan: IpcSender<ConstellationControlMsg>)
            -> PaintTimeMetrics {
        PaintTimeMetrics {
            pending_metrics: RefCell::new(HashMap::new()),
            navigation_start: None,
            first_paint: Cell::new(None),
            first_contentful_paint: Cell::new(None),
            pipeline_id,
            time_profiler_chan,
            constellation_chan,
            script_chan,
        }
    }

    pub fn maybe_set_first_paint<T>(&self, profiler_metadata_factory: &T)
    where
        T: ProfilerMetadataFactory,
    {
        if self.first_paint.get().is_some() {
            return;
        }

        set_metric(
            self,
            profiler_metadata_factory.new_metadata(),
            ProgressiveWebMetricType::FirstPaint,
            ProfilerCategory::TimeToFirstPaint,
            &self.first_paint,
            None,
        );
    }

    pub fn maybe_observe_paint_time<T>(
        &self,
        profiler_metadata_factory: &T,
        epoch: Epoch,
        display_list: &DisplayList)
    where T: ProfilerMetadataFactory {
        if self.first_paint.get().is_some() && self.first_contentful_paint.get().is_some() {
            // If we already set all paint metrics, we just bail out.
            return;
        }

        let mut is_contentful = false;
        // Analyze the display list to figure out if this may be the first
        // contentful paint (i.e. the display list contains items of type text,
        // image, non-white canvas or SVG).
        for item in &display_list.list {
            match item {
                &DisplayItem::Text(_) |
                &DisplayItem::Image(_) => {
                    is_contentful = true;
                    break;
                }
                _ => (),
            }
        }

        self.pending_metrics.borrow_mut().insert(epoch, (
            profiler_metadata_factory.new_metadata(),
            is_contentful,
        ));

        // Send the pending metric information to the compositor thread.
        // The compositor will record the current time after painting the
        // frame with the given ID and will send the metric back to us.
        let msg = LayoutMsg::PendingPaintMetric(self.pipeline_id, epoch);
        if let Err(e) = self.constellation_chan.send(msg) {
            warn!("Failed to send PendingPaintMetric {:?}", e);
        }
    }

    pub fn maybe_set_metric(&self, epoch: Epoch, paint_time: f64) {
        if self.first_paint.get().is_some() && self.first_contentful_paint.get().is_some() ||
            self.navigation_start.is_none() {
            // If we already set all paint metrics or we have not set navigation start yet,
            // we just bail out.
            return;
        }

        if let Some(pending_metric) = self.pending_metrics.borrow_mut().remove(&epoch) {
            let profiler_metadata = pending_metric.0;
            set_metric(
                self,
                profiler_metadata.clone(),
                ProgressiveWebMetricType::FirstPaint,
                ProfilerCategory::TimeToFirstPaint,
                &self.first_paint,
                Some(paint_time),
            );

            if pending_metric.1 {
                set_metric(
                    self,
                    profiler_metadata,
                    ProgressiveWebMetricType::FirstContentfulPaint,
                    ProfilerCategory::TimeToFirstContentfulPaint,
                    &self.first_contentful_paint,
                    Some(paint_time),
                );
            }
        }
    }

    pub fn get_first_paint(&self) -> Option<f64> {
        self.first_paint.get()
    }

    pub fn get_first_contentful_paint(&self) -> Option<f64> {
        self.first_contentful_paint.get()
    }
}

impl ProgressiveWebMetric for PaintTimeMetrics {
    fn get_navigation_start(&self) -> Option<f64> {
        self.navigation_start
    }

    fn set_navigation_start(&mut self, time: f64) {
        self.navigation_start = Some(time);
    }

    fn send_queued_constellation_msg(&self, name: ProgressiveWebMetricType, time: f64) {
        let msg = ConstellationControlMsg::PaintMetric(self.pipeline_id, name, time);
        if let Err(e) = self.script_chan.send(msg) {
            warn!("Sending metric to script thread failed ({}).", e);
        }
    }

    fn get_time_profiler_chan(&self) -> &ProfilerChan {
        &self.time_profiler_chan
    }
}
<|endoftext|>


<commit_before>use crate::spec::TargetOptions;

use Arch::*;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum Arch {
    Armv7,
    Armv7s,
    Arm64,
    I386,
    X86_64,
    X86_64_macabi,
}

fn target_cpu(arch: Arch) -> String {
    match arch {
        Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
        Armv7s => "cortex-a9",
        Arm64 => "apple-a7",
        I386 => "yonah",
        X86_64 => "core2",
        X86_64_macabi => "core2",
    }
    .to_string()
}

fn link_env_remove(arch: Arch) -> Vec<String> {
    match arch {
        Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
        X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
    }
}

pub fn opts(arch: Arch) -> TargetOptions {
    TargetOptions {
        cpu: target_cpu(arch),
        executables: true,
        link_env_remove: link_env_remove(arch),
        has_elf_tls: false,
        eliminate_frame_pointer: false,
        ..super::apple_base::opts()
    }
}
<commit_msg>Rollup merge of #77716 - francesca64:revert-ios-dynamic-linking, r=jonas-schievink<commit_after>use crate::spec::TargetOptions;

use Arch::*;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum Arch {
    Armv7,
    Armv7s,
    Arm64,
    I386,
    X86_64,
    X86_64_macabi,
}

fn target_cpu(arch: Arch) -> String {
    match arch {
        Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
        Armv7s => "cortex-a9",
        Arm64 => "apple-a7",
        I386 => "yonah",
        X86_64 => "core2",
        X86_64_macabi => "core2",
    }
    .to_string()
}

fn link_env_remove(arch: Arch) -> Vec<String> {
    match arch {
        Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
        X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
    }
}

pub fn opts(arch: Arch) -> TargetOptions {
    TargetOptions {
        cpu: target_cpu(arch),
        dynamic_linking: false,
        executables: true,
        link_env_remove: link_env_remove(arch),
        has_elf_tls: false,
        eliminate_frame_pointer: false,
        ..super::apple_base::opts()
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use extra::json;
use serialize::Decodable;
use glfw;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;
use mesh::Mesh;
use misc::read_file;

fn build_hex_mesh(&geom: &Geom) -> ~[Vec3<GLfloat>] {
  let mut vertex_data = ~[];
  for tile_pos in TileIterator::new() {
    let pos3d = geom.map_pos_to_world_pos(tile_pos);
    for num in range(0, 6) {
      let vertex = geom.index_to_hex_vertex(num);
      let next_vertex = geom.index_to_hex_vertex(num + 1);
      let data = &mut vertex_data;
      data.push(pos3d + vertex);
      data.push(pos3d + next_vertex);
      data.push(pos3d + Vec3::zero());
    }
  }
  vertex_data
}

pub struct Visualizer {
  program: GLuint,
  map_mesh: Mesh,
  unit_mesh: Mesh,
  mat_id: GLint,
  win: Option<glfw::Window>,
  mouse_pos: Vec2<f32>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<Vec2<i32>>,
  geom: Geom,
}

fn init_win(win_size: Vec2<int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "Marauder",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win.set_all_polling(true);
  win
}

#[deriving(Decodable)]
struct Size2<T> {
  x: T,
  y: T,
}

fn read_win_size(config_path: &str) -> Vec2<int> {
  let path = Path::new(config_path);
  let json = json::from_str(read_file(&path)).unwrap();
  let mut decoder = json::Decoder::new(json);
  let size: Size2<int> = Decodable::decode(&mut decoder);
  Vec2{x: size.x, y: size.y}
}

impl Visualizer {
  pub fn new() -> ~Visualizer {
    let win_size = read_win_size("config.json");
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      program: 0,
      map_mesh: Mesh::new(),
      unit_mesh: Mesh::new(),
      mat_id: 0,
      win: Some(win),
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(),
      selected_tile_pos: None,
      geom: geom,
    };
    vis.init_opengl();
    vis.picker.init(&geom);
    vis.init_models();
    vis
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    self.win.get_ref()
  }

  fn init_models(&mut self) {
    self.program = glh::compile_program(
      read_file(&Path::new("normal.vs.glsl")),
      read_file(&Path::new("normal.fs.glsl")),
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    let position_attr = glh::get_attr(self.program, "position");
    gl::EnableVertexAttribArray(position_attr);
    glh::vertex_attrib_pointer(position_attr);
    let map_vertex_data = build_hex_mesh(&self.geom);
    self.map_mesh.init(map_vertex_data);
    let unit_obj = obj::Model::new("data/tank.obj");
    self.unit_mesh.init(unit_obj.build());
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
  }

  fn draw_unit_at(&self, pos: Vec2<i32>) {
    let world_pos = self.geom.map_pos_to_world_pos(pos);
    let m = glh::tr(self.camera.mat(), world_pos);
    glh::uniform_mat4f(self.mat_id, &m);
    self.unit_mesh.draw(self.program);
  }

  fn draw_units(&self) {
    self.draw_unit_at(Vec2{x: 0, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 0});
    self.draw_unit_at(Vec2{x: 2, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 1});
    if !self.selected_tile_pos.is_none() {
      let p = self.selected_tile_pos.unwrap();
      self.draw_unit_at(p);
    }
  }

  fn draw_map(&self) {
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.map_mesh.draw(self.program);
  }

  fn draw(&self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::UseProgram(self.program);
    self.draw_units();
    self.draw_map();
    self.win().swap_buffers();
  }

  pub fn is_running(&self) -> bool {
    return !self.win().should_close()
  }

  fn handle_key_event(&mut self, key: glfw::Key) {
    match key {
      glfw::KeyEscape | glfw::KeyQ => {
        self.win().set_should_close(true);
      },
      glfw::KeySpace => println!("space"),
      glfw::KeyUp => self.camera.move(270.0),
      glfw::KeyDown => self.camera.move(90.0),
      glfw::KeyRight => self.camera.move(0.0),
      glfw::KeyLeft => self.camera.move(180.0),
      _ => {},
    }
  }

  fn handle_cursor_pos_event(&mut self, pos: Vec2<f32>) {
    let button = self.win().get_mouse_button(glfw::MouseButtonRight);
    if button == glfw::Press {
      self.camera.z_angle += self.mouse_pos.x - pos.x;
      self.camera.x_angle += self.mouse_pos.y - pos.y;
    }
    self.mouse_pos = pos;
  }

  fn get_events(&mut self) -> ~[glfw::WindowEvent]{
    glfw::poll_events();
    let mut events = ~[];
    for (_, event) in self.win().flush_events() {
      events.push(event);
    }
    events
  }

  fn handle_event(&mut self, event: glfw::WindowEvent) {
    match event {
      glfw::KeyEvent(key, _, glfw::Press, _) => {
        self.handle_key_event(key);
      },
      glfw::CursorPosEvent(x, y) => {
        let p = Vec2{x: x as f32, y: y as f32};
        self.handle_cursor_pos_event(p);
      },
      glfw::SizeEvent(w, h) => {
        gl::Viewport(0, 0, w, h);
      },
      _ => {},
    }
  }

  fn handle_events(&mut self) {
    for event in self.get_events().iter() {
      self.handle_event(*event);
    }
  }

  fn close_window(&mut self) {
    // destroy glfw::Window before terminating glfw
    self.win = None;
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as i32,
      y: self.mouse_pos.y as i32,
    };
    let win_size = self.win().get_size();
    self.selected_tile_pos = self.picker.pick_tile(
      win_size, &self.camera, mouse_pos);
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.pick_tile();
    self.draw();
  }
}

impl Drop for Visualizer {
  fn drop(&mut self) {
    self.cleanup_opengl();
    self.close_window();
    glfw::terminate();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>Updated to latest glfw-rs<commit_after>// See LICENSE file for copyright and license details.

use extra::json;
use serialize::Decodable;
use glfw;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;
use mesh::Mesh;
use misc::read_file;

fn build_hex_mesh(&geom: &Geom) -> ~[Vec3<GLfloat>] {
  let mut vertex_data = ~[];
  for tile_pos in TileIterator::new() {
    let pos3d = geom.map_pos_to_world_pos(tile_pos);
    for num in range(0, 6) {
      let vertex = geom.index_to_hex_vertex(num);
      let next_vertex = geom.index_to_hex_vertex(num + 1);
      let data = &mut vertex_data;
      data.push(pos3d + vertex);
      data.push(pos3d + next_vertex);
      data.push(pos3d + Vec3::zero());
    }
  }
  vertex_data
}

pub struct Visualizer {
  program: GLuint,
  map_mesh: Mesh,
  unit_mesh: Mesh,
  mat_id: GLint,
  win: Option<glfw::Window>,
  mouse_pos: Vec2<f32>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<Vec2<i32>>,
  geom: Geom,
}

fn init_win(win_size: Vec2<int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "Marauder",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win.set_all_polling(true);
  win
}

#[deriving(Decodable)]
struct Size2<T> {
  x: T,
  y: T,
}

fn read_win_size(config_path: &str) -> Vec2<int> {
  let path = Path::new(config_path);
  let json = json::from_str(read_file(&path)).unwrap();
  let mut decoder = json::Decoder::new(json);
  let size: Size2<int> = Decodable::decode(&mut decoder);
  Vec2{x: size.x, y: size.y}
}

impl Visualizer {
  pub fn new() -> ~Visualizer {
    let win_size = read_win_size("config.json");
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      program: 0,
      map_mesh: Mesh::new(),
      unit_mesh: Mesh::new(),
      mat_id: 0,
      win: Some(win),
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(),
      selected_tile_pos: None,
      geom: geom,
    };
    vis.init_opengl();
    vis.picker.init(&geom);
    vis.init_models();
    vis
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    self.win.get_ref()
  }

  fn init_models(&mut self) {
    self.program = glh::compile_program(
      read_file(&Path::new("normal.vs.glsl")),
      read_file(&Path::new("normal.fs.glsl")),
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    let position_attr = glh::get_attr(self.program, "position");
    gl::EnableVertexAttribArray(position_attr);
    glh::vertex_attrib_pointer(position_attr);
    let map_vertex_data = build_hex_mesh(&self.geom);
    self.map_mesh.init(map_vertex_data);
    let unit_obj = obj::Model::new("data/tank.obj");
    self.unit_mesh.init(unit_obj.build());
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
  }

  fn draw_unit_at(&self, pos: Vec2<i32>) {
    let world_pos = self.geom.map_pos_to_world_pos(pos);
    let m = glh::tr(self.camera.mat(), world_pos);
    glh::uniform_mat4f(self.mat_id, &m);
    self.unit_mesh.draw(self.program);
  }

  fn draw_units(&self) {
    self.draw_unit_at(Vec2{x: 0, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 0});
    self.draw_unit_at(Vec2{x: 2, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 1});
    if !self.selected_tile_pos.is_none() {
      let p = self.selected_tile_pos.unwrap();
      self.draw_unit_at(p);
    }
  }

  fn draw_map(&self) {
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.map_mesh.draw(self.program);
  }

  fn draw(&self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::UseProgram(self.program);
    self.draw_units();
    self.draw_map();
    self.win().swap_buffers();
  }

  pub fn is_running(&self) -> bool {
    return !self.win().should_close()
  }

  fn handle_key_event(&mut self, key: glfw::Key) {
    match key {
      glfw::KeyEscape | glfw::KeyQ => {
        self.win().set_should_close(true);
      },
      glfw::KeySpace => println!("space"),
      glfw::KeyUp => self.camera.move(270.0),
      glfw::KeyDown => self.camera.move(90.0),
      glfw::KeyRight => self.camera.move(0.0),
      glfw::KeyLeft => self.camera.move(180.0),
      _ => {},
    }
  }

  fn handle_cursor_pos_event(&mut self, pos: Vec2<f32>) {
    let button = self.win().get_mouse_button(glfw::MouseButtonRight);
    if button == glfw::Press {
      self.camera.z_angle += self.mouse_pos.x - pos.x;
      self.camera.x_angle += self.mouse_pos.y - pos.y;
    }
    self.mouse_pos = pos;
  }

  fn get_events(&mut self) -> ~[glfw::WindowEvent]{
    glfw::poll_events();
    let mut events = ~[];
    for (_, event) in self.win().flush_events() {
      events.push(event);
    }
    events
  }

  fn handle_event(&mut self, event: glfw::WindowEvent) {
    match event {
      glfw::KeyEvent(key, _, glfw::Press, _) => {
        self.handle_key_event(key);
      },
      glfw::CursorPosEvent(x, y) => {
        let p = Vec2{x: x as f32, y: y as f32};
        self.handle_cursor_pos_event(p);
      },
      glfw::SizeEvent(w, h) => {
        gl::Viewport(0, 0, w, h);
      },
      _ => {},
    }
  }

  fn handle_events(&mut self) {
    for event in self.get_events().iter() {
      self.handle_event(*event);
    }
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as i32,
      y: self.mouse_pos.y as i32,
    };
    let win_size = self.win().get_size();
    self.selected_tile_pos = self.picker.pick_tile(
      win_size, &self.camera, mouse_pos);
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.pick_tile();
    self.draw();
  }
}

impl Drop for Visualizer {
  fn drop(&mut self) {
    self.cleanup_opengl();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<|endoftext|>


<commit_before>use super::*;
use crate::test;
use envmnt;
use rust_info::types::RustChannel;

#[test]
#[ignore]
fn get_cargo_home_env() {
    let directory_path = env::current_dir().unwrap();
    let directory = directory_path.to_str().unwrap();
    envmnt::set("CARGO_HOME", directory);

    let output = get_cargo_home().unwrap();
    envmnt::remove("CARGO_HOME");

    assert_eq!(output, directory);
}

#[test]
#[ignore]
fn get_cargo_home_no_env() {
    envmnt::remove("CARGO_HOME");

    let output = get_cargo_home().unwrap();

    assert!(output.contains(".cargo"));
}

#[test]
#[ignore]
fn get_cargo_home_file() {
    let directory_path = env::current_dir().unwrap();
    let directory = directory_path.to_str().unwrap();
    let file_path = Path::new(directory).join("Cargo.toml");
    envmnt::set("CARGO_HOME", file_path);

    let output = get_cargo_home();
    envmnt::remove("CARGO_HOME");

    assert!(output.is_none());
}

#[test]
fn load_crates_toml_valid() {
    let cwd = envmnt::get_or_panic("CARGO_MAKE_WORKING_DIRECTORY");
    let file_path = Path::new(&cwd).join("src/lib/test/test_files");
    let directory = file_path.to_str().unwrap();
    let info_option = load_crates_toml(&directory);

    assert!(info_option.is_some());
    let info = info_option.unwrap();
    assert!(info.v1.is_some());
    assert_eq!(info.v1.unwrap().len(), 3);
}

#[test]
fn load_crates_toml_file_not_found() {
    let cwd = envmnt::get_or_panic("CARGO_MAKE_WORKING_DIRECTORY");
    let info_option = load_crates_toml(&cwd);

    assert!(info_option.is_none());
}

#[test]
fn get_crate_version_from_info_no_info() {
    let info = CratesRegistryInfo { v1: None };
    let version = get_crate_version_from_info("cargo-make", &info);

    assert!(version.is_none());
}

#[test]
fn get_crate_version_from_info_empty_info() {
    let info = CratesRegistryInfo {
        v1: Some(HashMap::new()),
    };
    let version = get_crate_version_from_info("cargo-make", &info);

    assert!(version.is_none());
}

#[test]
fn get_crate_version_from_info_not_found() {
    let mut map = HashMap::new();
    map.insert("1 1 1".to_string(), vec![]);
    map.insert("2 2 2".to_string(), vec![]);
    let info = CratesRegistryInfo { v1: Some(map) };
    let version = get_crate_version_from_info("cargo-make", &info);

    assert!(version.is_none());
}

#[test]
fn get_crate_version_from_info_found_invalid_line() {
    let mut map = HashMap::new();
    map.insert("1 1 1".to_string(), vec![]);
    map.insert("cargo-make".to_string(), vec![]);
    map.insert("2 2 2".to_string(), vec![]);
    let info = CratesRegistryInfo { v1: Some(map) };
    let version = get_crate_version_from_info("cargo-make", &info);

    assert!(version.is_none());
}

#[test]
fn get_crate_version_from_info_found_invalid_version() {
    let mut map = HashMap::new();
    map.insert("1 1 1".to_string(), vec![]);
    map.insert("cargo-make abc 2".to_string(), vec![]);
    map.insert("2 2 2".to_string(), vec![]);
    let info = CratesRegistryInfo { v1: Some(map) };
    let version = get_crate_version_from_info("cargo-make", &info);

    assert!(version.is_none());
}

#[test]
fn get_crate_version_from_info_valid() {
    let mut map = HashMap::new();
    map.insert("1 1 1".to_string(), vec![]);
    map.insert("cargo-make 1.2.3 2".to_string(), vec![]);
    map.insert("2 2 2".to_string(), vec![]);
    let info = CratesRegistryInfo { v1: Some(map) };
    let version = get_crate_version_from_info("cargo-make", &info);

    let semver_version = version.unwrap();
    assert_eq!(semver_version.major, 1);
    assert_eq!(semver_version.minor, 2);
    assert_eq!(semver_version.patch, 3);
}

#[test]
#[cfg(target_os = "linux")]
fn get_crate_version_for_rustup_component() {
    if test::is_rust_channel(RustChannel::Stable) {
        let mut version = get_crate_version("rustfmt", None);
        assert!(version.is_none());

        version = get_crate_version("rustfmt", Some("rustfmt"));
        assert!(version.is_some());
    }
}

#[test]
fn is_min_version_valid_for_versions_equal() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.2.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(valid);
}

#[test]
fn is_min_version_valid_for_versions_false_major() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("2.2.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_min_version_valid_for_versions_false_minor() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.3.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_min_version_valid_for_versions_false_patch() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.2.4").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_min_version_valid_for_versions_true_major() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.2.3").unwrap(),
        &Version::parse("2.2.3").unwrap(),
    );

    assert!(valid);
}

#[test]
fn is_min_version_valid_for_versions_true_minor() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.2.3").unwrap(),
        &Version::parse("1.3.3").unwrap(),
    );

    assert!(valid);
}

#[test]
fn is_min_version_valid_for_versions_true_patch() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.2.3").unwrap(),
        &Version::parse("1.2.4").unwrap(),
    );

    assert!(valid);
}

#[test]
fn is_min_version_valid_not_found() {
    let valid = is_min_version_valid("bad_crate", "1.2.3", None);

    assert!(valid);
}

#[test]
fn is_min_version_valid_invalid_version() {
    let valid = is_min_version_valid("cargo-make", "bad_version", None);

    assert!(valid);
}

#[test]
fn is_min_version_valid_old_version() {
    let valid = is_min_version_valid("cargo-make", "0.0.1", None);

    assert!(valid);
}

#[test]
fn is_min_version_valid_newer_version() {
    let valid = is_min_version_valid("cargo-make", "10000.0.0", None);

    assert!(!valid);
}

#[test]
fn is_min_version_valid_same_version() {
    let version = get_crate_version("cargo-make", None).unwrap();
    let mut version_string = String::new();
    version_string.push_str(&version.major.to_string());
    version_string.push_str(".");
    version_string.push_str(&version.minor.to_string());
    version_string.push_str(".");
    version_string.push_str(&version.patch.to_string());

    let valid = is_min_version_valid("cargo-make", &version_string, None);

    assert!(valid);
}

#[test]
fn is_version_valid_for_versions_equal() {
    let valid = is_version_valid_for_versions(
        &Version::parse("1.2.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(valid);
}

#[test]
fn is_version_valid_for_versions_false_major() {
    let valid = is_version_valid_for_versions(
        &Version::parse("2.2.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_version_valid_for_versions_false_minor() {
    let valid = is_version_valid_for_versions(
        &Version::parse("1.3.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_version_valid_for_versions_false_patch() {
    let valid = is_version_valid_for_versions(
        &Version::parse("1.2.4").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_version_valid_not_found() {
    let valid = is_version_valid("bad_crate", "1.2.3", None);

    assert!(valid);
}

#[test]
fn is_version_valid_invalid_version() {
    let valid = is_version_valid("cargo-make", "bad_version", None);

    assert!(valid);
}

#[test]
fn is_version_valid_old_version() {
    let valid = is_version_valid("cargo-make", "0.0.1", None);

    assert!(!valid);
}

#[test]
fn is_version_valid_newer_version() {
    let valid = is_version_valid("cargo-make", "10000.0.0", None);

    assert!(!valid);
}

#[test]
fn is_version_valid_same_version() {
    let version = get_crate_version("cargo-make", None).unwrap();
    let mut version_string = String::new();
    version_string.push_str(&version.major.to_string());
    version_string.push_str(".");
    version_string.push_str(&version.minor.to_string());
    version_string.push_str(".");
    version_string.push_str(&version.patch.to_string());

    let valid = is_min_version_valid("cargo-make", &version_string, None);

    assert!(valid);
}
<commit_msg>fix tests<commit_after>use super::*;
use crate::test;
use ci_info;
use envmnt;
use rust_info::types::RustChannel;

#[test]
#[ignore]
fn get_cargo_home_env() {
    let directory_path = env::current_dir().unwrap();
    let directory = directory_path.to_str().unwrap();
    envmnt::set("CARGO_HOME", directory);

    let output = get_cargo_home().unwrap();
    envmnt::remove("CARGO_HOME");

    assert_eq!(output, directory);
}

#[test]
#[ignore]
fn get_cargo_home_no_env() {
    envmnt::remove("CARGO_HOME");

    let output = get_cargo_home().unwrap();

    assert!(output.contains(".cargo"));
}

#[test]
#[ignore]
fn get_cargo_home_file() {
    let directory_path = env::current_dir().unwrap();
    let directory = directory_path.to_str().unwrap();
    let file_path = Path::new(directory).join("Cargo.toml");
    envmnt::set("CARGO_HOME", file_path);

    let output = get_cargo_home();
    envmnt::remove("CARGO_HOME");

    assert!(output.is_none());
}

#[test]
fn load_crates_toml_valid() {
    let cwd = envmnt::get_or_panic("CARGO_MAKE_WORKING_DIRECTORY");
    let file_path = Path::new(&cwd).join("src/lib/test/test_files");
    let directory = file_path.to_str().unwrap();
    let info_option = load_crates_toml(&directory);

    assert!(info_option.is_some());
    let info = info_option.unwrap();
    assert!(info.v1.is_some());
    assert_eq!(info.v1.unwrap().len(), 3);
}

#[test]
fn load_crates_toml_file_not_found() {
    let cwd = envmnt::get_or_panic("CARGO_MAKE_WORKING_DIRECTORY");
    let info_option = load_crates_toml(&cwd);

    assert!(info_option.is_none());
}

#[test]
fn get_crate_version_from_info_no_info() {
    let info = CratesRegistryInfo { v1: None };
    let version = get_crate_version_from_info("cargo-make", &info);

    assert!(version.is_none());
}

#[test]
fn get_crate_version_from_info_empty_info() {
    let info = CratesRegistryInfo {
        v1: Some(HashMap::new()),
    };
    let version = get_crate_version_from_info("cargo-make", &info);

    assert!(version.is_none());
}

#[test]
fn get_crate_version_from_info_not_found() {
    let mut map = HashMap::new();
    map.insert("1 1 1".to_string(), vec![]);
    map.insert("2 2 2".to_string(), vec![]);
    let info = CratesRegistryInfo { v1: Some(map) };
    let version = get_crate_version_from_info("cargo-make", &info);

    assert!(version.is_none());
}

#[test]
fn get_crate_version_from_info_found_invalid_line() {
    let mut map = HashMap::new();
    map.insert("1 1 1".to_string(), vec![]);
    map.insert("cargo-make".to_string(), vec![]);
    map.insert("2 2 2".to_string(), vec![]);
    let info = CratesRegistryInfo { v1: Some(map) };
    let version = get_crate_version_from_info("cargo-make", &info);

    assert!(version.is_none());
}

#[test]
fn get_crate_version_from_info_found_invalid_version() {
    let mut map = HashMap::new();
    map.insert("1 1 1".to_string(), vec![]);
    map.insert("cargo-make abc 2".to_string(), vec![]);
    map.insert("2 2 2".to_string(), vec![]);
    let info = CratesRegistryInfo { v1: Some(map) };
    let version = get_crate_version_from_info("cargo-make", &info);

    assert!(version.is_none());
}

#[test]
fn get_crate_version_from_info_valid() {
    let mut map = HashMap::new();
    map.insert("1 1 1".to_string(), vec![]);
    map.insert("cargo-make 1.2.3 2".to_string(), vec![]);
    map.insert("2 2 2".to_string(), vec![]);
    let info = CratesRegistryInfo { v1: Some(map) };
    let version = get_crate_version_from_info("cargo-make", &info);

    let semver_version = version.unwrap();
    assert_eq!(semver_version.major, 1);
    assert_eq!(semver_version.minor, 2);
    assert_eq!(semver_version.patch, 3);
}

#[test]
#[cfg(target_os = "linux")]
fn get_crate_version_for_rustup_component() {
    if test::is_rust_channel(RustChannel::Stable) || !ci_info::is_ci() {
        let mut version = get_crate_version("rustfmt", None);
        assert!(version.is_none());

        version = get_crate_version("rustfmt", Some("rustfmt"));
        assert!(version.is_some());
    }
}

#[test]
fn is_min_version_valid_for_versions_equal() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.2.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(valid);
}

#[test]
fn is_min_version_valid_for_versions_false_major() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("2.2.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_min_version_valid_for_versions_false_minor() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.3.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_min_version_valid_for_versions_false_patch() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.2.4").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_min_version_valid_for_versions_true_major() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.2.3").unwrap(),
        &Version::parse("2.2.3").unwrap(),
    );

    assert!(valid);
}

#[test]
fn is_min_version_valid_for_versions_true_minor() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.2.3").unwrap(),
        &Version::parse("1.3.3").unwrap(),
    );

    assert!(valid);
}

#[test]
fn is_min_version_valid_for_versions_true_patch() {
    let valid = is_min_version_valid_for_versions(
        &Version::parse("1.2.3").unwrap(),
        &Version::parse("1.2.4").unwrap(),
    );

    assert!(valid);
}

#[test]
fn is_min_version_valid_not_found() {
    let valid = is_min_version_valid("bad_crate", "1.2.3", None);

    assert!(valid);
}

#[test]
fn is_min_version_valid_invalid_version() {
    let valid = is_min_version_valid("cargo-make", "bad_version", None);

    assert!(valid);
}

#[test]
fn is_min_version_valid_old_version() {
    let valid = is_min_version_valid("cargo-make", "0.0.1", None);

    assert!(valid);
}

#[test]
fn is_min_version_valid_newer_version() {
    let valid = is_min_version_valid("cargo-make", "10000.0.0", None);

    assert!(!valid);
}

#[test]
fn is_min_version_valid_same_version() {
    let version = get_crate_version("cargo-make", None).unwrap();
    let mut version_string = String::new();
    version_string.push_str(&version.major.to_string());
    version_string.push_str(".");
    version_string.push_str(&version.minor.to_string());
    version_string.push_str(".");
    version_string.push_str(&version.patch.to_string());

    let valid = is_min_version_valid("cargo-make", &version_string, None);

    assert!(valid);
}

#[test]
fn is_version_valid_for_versions_equal() {
    let valid = is_version_valid_for_versions(
        &Version::parse("1.2.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(valid);
}

#[test]
fn is_version_valid_for_versions_false_major() {
    let valid = is_version_valid_for_versions(
        &Version::parse("2.2.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_version_valid_for_versions_false_minor() {
    let valid = is_version_valid_for_versions(
        &Version::parse("1.3.3").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_version_valid_for_versions_false_patch() {
    let valid = is_version_valid_for_versions(
        &Version::parse("1.2.4").unwrap(),
        &Version::parse("1.2.3").unwrap(),
    );

    assert!(!valid);
}

#[test]
fn is_version_valid_not_found() {
    let valid = is_version_valid("bad_crate", "1.2.3", None);

    assert!(valid);
}

#[test]
fn is_version_valid_invalid_version() {
    let valid = is_version_valid("cargo-make", "bad_version", None);

    assert!(valid);
}

#[test]
fn is_version_valid_old_version() {
    let valid = is_version_valid("cargo-make", "0.0.1", None);

    assert!(!valid);
}

#[test]
fn is_version_valid_newer_version() {
    let valid = is_version_valid("cargo-make", "10000.0.0", None);

    assert!(!valid);
}

#[test]
fn is_version_valid_same_version() {
    let version = get_crate_version("cargo-make", None).unwrap();
    let mut version_string = String::new();
    version_string.push_str(&version.major.to_string());
    version_string.push_str(".");
    version_string.push_str(&version.minor.to_string());
    version_string.push_str(".");
    version_string.push_str(&version.patch.to_string());

    let valid = is_min_version_valid("cargo-make", &version_string, None);

    assert!(valid);
}
<|endoftext|>