<commit_before>extern crate termion;
extern crate chrono;

use termion::input::TermRead;
use termion::raw::IntoRawMode;
use termion::{color, style};
use termion::event::Key;
use termion::terminal_size;
use std::io::{Read, Write, Stdout, Stdin};
use std::io::{stdout, stdin};
use std;

use chrono::*;
use utility::string::*;
use model::ShowReplyItem;
use model::ShowItem;
use reply_model::*;
use screen::common::*;

pub struct Show {
    scrollY: usize,
    y: usize,
    replier_max_width: usize,
    time_max_width: usize,
    is_scroll_to_end: bool
}

impl Show {
    pub fn new() -> Self {
        Show {
            scrollY: 0,
            y: 0,
            replier_max_width: 14,
            time_max_width: 5,
            is_scroll_to_end: false
        }
    }
    pub fn print(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, title: &str, item: &ShowItem) {

        self.y = 2;

        self.print_header(stdout, &format!("{} - {} [{}/{}]",
                                   item.title,
                                   title,
                                   item.page,
                                   item.max_page));
        self.print_body(stdout, &item);
    }

    fn print_separator_top(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, reply: &ShowReplyItem) {
        if self.can_print() {
            let (replier_name, time) = make_separator_content(&reply);
            let s = self.build_separator_top(&replier_name, &time);
            self.print_separator_line(stdout, &s);
        }
    }

    fn print_separator_bottom(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>) {
        if self.can_print() {
            let s = self.build_separator_bottom();
            self.print_separator_line(stdout, &s);
        }
    }

    fn print_separator_line(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, s: &str) {

        write!(stdout, "{}{}{}{}{}{}",
                termion::cursor::Goto(1, (self.scrolledY() + 1) as u16),
                color::Fg(color::Green),
                color::Bg(color::Black),
                s,
                style::Reset,
                termion::cursor::Hide);
    }

    fn print_header(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, text: &str) {
        let title_len = jks_len(text);
        let w = terminal_size().unwrap().0 as usize;
        let padding = ((if w >= title_len {
            w - title_len
        } else {
            0
        }) / 2) as u16;

        let header_bottom = seq_str_gen(0, w, "─", "");

        write!(stdout, "{}{}{}{}{}{}{}",
                termion::cursor::Goto(padding + 1, 1),
                color::Fg(color::White),
                color::Bg(color::Black),
                style::Bold,
                text, style::Reset,
                termion::cursor::Hide);

        write!(stdout, "{}{}{}{}{}{}{}",
                termion::cursor::Goto(1, 2),
                color::Fg(color::Yellow),
                color::Bg(color::Black),
                style::Bold,
                header_bottom,
                style::Reset,
                termion::cursor::Hide);
    }

    pub fn print_body(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, item: &ShowItem) {
        let width = self.body_width();
        let rows = self.body_height();

        for (i, reply) in item.replies.iter().take(rows).enumerate() {

            self.print_reply(stdout, &reply.body, 0);

            self.print_separator_top(stdout, &reply);
            self.y += 1;

            self.print_separator_bottom(stdout);
            self.y += 1;
        }

        self.is_scroll_to_end = self.scrolledY() < self.body_height();
    }

    fn print_reply_line(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, s: String) {

       write!(stdout, "{}{}{}{}{}{}",
               termion::cursor::Goto(1, (self.scrolledY() + 1) as u16),
               color::Fg(color::White),
               color::Bg(color::Black),
               s,
               style::Reset,
               termion::cursor::Hide);
    }

    fn print_reply(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, vec: &Vec<NodeType>, depth: usize) {

        let icon_width = 2;
        let clown = imgcat(&"data/img/clown.gif", icon_width);
        let padding = seq_str_gen(0, depth, "├─", "");
        let mut line = String::new();
        let mut is_first = true;

        let vec_clean = clean_reply_body(vec);
        for (j, node) in vec_clean.iter().enumerate() {
            match node.clone() {
                NodeType::Text(n) => {
                    if n.data != "" {
                        line = format!("{}{}", line, n.data);
                    }
                }
                NodeType::Image(n) => {
                    if n.data != "" {
                        if self.can_print() {

                            line = format!("{}{}",
                                    line,
                                    clown);
                        }
                    }
                }
                NodeType::BlockQuote(n) => {
                    self.print_reply(stdout, &n.data, depth + 1);
                    is_first = false;
                }
                NodeType::Br(n) => {
                    if !line.is_empty() {
                        if self.can_print() {
                            self.print_reply_line(stdout, format!(" {}{}", padding, line));
                        }
                        line = String::new();
                        is_first = false;
                    }

                    // prevent first line empty
                    if !is_first {
                        self.y += 1;
                    }

                }
            }
        }

        if !line.is_empty() {
            if self.can_print() {
                self.print_reply_line(stdout, format!(" {}{}  ", padding, line));
            }
            line = String::new();
            self.y += 1;
        }
    }

    fn build_separator_arguments(&mut self) -> (usize, usize, String) {
        let separator_width = self.body_width();
        let w = terminal_size().unwrap().0 as usize;

        let separator_padding_width = if w > separator_width {
            w - separator_width
        } else {
            0
        } / 2;

        let separator_padding = seq_str_gen(0, separator_padding_width, " ", "");

        (separator_width, separator_padding_width, separator_padding)
    }

    fn build_separator_top(&mut self, replier_name: &str, time: &str) -> String {
        let (separator_width, separator_padding_width, separator_padding) =
            self.build_separator_arguments();
        make_separator_top(separator_width,
                           &separator_padding,
                           self.replier_max_width,
                           &replier_name,
                           self.time_max_width,
                           &time)
    }

    fn build_separator_bottom(&mut self) -> String {
        let (separator_width, separator_padding_width, separator_padding) =
            self.build_separator_arguments();
        make_separator_bottom(separator_width, &separator_padding)
    }

    pub fn resetY(&mut self) {
        self.scrollY = 0;
    }

    pub fn scrollUp(&mut self, value: usize) -> bool {
        let tmp = self.scrollY;
        if tmp > value {
            self.scrollY = tmp - value;
            true
        } else if tmp != 0 {
            self.scrollY = 0;
            true
        } else {
            false
        }
    }

    pub fn scrollDown(&mut self, value: usize) -> bool {

        if !self.is_scroll_to_end {
            let min_to_scroll = self.scrollY + self.body_height();
            if self.y >= min_to_scroll + value {
                self.scrollY += value;
                return true;
            } else if self.y >= min_to_scroll {
                self.scrollY += self.y - min_to_scroll;
                return true;
            }
        }

        false
    }

    pub fn body_height(&self) -> usize {

        let h = terminal_size().unwrap().1;

        if h >= 3 {
            h as usize - 3
        } else {
            0
        }
    }

    pub fn body_width(&self) -> usize {

        let w = terminal_size().unwrap().0;

        if w >= 2 {
            w as usize - 2
        } else {
            0
        }
    }

    fn can_print(&self) -> bool {
        self.y > self.scrollY + 1 && self.y < self.scrollY + 1 + self.body_height()
    }

    fn scrolledY(&self) -> usize {
        self.y - self.scrollY
    }

}

fn make_separator_content(reply: &ShowReplyItem) -> (String, String) {
    let now = Local::now();

    let replier_name = reply.username.clone();

    let published_at = reply.published_at.clone();

    let published_at_dt = match Local.datetime_from_str(&published_at, "%d/%m/%Y %H:%M") {
        Ok(v) => v,
        Err(e) => now,
    };
    let time = published_at_format(&(now - published_at_dt));
    (replier_name, time)
}

fn clean_reply_body(vec: &Vec<NodeType>) -> Vec<NodeType> {
    // clean up lines (end)
    let vec2 = {
        let vec_length = vec.len();
        let vec_check_cleanup = vec.clone();

        // check if last 4 elements match the EMPTY PATTERN
        let is_last4_empty = vec_check_cleanup.iter()
                                              .rev()
                                              .take(4)
                                              .enumerate()
                                              .all(|(j, node)| match node.clone() {
                                                  NodeType::Br(n) => j == 1 || j == 2 || j == 3,
                                                  NodeType::Text(n) => j == 0 && n.data.is_empty(),
                                                  _ => false,
                                              });

        let vec_short_length = if vec_length > 4 && is_last4_empty {
            vec_length - 4
        } else {
            vec_length
        };

        vec.iter().take(vec_short_length)
    };

    // clean up lines (start)
    let vec3 = {
        let vec2_cloned = vec2.clone();
        let mut result: Vec<NodeType> = Vec::new();
        for (j, node) in vec2_cloned.enumerate() {
            let node2 = node.clone();
            let node3 = node.clone();
            match node2 {
                NodeType::Br(n) => {
                    if !result.is_empty() {
                        result.push(node3);
                    }
                }
                _ => result.push(node3),
            }
        }
        result.clone()
    };

    vec3
}

fn make_separator_replier_name(separator_width: usize,
                               separator_padding: &str,
                               replier_max_width: usize,
                               replier_name: &str)
                               -> String {
    let replier_name_len = jks_len(&replier_name);
    let replier_name_spacing_width = replier_max_width - replier_name_len;
    let is_replier_name_spacing_width_odd = replier_name_spacing_width & 1 == 1;
    let replier_name_right_spacing_width = replier_name_spacing_width / 2;
    let replier_name_left_spacing_width = if is_replier_name_spacing_width_odd {
        replier_name_right_spacing_width + 1
    } else {
        replier_name_right_spacing_width
    };

    let replier_name_left_spacing = seq_str_gen(0, replier_name_left_spacing_width, "─", "");
    let replier_name_right_spacing = seq_str_gen(0, replier_name_right_spacing_width, "─", "");

    let separator_replier = format!("{}{}{}{}{}",
                                    "╭",
                                    replier_name_left_spacing,
                                    replier_name,
                                    replier_name_right_spacing,
                                    "");

    return separator_replier;
}

fn make_separator_time(separator_width: usize,
                       separator_padding: &str,
                       time_max_width: usize,
                       time: &str)
                       -> String {
    let time_len = jks_len(&time);
    let time_spacing_width = if time_max_width > time_len {
        time_max_width - time_len
    } else {
        0
    };

    let is_time_spacing_width_odd = time_spacing_width & 1 == 1;
    let time_right_spacing_width = time_spacing_width / 2;
    let time_left_spacing_width = if is_time_spacing_width_odd {
        time_right_spacing_width + 1
    } else {
        time_right_spacing_width
    };

    let time_left_spacing = seq_str_gen(0, time_left_spacing_width, "─", "");
    let time_right_spacing = seq_str_gen(0, time_right_spacing_width, "─", "");

    let separator_time = format!("{}{}{}{}{}",
                                 "",
                                 time_left_spacing,
                                 time,
                                 time_right_spacing,
                                 "╮");

    return separator_time;
}

fn make_separator_top(separator_width: usize,
                      separator_padding: &str,
                      replier_max_width: usize,
                      replier_name: &str,
                      time_max_width: usize,
                      time: &str)
                      -> String {

    let separator_replier = make_separator_replier_name(separator_width,
                                                        &separator_padding,
                                                        replier_max_width,
                                                        &replier_name);

    let separator_replier_width = jks_len(&separator_replier);

    let separator_time = make_separator_time(separator_width,
                                             &separator_padding,
                                             time_max_width,
                                             &time);

    let separator_time_width = jks_len(&separator_time);

    let separator_top_middle_width = if separator_width >=
                                        (separator_replier_width + separator_time_width) {
        separator_width - separator_replier_width - separator_time_width
    } else {
        0
    };

    let separator_top_middle = seq_str_gen(0, separator_top_middle_width, " ", "");
    let separator_top = format!("{}{}{}{}{}",
                                separator_padding,
                                separator_top_middle,
                                separator_replier,
                                separator_time,
                                separator_padding);
    return separator_top;
}

fn make_separator_bottom(separator_width: usize, separator_padding: &str) -> String {
    let style_box_width = 1;
    let separator_bottom_middle_width = if separator_width > style_box_width {
        separator_width - style_box_width
    } else {
        0
    };
    let separator_bottom_middle = seq_str_gen(0, separator_bottom_middle_width, "─", "");

    let separator_bottom = format!("{}{}{}{}",
                                   separator_padding,
                                   separator_bottom_middle,
                                   "╯",
                                   separator_padding);
    return separator_bottom;
}

fn published_at_format(duration: &Duration) -> String {
    let weeks = duration.num_weeks();
    let days = duration.num_days();
    let hours = duration.num_hours();
    let minutes = duration.num_minutes();

    if weeks > 0 {
        format!("{}w", weeks)
    } else if days > 0 {
        format!("{}d", days)
    } else if hours > 0 {
        format!("{}h", hours)
    } else if minutes > 0 {
        format!("{}m", minutes)
    } else {
        String::from("1m")
    }
}

fn seq_str_gen(start: usize, end: usize, sym: &str, join_sym: &str) -> String {
    (start..end).map(|_| sym.clone()).collect::<Vec<_>>().join(&join_sym)
}
<commit_msg>show - remove space in print_reply_line function<commit_after>extern crate termion;
extern crate chrono;

use termion::input::TermRead;
use termion::raw::IntoRawMode;
use termion::{color, style};
use termion::event::Key;
use termion::terminal_size;
use std::io::{Read, Write, Stdout, Stdin};
use std::io::{stdout, stdin};
use std;

use chrono::*;
use utility::string::*;
use model::ShowReplyItem;
use model::ShowItem;
use reply_model::*;
use screen::common::*;

pub struct Show {
    scrollY: usize,
    y: usize,
    replier_max_width: usize,
    time_max_width: usize,
    is_scroll_to_end: bool
}

impl Show {
    pub fn new() -> Self {
        Show {
            scrollY: 0,
            y: 0,
            replier_max_width: 14,
            time_max_width: 5,
            is_scroll_to_end: false
        }
    }
    pub fn print(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, title: &str, item: &ShowItem) {

        self.y = 2;

        self.print_header(stdout, &format!("{} - {} [{}/{}]",
                                   item.title,
                                   title,
                                   item.page,
                                   item.max_page));
        self.print_body(stdout, &item);
    }

    fn print_separator_top(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, reply: &ShowReplyItem) {
        if self.can_print() {
            let (replier_name, time) = make_separator_content(&reply);
            let s = self.build_separator_top(&replier_name, &time);
            self.print_separator_line(stdout, &s);
        }
    }

    fn print_separator_bottom(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>) {
        if self.can_print() {
            let s = self.build_separator_bottom();
            self.print_separator_line(stdout, &s);
        }
    }

    fn print_separator_line(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, s: &str) {

        write!(stdout, "{}{}{}{}{}{}",
                termion::cursor::Goto(1, (self.scrolledY() + 1) as u16),
                color::Fg(color::Green),
                color::Bg(color::Black),
                s,
                style::Reset,
                termion::cursor::Hide);
    }

    fn print_header(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, text: &str) {
        let title_len = jks_len(text);
        let w = terminal_size().unwrap().0 as usize;
        let padding = ((if w >= title_len {
            w - title_len
        } else {
            0
        }) / 2) as u16;

        let header_bottom = seq_str_gen(0, w, "─", "");

        write!(stdout, "{}{}{}{}{}{}{}",
                termion::cursor::Goto(padding + 1, 1),
                color::Fg(color::White),
                color::Bg(color::Black),
                style::Bold,
                text, style::Reset,
                termion::cursor::Hide);

        write!(stdout, "{}{}{}{}{}{}{}",
                termion::cursor::Goto(1, 2),
                color::Fg(color::Yellow),
                color::Bg(color::Black),
                style::Bold,
                header_bottom,
                style::Reset,
                termion::cursor::Hide);
    }

    pub fn print_body(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, item: &ShowItem) {
        let width = self.body_width();
        let rows = self.body_height();

        for (i, reply) in item.replies.iter().take(rows).enumerate() {

            self.print_reply(stdout, &reply.body, 0);

            self.print_separator_top(stdout, &reply);
            self.y += 1;

            self.print_separator_bottom(stdout);
            self.y += 1;
        }

        self.is_scroll_to_end = self.scrolledY() < self.body_height();
    }

    fn print_reply_line(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, s: String) {

       write!(stdout, "{}{}{}{}{}{}",
               termion::cursor::Goto(1, (self.scrolledY() + 1) as u16),
               color::Fg(color::White),
               color::Bg(color::Black),
               s,
               style::Reset,
               termion::cursor::Hide);
    }

    fn print_reply(&mut self, stdout: &mut termion::raw::RawTerminal<std::io::StdoutLock>, vec: &Vec<NodeType>, depth: usize) {

        let icon_width = 2;
        let clown = imgcat(&"data/img/clown.gif", icon_width);
        let padding = seq_str_gen(0, depth, "├─", "");
        let mut line = String::new();
        let mut is_first = true;

        let vec_clean = clean_reply_body(vec);
        for (j, node) in vec_clean.iter().enumerate() {
            match node.clone() {
                NodeType::Text(n) => {
                    if n.data != "" {
                        line = format!("{}{}", line, n.data);
                    }
                }
                NodeType::Image(n) => {
                    if n.data != "" {
                        if self.can_print() {

                            line = format!("{}{}",
                                    line,
                                    clown);
                        }
                    }
                }
                NodeType::BlockQuote(n) => {
                    self.print_reply(stdout, &n.data, depth + 1);
                    is_first = false;
                }
                NodeType::Br(n) => {
                    if !line.is_empty() {
                        if self.can_print() {
                            self.print_reply_line(stdout, format!(" {}{}", padding, line));
                        }
                        line = String::new();
                        is_first = false;
                    }

                    // prevent first line empty
                    if !is_first {
                        self.y += 1;
                    }

                }
            }
        }

        if !line.is_empty() {
            if self.can_print() {
                self.print_reply_line(stdout, format!(" {}{}", padding, line));
            }
            line = String::new();
            self.y += 1;
        }
    }

    fn build_separator_arguments(&mut self) -> (usize, usize, String) {
        let separator_width = self.body_width();
        let w = terminal_size().unwrap().0 as usize;

        let separator_padding_width = if w > separator_width {
            w - separator_width
        } else {
            0
        } / 2;

        let separator_padding = seq_str_gen(0, separator_padding_width, " ", "");

        (separator_width, separator_padding_width, separator_padding)
    }

    fn build_separator_top(&mut self, replier_name: &str, time: &str) -> String {
        let (separator_width, separator_padding_width, separator_padding) =
            self.build_separator_arguments();
        make_separator_top(separator_width,
                           &separator_padding,
                           self.replier_max_width,
                           &replier_name,
                           self.time_max_width,
                           &time)
    }

    fn build_separator_bottom(&mut self) -> String {
        let (separator_width, separator_padding_width, separator_padding) =
            self.build_separator_arguments();
        make_separator_bottom(separator_width, &separator_padding)
    }

    pub fn resetY(&mut self) {
        self.scrollY = 0;
    }

    pub fn scrollUp(&mut self, value: usize) -> bool {
        let tmp = self.scrollY;
        if tmp > value {
            self.scrollY = tmp - value;
            true
        } else if tmp != 0 {
            self.scrollY = 0;
            true
        } else {
            false
        }
    }

    pub fn scrollDown(&mut self, value: usize) -> bool {

        if !self.is_scroll_to_end {
            let min_to_scroll = self.scrollY + self.body_height();
            if self.y >= min_to_scroll + value {
                self.scrollY += value;
                return true;
            } else if self.y >= min_to_scroll {
                self.scrollY += self.y - min_to_scroll;
                return true;
            }
        }

        false
    }

    pub fn body_height(&self) -> usize {

        let h = terminal_size().unwrap().1;

        if h >= 3 {
            h as usize - 3
        } else {
            0
        }
    }

    pub fn body_width(&self) -> usize {

        let w = terminal_size().unwrap().0;

        if w >= 2 {
            w as usize - 2
        } else {
            0
        }
    }

    fn can_print(&self) -> bool {
        self.y > self.scrollY + 1 && self.y < self.scrollY + 1 + self.body_height()
    }

    fn scrolledY(&self) -> usize {
        self.y - self.scrollY
    }

}

fn make_separator_content(reply: &ShowReplyItem) -> (String, String) {
    let now = Local::now();

    let replier_name = reply.username.clone();

    let published_at = reply.published_at.clone();

    let published_at_dt = match Local.datetime_from_str(&published_at, "%d/%m/%Y %H:%M") {
        Ok(v) => v,
        Err(e) => now,
    };
    let time = published_at_format(&(now - published_at_dt));
    (replier_name, time)
}

fn clean_reply_body(vec: &Vec<NodeType>) -> Vec<NodeType> {
    // clean up lines (end)
    let vec2 = {
        let vec_length = vec.len();
        let vec_check_cleanup = vec.clone();

        // check if last 4 elements match the EMPTY PATTERN
        let is_last4_empty = vec_check_cleanup.iter()
                                              .rev()
                                              .take(4)
                                              .enumerate()
                                              .all(|(j, node)| match node.clone() {
                                                  NodeType::Br(n) => j == 1 || j == 2 || j == 3,
                                                  NodeType::Text(n) => j == 0 && n.data.is_empty(),
                                                  _ => false,
                                              });

        let vec_short_length = if vec_length > 4 && is_last4_empty {
            vec_length - 4
        } else {
            vec_length
        };

        vec.iter().take(vec_short_length)
    };

    // clean up lines (start)
    let vec3 = {
        let vec2_cloned = vec2.clone();
        let mut result: Vec<NodeType> = Vec::new();
        for (j, node) in vec2_cloned.enumerate() {
            let node2 = node.clone();
            let node3 = node.clone();
            match node2 {
                NodeType::Br(n) => {
                    if !result.is_empty() {
                        result.push(node3);
                    }
                }
                _ => result.push(node3),
            }
        }
        result.clone()
    };

    vec3
}

fn make_separator_replier_name(separator_width: usize,
                               separator_padding: &str,
                               replier_max_width: usize,
                               replier_name: &str)
                               -> String {
    let replier_name_len = jks_len(&replier_name);
    let replier_name_spacing_width = replier_max_width - replier_name_len;
    let is_replier_name_spacing_width_odd = replier_name_spacing_width & 1 == 1;
    let replier_name_right_spacing_width = replier_name_spacing_width / 2;
    let replier_name_left_spacing_width = if is_replier_name_spacing_width_odd {
        replier_name_right_spacing_width + 1
    } else {
        replier_name_right_spacing_width
    };

    let replier_name_left_spacing = seq_str_gen(0, replier_name_left_spacing_width, "─", "");
    let replier_name_right_spacing = seq_str_gen(0, replier_name_right_spacing_width, "─", "");

    let separator_replier = format!("{}{}{}{}{}",
                                    "╭",
                                    replier_name_left_spacing,
                                    replier_name,
                                    replier_name_right_spacing,
                                    "");

    return separator_replier;
}

fn make_separator_time(separator_width: usize,
                       separator_padding: &str,
                       time_max_width: usize,
                       time: &str)
                       -> String {
    let time_len = jks_len(&time);
    let time_spacing_width = if time_max_width > time_len {
        time_max_width - time_len
    } else {
        0
    };

    let is_time_spacing_width_odd = time_spacing_width & 1 == 1;
    let time_right_spacing_width = time_spacing_width / 2;
    let time_left_spacing_width = if is_time_spacing_width_odd {
        time_right_spacing_width + 1
    } else {
        time_right_spacing_width
    };

    let time_left_spacing = seq_str_gen(0, time_left_spacing_width, "─", "");
    let time_right_spacing = seq_str_gen(0, time_right_spacing_width, "─", "");

    let separator_time = format!("{}{}{}{}{}",
                                 "",
                                 time_left_spacing,
                                 time,
                                 time_right_spacing,
                                 "╮");

    return separator_time;
}

fn make_separator_top(separator_width: usize,
                      separator_padding: &str,
                      replier_max_width: usize,
                      replier_name: &str,
                      time_max_width: usize,
                      time: &str)
                      -> String {

    let separator_replier = make_separator_replier_name(separator_width,
                                                        &separator_padding,
                                                        replier_max_width,
                                                        &replier_name);

    let separator_replier_width = jks_len(&separator_replier);

    let separator_time = make_separator_time(separator_width,
                                             &separator_padding,
                                             time_max_width,
                                             &time);

    let separator_time_width = jks_len(&separator_time);

    let separator_top_middle_width = if separator_width >=
                                        (separator_replier_width + separator_time_width) {
        separator_width - separator_replier_width - separator_time_width
    } else {
        0
    };

    let separator_top_middle = seq_str_gen(0, separator_top_middle_width, " ", "");
    let separator_top = format!("{}{}{}{}{}",
                                separator_padding,
                                separator_top_middle,
                                separator_replier,
                                separator_time,
                                separator_padding);
    return separator_top;
}

fn make_separator_bottom(separator_width: usize, separator_padding: &str) -> String {
    let style_box_width = 1;
    let separator_bottom_middle_width = if separator_width > style_box_width {
        separator_width - style_box_width
    } else {
        0
    };
    let separator_bottom_middle = seq_str_gen(0, separator_bottom_middle_width, "─", "");

    let separator_bottom = format!("{}{}{}{}",
                                   separator_padding,
                                   separator_bottom_middle,
                                   "╯",
                                   separator_padding);
    return separator_bottom;
}

fn published_at_format(duration: &Duration) -> String {
    let weeks = duration.num_weeks();
    let days = duration.num_days();
    let hours = duration.num_hours();
    let minutes = duration.num_minutes();

    if weeks > 0 {
        format!("{}w", weeks)
    } else if days > 0 {
        format!("{}d", days)
    } else if hours > 0 {
        format!("{}h", hours)
    } else if minutes > 0 {
        format!("{}m", minutes)
    } else {
        String::from("1m")
    }
}

fn seq_str_gen(start: usize, end: usize, sym: &str, join_sym: &str) -> String {
    (start..end).map(|_| sym.clone()).collect::<Vec<_>>().join(&join_sym)
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate difference;
#[macro_use]
extern crate assert_cli;
#[macro_use]
extern crate lazy_static;

use std::env;
use std::str;
use std::path::{Path, PathBuf};

static EMPTY: &'static [&'static str] = &[];
lazy_static! {
    static ref _CWD: PathBuf = env::current_dir().unwrap();
    static ref CWD: &'static Path = _CWD.as_path();
    // TODO test on release
    static ref _BIN: PathBuf = CWD.join("target/debug/cobalt");
    static ref BIN: &'static str = _BIN.to_str().unwrap();
}

macro_rules! assert_contains {
    ($utf8: expr, $vec: expr) => {
        let text = str::from_utf8($utf8).unwrap();
        println!("{}", text);
        assert!(text.contains($vec))
    }
}

macro_rules! assert_contains_not {
    ($utf8: expr, $vec: expr) => {
        let text = str::from_utf8($utf8).unwrap();
        println!("{}", text);
        assert!(!text.contains($vec))
    }
}

#[test]
pub fn invalid_calls() {
    println!("Binary: {:?}", BIN.to_owned());
    let output = assert_cli!(&BIN, EMPTY => Error 1).unwrap();
    assert_contains!(&output.stderr, "requires a subcommand");

    let output = assert_cli!(&BIN, &["--nonexistent-argument"] => Error 1).unwrap();
    assert_contains!(&output.stderr,
                     r"Found argument '--nonexistent-argument' which wasn't expected");
}

#[test]
pub fn log_levels() {
    env::set_current_dir(CWD.join("tests/fixtures/example")).unwrap();

    let output1 = assert_cli!(&BIN, &["build", "--trace"] => Success).unwrap();
    let output1_stderr = str::from_utf8(&output1.stderr).to_owned().unwrap();
    assert_contains!(&output1.stderr, "[trace]");
    assert_contains!(&output1.stderr, "[debug]");
    assert_contains!(&output1.stderr, "[info]");

    let output2 = assert_cli!(&BIN, &["build", "-L", "trace"] => Success).unwrap();
    let output2_stderr = str::from_utf8(&output2.stderr).to_owned().unwrap();
    assert_diff!(&output1_stderr, &output2_stderr, " ", 0);

    let output = assert_cli!(&BIN, &["build", "-L", "debug"] => Success).unwrap();
    assert_contains_not!(&output.stderr, "[trace]");
    assert_contains!(&output.stderr, "[debug]");
    assert_contains!(&output.stderr, "[info]");

    let output = assert_cli!(&BIN, &["build", "-L", "info"] => Success).unwrap();
    assert_contains_not!(&output.stderr, "[trace]");
    assert_contains_not!(&output.stderr, "[debug]");
    assert_contains!(&output.stderr, "[info]");

    assert_cli!(&BIN, &["build", "--silent"] => Success, "").unwrap();
}

#[test]
pub fn clean() {
    env::set_current_dir(CWD.join("tests/fixtures/example")).unwrap();
    assert_cli!(&BIN, &["build", "-d", "./test_dest"] => Success).unwrap();
    assert_eq!(Path::new("./test_dest/").is_dir(), true);

    let output = assert_cli!(&BIN, &["clean", "-d", "./test_dest"] => Success).unwrap();
    assert_eq!(Path::new("./test_dest").is_dir(), false);
    assert_contains!(&output.stderr, "directory \"./test_dest\" removed");
}

#[cfg(not(windows))]
#[test]
pub fn clean_warning() {
    env::set_current_dir(CWD.join("tests/fixtures/example")).unwrap();
    let output = assert_cli!(&BIN, &["clean"] => Error 1).unwrap();
    assert_contains!(&output.stderr,
                     "Destination directory is same as current directory. Cancelling the \
                      operation");
}
<commit_msg>fix(tests): Harden CLI tests<commit_after>#[macro_use]
extern crate assert_cli;
#[macro_use]
extern crate lazy_static;
extern crate tempdir;

use std::env;
use std::str;
use std::path::{Path, PathBuf};

use tempdir::TempDir;

static EMPTY: &'static [&'static str] = &[];
lazy_static! {
    static ref _CWD: PathBuf = env::current_dir().unwrap();
    static ref CWD: &'static Path = _CWD.as_path();
    // TODO test on release
    static ref _BIN: PathBuf = CWD.join("target/debug/cobalt");
    static ref BIN: &'static str = _BIN.to_str().unwrap();
}

macro_rules! assert_contains {
    ($utf8: expr, $vec: expr) => {
        let text = str::from_utf8($utf8).unwrap();
        println!("{}", text);
        assert!(text.contains($vec))
    }
}

macro_rules! assert_contains_not {
    ($utf8: expr, $vec: expr) => {
        let text = str::from_utf8($utf8).unwrap();
        println!("{}", text);
        assert!(!text.contains($vec))
    }
}

#[test]
pub fn invalid_calls() {
    println!("Binary: {:?}", BIN.to_owned());
    let output = assert_cli!(&BIN, EMPTY => Error 1).unwrap();
    assert_contains!(&output.stderr, "requires a subcommand");

    let output = assert_cli!(&BIN, &["--nonexistent-argument"] => Error 1).unwrap();
    assert_contains!(&output.stderr,
                     r"Found argument '--nonexistent-argument' which wasn't expected");
}

#[test]
pub fn log_levels_trace() {
    env::set_current_dir(CWD.join("tests/fixtures/example")).unwrap();

    let destdir = TempDir::new("trace").expect("Tempdir not created");
    let dest_param = destdir
        .path()
        .to_str()
        .expect("Can't convert destdir to str")
        .to_owned();

    let output1 = assert_cli!(&BIN, &["build", "-L", "trace", "-d", &dest_param] => Success)
        .unwrap();
    assert_contains!(&output1.stderr, "[trace]");
    assert_contains!(&output1.stderr, "[debug]");
    assert_contains!(&output1.stderr, "[info]");

    destdir.close().unwrap();
}

#[test]
pub fn log_levels_trace_alias() {
    env::set_current_dir(CWD.join("tests/fixtures/example")).unwrap();

    let destdir = TempDir::new("trace_alias").expect("Tempdir not created");
    let dest_param = destdir
        .path()
        .to_str()
        .expect("Can't convert destdir to str")
        .to_owned();

    let output1 = assert_cli!(&BIN, &["build", "--trace", "-d", &dest_param] => Success).unwrap();
    assert_contains!(&output1.stderr, "[trace]");
    assert_contains!(&output1.stderr, "[debug]");
    assert_contains!(&output1.stderr, "[info]");

    destdir.close().unwrap();
}

#[test]
pub fn log_levels_debug() {
    env::set_current_dir(CWD.join("tests/fixtures/example")).unwrap();

    let destdir = TempDir::new("debug").expect("Tempdir not created");
    let dest_param = destdir
        .path()
        .to_str()
        .expect("Can't convert destdir to str")
        .to_owned();

    let output = assert_cli!(&BIN, &["build", "-L", "debug", "-d", &dest_param] => Success)
        .unwrap();
    assert_contains_not!(&output.stderr, "[trace]");
    assert_contains!(&output.stderr, "[debug]");
    assert_contains!(&output.stderr, "[info]");

    destdir.close().unwrap();
}

#[test]
pub fn log_levels_info() {
    env::set_current_dir(CWD.join("tests/fixtures/example")).unwrap();

    let destdir = TempDir::new("info").expect("Tempdir not created");
    let dest_param = destdir
        .path()
        .to_str()
        .expect("Can't convert destdir to str")
        .to_owned();

    let output = assert_cli!(&BIN, &["build", "-L", "info", "-d", &dest_param] => Success).unwrap();
    assert_contains_not!(&output.stderr, "[trace]");
    assert_contains_not!(&output.stderr, "[debug]");
    assert_contains!(&output.stderr, "[info]");

    destdir.close().unwrap();
}

#[test]
pub fn log_levels_silent() {
    env::set_current_dir(CWD.join("tests/fixtures/example")).unwrap();

    let destdir = TempDir::new("silent").expect("Tempdir not created");
    let dest_param = destdir
        .path()
        .to_str()
        .expect("Can't convert destdir to str")
        .to_owned();

    assert_cli!(&BIN, &["build", "--silent", "-d", &dest_param] => Success, "").unwrap();

    destdir.close().unwrap();
}

#[test]
pub fn clean() {
    env::set_current_dir(CWD.join("tests/fixtures/example")).unwrap();

    let destdir = TempDir::new("clean").expect("Tempdir not created");
    let dest_param = destdir
        .path()
        .to_str()
        .expect("Can't convert destdir to str")
        .to_owned();

    assert_cli!(&BIN, &["build", "-d", &dest_param] => Success).unwrap();
    assert_eq!(destdir.path().is_dir(), true);

    assert_cli!(&BIN, &["clean", "-d", &dest_param] => Success).unwrap();
    assert_eq!(destdir.path().is_dir(), false);
}

#[cfg(not(windows))]
#[test]
pub fn clean_warning() {
    env::set_current_dir(CWD.join("tests/fixtures/example")).unwrap();
    let output = assert_cli!(&BIN, &["clean"] => Error 1).unwrap();
    assert_contains!(&output.stderr,
                     "Destination directory is same as current directory. Cancelling the \
                      operation");
}
<|endoftext|>


<commit_before>
extern crate metl;
extern crate cocoa;

use cocoa::base::{BOOL, nil};
use cocoa::foundation::NSString;
use metl::{CompileOptions, DepthStencilDescriptor, Device, FeatureSet, LanguageVersion, PixelFormat, SpecificLanguageVersion,
           SamplerDescriptor, TextureDescriptor};
use metl::LibraryError;
use metl::{FromRaw, FromRawError, IntoRaw};
use metl::sys::{MTLCompileOptions, MTLLanguageVersion};

#[test]
fn get_device() {
    let device = Device::system_default_device();
    assert!(device.is_ok());
}

#[test]
fn get_all_devices() {
    let all_devices = Device::enumerate_all_system_devices();
    assert!(!all_devices.is_empty());
    for device in all_devices {
        assert!(device.is_ok());
    }
}

#[test]
fn get_device_name() {
    let device = Device::system_default_device().unwrap();
    assert!(!device.name().is_empty());
}

#[cfg(target_os = "macos")]
#[test]
fn device_supports_base_features() {
    let base_osx_feature_set = FeatureSet::OsxGpuFamily1_v1;
    let device = Device::system_default_device().unwrap();
    assert!(device.supports_feature_set(base_osx_feature_set));
}

#[test]
fn set_get_command_queue_label() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();

    const DUMMY_COMMAND_QUEUE_NAME: &'static str = "foo";
    command_queue.set_label(&DUMMY_COMMAND_QUEUE_NAME);

    assert_eq!(command_queue.label(), DUMMY_COMMAND_QUEUE_NAME);
}

#[test]
fn insert_debug_capture_boundary_on_command_queue() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();
    command_queue.insert_debug_capture_boundary();
    assert!(true);
}

#[test]
fn device_from_to_raw() {
    let device = Device::system_default_device().unwrap();
    let raw = device.into_raw();
    let device = Device::from_raw(raw);
    assert!(device.is_ok());
}

#[test]
fn device_from_wrong_type() {
    let some_string = unsafe { NSString::alloc(nil).init_str("Hello") };
    let device_result = Device::from_raw(some_string);
    println!("{}", device_result.is_ok());
    match device_result {
        Result::Err(FromRawError::WrongPointerType) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn device_from_nullptr() {
    let device_result = Device::from_raw(nil);
    match device_result {
        Result::Err(FromRawError::NilPointer) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn compile_opts_creation_is_correct() {
    let fast_math_enabled = true;
    let options =
        CompileOptions::default()
            .fast_math_enabled(fast_math_enabled)
            .language_version(LanguageVersion::Specific(SpecificLanguageVersion::Version_1_0))
            .with_macro("Foo", 54)
            .with_macro("Bar", 32.0)
            .with_macro("Baz", "Hi")
            .mtl_compile_options();

    unsafe {
        assert_eq!(fast_math_enabled as BOOL, options.fastMathEnabled());
        assert_eq!(options.languageVersion(),
                   MTLLanguageVersion::MTLLanguageVersion1_0);
    }
}

#[test]
#[allow(unused_variables)]
fn create_sampler_and_set_label() {
    const SAMPLER_LABEL: &'static str = "ExampleSampler";
    let mut device = Device::system_default_device().unwrap();

    let mut sampler_descriptor = SamplerDescriptor::new();
    sampler_descriptor.set_label(&SAMPLER_LABEL);
    assert_eq!(sampler_descriptor.label(), SAMPLER_LABEL);

    let sampler = device.new_sampler_state(&sampler_descriptor).unwrap();
    // TODO(burtonageo): Fix getting the label
    // assert_eq!(sampler.label(), sampler_descriptor.label());
}

#[test]
fn create_depth_stencil_state() {
    const DEPTH_STENCIL_LABEL: &'static str = "ExampleDepthStencil";
    let mut device = Device::system_default_device().unwrap();

    let mut depth_stencil_descriptor = DepthStencilDescriptor::new();
    depth_stencil_descriptor.set_label(&DEPTH_STENCIL_LABEL);
    assert_eq!(depth_stencil_descriptor.label(), DEPTH_STENCIL_LABEL);

    let depth_stencil = device.new_depth_stencil_state(&depth_stencil_descriptor).unwrap();
    // TODO(burtonageo): Fix getting the label
    // assert_eq!(depth_stencil.label(), depth_stencil_descriptor.label());
}

#[test]
fn create_texture() {
    const PIX_FORMAT: PixelFormat = PixelFormat::Rgba8UnormSrgb;
    const TEX_DIMS: (usize, usize) = (600, 800);
    const MIPPED: bool = false;

    let mut device = Device::system_default_device().unwrap();
    let tex_descriptor = TextureDescriptor::new_2d(PIX_FORMAT, TEX_DIMS.0, TEX_DIMS.1, MIPPED);
    let texture = device.new_texture(&tex_descriptor).unwrap();

    assert_eq!(texture.pixel_format(), PIX_FORMAT);
    assert_eq!(texture.width(), TEX_DIMS.0);
    assert_eq!(texture.height(), TEX_DIMS.1);
    assert_eq!(texture.texture_type(), metl::TextureType::Type2D);
}

#[test]
fn create_invalid_shader() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"abcdefghijklmnopqrstuvwxyz";
    match device.new_library_with_source(&BAD_SHADER, &Default::default()) {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(LibraryError::SourceError(_)) => assert!(true),
        Err(_) => panic!("Incorrect error type")
    }
}

#[test]
fn create_invalid_shader_async() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"FooBarBaz";
    match device.new_library_with_source_async(&BAD_SHADER, &Default::default()).recv().unwrap() {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(LibraryError::SourceError(_)) => assert!(true),
        Err(_) => panic!("Incorrect error type")
    }
}

// Shader source taken from http://metalbyexample.com/up-and-running-2/
const SHADER: &'static str = r"
using namespace metal;

struct ColoredVertex
{
    float4 position [[position]];
    float4 color;
};

vertex ColoredVertex vertex_main(constant float4 *position [[buffer(0)]],
                                 constant float4 *color [[buffer(1)]],
                                 uint vid [[vertex_id]])
{
    ColoredVertex vert;
    vert.position = position[vid];
    vert.color = color[vid];
    return vert;
}

fragment float4 fragment_main(ColoredVertex vert [[stage_in]])
{
    return vert.color;
}
";

#[test]
fn device_create_library_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    let library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}

#[test]
#[ignore]
fn device_create_library_async_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    let library = device.new_library_with_source_async(&SHADER, &Default::default())
                        .recv()
                        .unwrap()
                        .unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}

#[test]
fn shader_get_function_with_name() {
    let mut device = Device::system_default_device().unwrap();
    let mut library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let function = library.new_function_with_name(&"fragment_main");
    assert!(function.is_some());
}

#[test]
#[allow(unused_imports, unused_variables)]
#[ignore]
fn shader_get_struct_info() {
    use metl::{StructMember, StructType};
    let mut device = Device::system_default_device().unwrap();
    let mut library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let function = library.new_function_with_name(&"fragment_main").unwrap();
    unimplemented!();
}
<commit_msg>Remove dead comments<commit_after>
extern crate metl;
extern crate cocoa;

use cocoa::base::{BOOL, nil};
use cocoa::foundation::NSString;
use metl::{CompileOptions, DepthStencilDescriptor, Device, FeatureSet, LanguageVersion, PixelFormat, SpecificLanguageVersion,
           SamplerDescriptor, TextureDescriptor};
use metl::LibraryError;
use metl::{FromRaw, FromRawError, IntoRaw};
use metl::sys::{MTLCompileOptions, MTLLanguageVersion};

#[test]
fn get_device() {
    let device = Device::system_default_device();
    assert!(device.is_ok());
}

#[test]
fn get_all_devices() {
    let all_devices = Device::enumerate_all_system_devices();
    assert!(!all_devices.is_empty());
    for device in all_devices {
        assert!(device.is_ok());
    }
}

#[test]
fn get_device_name() {
    let device = Device::system_default_device().unwrap();
    assert!(!device.name().is_empty());
}

#[cfg(target_os = "macos")]
#[test]
fn device_supports_base_features() {
    let base_osx_feature_set = FeatureSet::OsxGpuFamily1_v1;
    let device = Device::system_default_device().unwrap();
    assert!(device.supports_feature_set(base_osx_feature_set));
}

#[test]
fn set_get_command_queue_label() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();

    const DUMMY_COMMAND_QUEUE_NAME: &'static str = "foo";
    command_queue.set_label(&DUMMY_COMMAND_QUEUE_NAME);

    assert_eq!(command_queue.label(), DUMMY_COMMAND_QUEUE_NAME);
}

#[test]
fn insert_debug_capture_boundary_on_command_queue() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();
    command_queue.insert_debug_capture_boundary();
    assert!(true);
}

#[test]
fn device_from_to_raw() {
    let device = Device::system_default_device().unwrap();
    let raw = device.into_raw();
    let device = Device::from_raw(raw);
    assert!(device.is_ok());
}

#[test]
fn device_from_wrong_type() {
    let some_string = unsafe { NSString::alloc(nil).init_str("Hello") };
    let device_result = Device::from_raw(some_string);
    println!("{}", device_result.is_ok());
    match device_result {
        Result::Err(FromRawError::WrongPointerType) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn device_from_nullptr() {
    let device_result = Device::from_raw(nil);
    match device_result {
        Result::Err(FromRawError::NilPointer) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn compile_opts_creation_is_correct() {
    let fast_math_enabled = true;
    let options =
        CompileOptions::default()
            .fast_math_enabled(fast_math_enabled)
            .language_version(LanguageVersion::Specific(SpecificLanguageVersion::Version_1_0))
            .with_macro("Foo", 54)
            .with_macro("Bar", 32.0)
            .with_macro("Baz", "Hi")
            .mtl_compile_options();

    unsafe {
        assert_eq!(fast_math_enabled as BOOL, options.fastMathEnabled());
        assert_eq!(options.languageVersion(),
                   MTLLanguageVersion::MTLLanguageVersion1_0);
    }
}

#[test]
#[allow(unused_variables)]
fn create_sampler_and_set_label() {
    const SAMPLER_LABEL: &'static str = "ExampleSampler";
    let mut device = Device::system_default_device().unwrap();

    let mut sampler_descriptor = SamplerDescriptor::new();
    sampler_descriptor.set_label(&SAMPLER_LABEL);
    assert_eq!(sampler_descriptor.label(), SAMPLER_LABEL);

    let sampler = device.new_sampler_state(&sampler_descriptor).unwrap();
    assert_eq!(sampler.label(), sampler_descriptor.label());
}

#[test]
fn create_depth_stencil_state() {
    const DEPTH_STENCIL_LABEL: &'static str = "ExampleDepthStencil";
    let mut device = Device::system_default_device().unwrap();

    let mut depth_stencil_descriptor = DepthStencilDescriptor::new();
    depth_stencil_descriptor.set_label(&DEPTH_STENCIL_LABEL);
    assert_eq!(depth_stencil_descriptor.label(), DEPTH_STENCIL_LABEL);

    let depth_stencil = device.new_depth_stencil_state(&depth_stencil_descriptor).unwrap();
    assert_eq!(depth_stencil.label(), depth_stencil_descriptor.label());
}

#[test]
fn create_texture() {
    const PIX_FORMAT: PixelFormat = PixelFormat::Rgba8UnormSrgb;
    const TEX_DIMS: (usize, usize) = (600, 800);
    const MIPPED: bool = false;

    let mut device = Device::system_default_device().unwrap();
    let tex_descriptor = TextureDescriptor::new_2d(PIX_FORMAT, TEX_DIMS.0, TEX_DIMS.1, MIPPED);
    let texture = device.new_texture(&tex_descriptor).unwrap();

    assert_eq!(texture.pixel_format(), PIX_FORMAT);
    assert_eq!(texture.width(), TEX_DIMS.0);
    assert_eq!(texture.height(), TEX_DIMS.1);
    assert_eq!(texture.texture_type(), metl::TextureType::Type2D);
}

#[test]
fn create_invalid_shader() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"abcdefghijklmnopqrstuvwxyz";
    match device.new_library_with_source(&BAD_SHADER, &Default::default()) {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(LibraryError::SourceError(_)) => assert!(true),
        Err(_) => panic!("Incorrect error type")
    }
}

#[test]
fn create_invalid_shader_async() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"FooBarBaz";
    match device.new_library_with_source_async(&BAD_SHADER, &Default::default()).recv().unwrap() {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(LibraryError::SourceError(_)) => assert!(true),
        Err(_) => panic!("Incorrect error type")
    }
}

// Shader source taken from http://metalbyexample.com/up-and-running-2/
const SHADER: &'static str = r"
using namespace metal;

struct ColoredVertex
{
    float4 position [[position]];
    float4 color;
};

vertex ColoredVertex vertex_main(constant float4 *position [[buffer(0)]],
                                 constant float4 *color [[buffer(1)]],
                                 uint vid [[vertex_id]])
{
    ColoredVertex vert;
    vert.position = position[vid];
    vert.color = color[vid];
    return vert;
}

fragment float4 fragment_main(ColoredVertex vert [[stage_in]])
{
    return vert.color;
}
";

#[test]
fn device_create_library_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    let library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}

#[test]
#[ignore]
fn device_create_library_async_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    let library = device.new_library_with_source_async(&SHADER, &Default::default())
                        .recv()
                        .unwrap()
                        .unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}

#[test]
fn shader_get_function_with_name() {
    let mut device = Device::system_default_device().unwrap();
    let mut library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let function = library.new_function_with_name(&"fragment_main");
    assert!(function.is_some());
}

#[test]
#[allow(unused_imports, unused_variables)]
#[ignore]
fn shader_get_struct_info() {
    use metl::{StructMember, StructType};
    let mut device = Device::system_default_device().unwrap();
    let mut library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let function = library.new_function_with_name(&"fragment_main").unwrap();
    unimplemented!();
}
<|endoftext|>


<commit_before>extern crate multiaddr;
extern crate data_encoding;

use data_encoding::hex;
use multiaddr::*;
use std::net::{SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr};

#[test]
fn protocol_to_code() {
    assert_eq!(Protocol::IP4 as usize, 4);
}

#[test]
fn protocol_to_name() {
    assert_eq!(Protocol::TCP.to_string(), "tcp");
}

fn assert_bytes(source: &str, target: &str, protocols: Vec<Protocol>) -> () {
    let address = source.parse::<Multiaddr>().unwrap();
    assert_eq!(hex::encode(address.to_bytes().as_slice()), target);
    assert_eq!(address.iter().map(|addr| addr.protocol_id()).collect::<Vec<_>>(), protocols);
}
fn ma_valid(source: &str, target: &str, protocols: Vec<Protocol>) -> () {
    assert_bytes(source, target, protocols);
    assert_eq!(source.parse::<Multiaddr>().unwrap().to_string(), source);
}

#[test]
fn multiaddr_eq() {
    let m1 = "/ip4/127.0.0.1/udp/1234".parse::<Multiaddr>().unwrap();
    let m2 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap();
    let m3 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap();

    assert_ne!(m1, m2);
    assert_ne!(m2, m1);
    assert_eq!(m2, m3);
    assert_eq!(m1, m1);
}

#[test]
fn construct_success() {
    use Protocol::*;

    ma_valid("/ip4/1.2.3.4", "0401020304", vec![IP4]);
    ma_valid("/ip4/0.0.0.0", "0400000000", vec![IP4]);
    ma_valid("/ip6/::1", "2900000000000000000000000000000001", vec![IP6]);
    ma_valid("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21",
             "29260100094F819700803ECA6566E80C21",
             vec![IP6]);
    ma_valid("/udp/0", "110000", vec![UDP]);
    ma_valid("/tcp/0", "060000", vec![TCP]);
    ma_valid("/sctp/0", "84010000", vec![SCTP]);
    ma_valid("/udp/1234", "1104D2", vec![UDP]);
    ma_valid("/tcp/1234", "0604D2", vec![TCP]);
    ma_valid("/sctp/1234", "840104D2", vec![SCTP]);
    ma_valid("/udp/65535", "11FFFF", vec![UDP]);
    ma_valid("/tcp/65535", "06FFFF", vec![TCP]);
    ma_valid("/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![IPFS]);
    ma_valid("/udp/1234/sctp/1234", "1104D2840104D2", vec![UDP, SCTP]);
    ma_valid("/udp/1234/udt", "1104D2AD02", vec![UDP, UDT]);
    ma_valid("/udp/1234/utp", "1104D2AE02", vec![UDP, UTP]);
    ma_valid("/tcp/1234/http", "0604D2E003", vec![TCP, HTTP]);
    ma_valid("/tcp/1234/https", "0604D2BB03", vec![TCP, HTTPS]);
    ma_valid("/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
             "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2",
             vec![IPFS, TCP]);
    ma_valid("/ip4/127.0.0.1/udp/1234",
             "047F0000011104D2",
             vec![IP4, UDP]);
    ma_valid("/ip4/127.0.0.1/udp/0", "047F000001110000", vec![IP4, UDP]);
    ma_valid("/ip4/127.0.0.1/tcp/1234",
             "047F0000010604D2",
             vec![IP4, TCP]);
    ma_valid("/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![IP4, IPFS]);
    ma_valid("/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
             "047F000001A503221220D52EBB89D85B02A284948203A\
62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2",
             vec![IP4, IPFS, TCP]);
    // /unix/a/b/c/d/e,
    // /unix/stdio,
    // /ip4/1.2.3.4/tcp/80/unix/a/b/c/d/e/f,
    // /ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234/unix/stdio
    ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:\
              7095/tcp/8000/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "29200108A07AC542013AC986FFFE317095061F40DD03A5\
03221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![IP6, TCP, WS, IPFS]);
    ma_valid("/p2p-webrtc-star/ip4/127.0.0.\
              1/tcp/9090/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "9302047F000001062382DD03A503221220D52EBB89D85B\
02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![Libp2pWebrtcStar, IP4, TCP, WS, IPFS]);
    ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:\
              7095/tcp/8000/wss/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "29200108A07AC542013AC986FFFE317095061F40DE03A503221220D52EBB8\
9D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![IP6, TCP, WSS, IPFS]);
    ma_valid("/ip4/127.0.0.1/tcp/9090/p2p-circuit/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "047F000001062382A202A503221220D52EBB89D85B\
02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![IP4, TCP, P2pCircuit, IPFS]);
}

#[test]
fn construct_fail() {
    let addresses = ["/ip4",
                     "/ip4/::1",
                     "/ip4/fdpsofodsajfdoisa",
                     "/ip6",
                     "/udp",
                     "/tcp",
                     "/sctp",
                     "/udp/65536",
                     "/tcp/65536",
                     // "/onion/9imaq4ygg2iegci7:80",
                     // "/onion/aaimaq4ygg2iegci7:80",
                     // "/onion/timaq4ygg2iegci7:0",
                     // "/onion/timaq4ygg2iegci7:-1",
                     // "/onion/timaq4ygg2iegci7",
                     // "/onion/timaq4ygg2iegci@:666",
                     "/udp/1234/sctp",
                     "/udp/1234/udt/1234",
                     "/udp/1234/utp/1234",
                     "/ip4/127.0.0.1/udp/jfodsajfidosajfoidsa",
                     "/ip4/127.0.0.1/udp",
                     "/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa",
                     "/ip4/127.0.0.1/tcp",
                     "/ip4/127.0.0.1/ipfs",
                     "/ip4/127.0.0.1/ipfs/tcp",
                     "/p2p-circuit/50"];

    for address in &addresses {
        assert!(address.parse::<Multiaddr>().is_err(), address.to_string());
    }
}

#[test]
fn to_multiaddr() {
    assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_multiaddr().unwrap(),
               "/ip4/127.0.0.1".parse::<Multiaddr>().unwrap());
    assert_eq!(Ipv6Addr::new(0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21)
                   .to_multiaddr()
                   .unwrap(),
               "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse::<Multiaddr>().unwrap());
    assert_eq!("/ip4/127.0.0.1/tcp/1234".to_string().to_multiaddr().unwrap(),
               "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap());
    assert_eq!("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".to_multiaddr().unwrap(),
               "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse::<Multiaddr>().unwrap());
    assert_eq!(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 1234).to_multiaddr().unwrap(),
               "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap());
    assert_eq!(SocketAddrV6::new(Ipv6Addr::new(0x2601,
                                               0x9,
                                               0x4f81,
                                               0x9700,
                                               0x803e,
                                               0xca65,
                                               0x66e8,
                                               0xc21),
                                 1234,
                                 0,
                                 0)
                   .to_multiaddr()
                   .unwrap(),
               "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21/tcp/1234".parse::<Multiaddr>().unwrap());
}
<commit_msg>Add test for from_bytes<commit_after>extern crate multiaddr;
extern crate data_encoding;

use data_encoding::hex;
use multiaddr::*;
use std::net::{SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr};

#[test]
fn protocol_to_code() {
    assert_eq!(Protocol::IP4 as usize, 4);
}

#[test]
fn protocol_to_name() {
    assert_eq!(Protocol::TCP.to_string(), "tcp");
}

fn ma_valid(source: &str, target: &str, protocols: Vec<Protocol>) {
    let parsed = source.parse::<Multiaddr>().unwrap();
    assert_eq!(hex::encode(parsed.to_bytes().as_slice()), target);
    assert_eq!(parsed.iter().map(|addr| addr.protocol_id()).collect::<Vec<_>>(), protocols);
    assert_eq!(source.parse::<Multiaddr>().unwrap().to_string(), source);
    assert_eq!(Multiaddr::from_bytes(hex::decode(target.as_bytes()).unwrap()).unwrap(), parsed);
}

#[test]
fn multiaddr_eq() {
    let m1 = "/ip4/127.0.0.1/udp/1234".parse::<Multiaddr>().unwrap();
    let m2 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap();
    let m3 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap();

    assert_ne!(m1, m2);
    assert_ne!(m2, m1);
    assert_eq!(m2, m3);
    assert_eq!(m1, m1);
}

#[test]
fn construct_success() {
    use Protocol::*;

    ma_valid("/ip4/1.2.3.4", "0401020304", vec![IP4]);
    ma_valid("/ip4/0.0.0.0", "0400000000", vec![IP4]);
    ma_valid("/ip6/::1", "2900000000000000000000000000000001", vec![IP6]);
    ma_valid("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21",
             "29260100094F819700803ECA6566E80C21",
             vec![IP6]);
    ma_valid("/udp/0", "110000", vec![UDP]);
    ma_valid("/tcp/0", "060000", vec![TCP]);
    ma_valid("/sctp/0", "84010000", vec![SCTP]);
    ma_valid("/udp/1234", "1104D2", vec![UDP]);
    ma_valid("/tcp/1234", "0604D2", vec![TCP]);
    ma_valid("/sctp/1234", "840104D2", vec![SCTP]);
    ma_valid("/udp/65535", "11FFFF", vec![UDP]);
    ma_valid("/tcp/65535", "06FFFF", vec![TCP]);
    ma_valid("/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![IPFS]);
    ma_valid("/udp/1234/sctp/1234", "1104D2840104D2", vec![UDP, SCTP]);
    ma_valid("/udp/1234/udt", "1104D2AD02", vec![UDP, UDT]);
    ma_valid("/udp/1234/utp", "1104D2AE02", vec![UDP, UTP]);
    ma_valid("/tcp/1234/http", "0604D2E003", vec![TCP, HTTP]);
    ma_valid("/tcp/1234/https", "0604D2BB03", vec![TCP, HTTPS]);
    ma_valid("/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
             "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2",
             vec![IPFS, TCP]);
    ma_valid("/ip4/127.0.0.1/udp/1234",
             "047F0000011104D2",
             vec![IP4, UDP]);
    ma_valid("/ip4/127.0.0.1/udp/0", "047F000001110000", vec![IP4, UDP]);
    ma_valid("/ip4/127.0.0.1/tcp/1234",
             "047F0000010604D2",
             vec![IP4, TCP]);
    ma_valid("/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![IP4, IPFS]);
    ma_valid("/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
             "047F000001A503221220D52EBB89D85B02A284948203A\
62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2",
             vec![IP4, IPFS, TCP]);
    // /unix/a/b/c/d/e,
    // /unix/stdio,
    // /ip4/1.2.3.4/tcp/80/unix/a/b/c/d/e/f,
    // /ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234/unix/stdio
    ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:\
              7095/tcp/8000/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "29200108A07AC542013AC986FFFE317095061F40DD03A5\
03221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![IP6, TCP, WS, IPFS]);
    ma_valid("/p2p-webrtc-star/ip4/127.0.0.\
              1/tcp/9090/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "9302047F000001062382DD03A503221220D52EBB89D85B\
02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![Libp2pWebrtcStar, IP4, TCP, WS, IPFS]);
    ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:\
              7095/tcp/8000/wss/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "29200108A07AC542013AC986FFFE317095061F40DE03A503221220D52EBB8\
9D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![IP6, TCP, WSS, IPFS]);
    ma_valid("/ip4/127.0.0.1/tcp/9090/p2p-circuit/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
             "047F000001062382A202A503221220D52EBB89D85B\
02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
             vec![IP4, TCP, P2pCircuit, IPFS]);
}

#[test]
fn construct_fail() {
    let addresses = ["/ip4",
                     "/ip4/::1",
                     "/ip4/fdpsofodsajfdoisa",
                     "/ip6",
                     "/udp",
                     "/tcp",
                     "/sctp",
                     "/udp/65536",
                     "/tcp/65536",
                     // "/onion/9imaq4ygg2iegci7:80",
                     // "/onion/aaimaq4ygg2iegci7:80",
                     // "/onion/timaq4ygg2iegci7:0",
                     // "/onion/timaq4ygg2iegci7:-1",
                     // "/onion/timaq4ygg2iegci7",
                     // "/onion/timaq4ygg2iegci@:666",
                     "/udp/1234/sctp",
                     "/udp/1234/udt/1234",
                     "/udp/1234/utp/1234",
                     "/ip4/127.0.0.1/udp/jfodsajfidosajfoidsa",
                     "/ip4/127.0.0.1/udp",
                     "/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa",
                     "/ip4/127.0.0.1/tcp",
                     "/ip4/127.0.0.1/ipfs",
                     "/ip4/127.0.0.1/ipfs/tcp",
                     "/p2p-circuit/50"];

    for address in &addresses {
        assert!(address.parse::<Multiaddr>().is_err(), address.to_string());
    }
}

#[test]
fn to_multiaddr() {
    assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_multiaddr().unwrap(),
               "/ip4/127.0.0.1".parse::<Multiaddr>().unwrap());
    assert_eq!(Ipv6Addr::new(0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21)
                   .to_multiaddr()
                   .unwrap(),
               "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse::<Multiaddr>().unwrap());
    assert_eq!("/ip4/127.0.0.1/tcp/1234".to_string().to_multiaddr().unwrap(),
               "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap());
    assert_eq!("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".to_multiaddr().unwrap(),
               "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse::<Multiaddr>().unwrap());
    assert_eq!(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 1234).to_multiaddr().unwrap(),
               "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap());
    assert_eq!(SocketAddrV6::new(Ipv6Addr::new(0x2601,
                                               0x9,
                                               0x4f81,
                                               0x9700,
                                               0x803e,
                                               0xca65,
                                               0x66e8,
                                               0xc21),
                                 1234,
                                 0,
                                 0)
                   .to_multiaddr()
                   .unwrap(),
               "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21/tcp/1234".parse::<Multiaddr>().unwrap());
}

#[test]
fn from_bytes_fail() {
    let bytes = vec![1, 2, 3, 4];
    assert!(Multiaddr::from_bytes(bytes).is_err());
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate json;
extern crate requests;

use requests::{delete, get, head, post, put};

#[test]
fn simple_get() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    let data = res.json().unwrap();
    println!("{:?}", data);
    assert_eq!(data["url"], URL);
    assert_eq!(data["headers"]["Host"], "httpbin.org");
    assert_eq!(data["headers"]["User-Agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn simple_post() {
    const URL: &'static str = "http://httpbin.org/post";
    let res = post(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_put() {
    const URL: &'static str = "http://httpbin.org/put";
    let res = put(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_head() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = head(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_delete() {
    const URL: &'static str = "http://httpbin.org/delete";
    let res = delete(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn user_agent() {
    let useragent = concat!("{\n  \"user-agent\": \"requests-rs/",
                            env!("CARGO_PKG_VERSION"),
                            "\"\n}\n");
    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    assert_eq!(res.text(), Some(useragent));
}

#[test]
fn user_agent_json() {

    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert!(res.is_json());

    let ua = res.json().unwrap();
    assert_eq!(ua["user-agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn content() {
    const URL: &'static str = "http://httpbin.org/headers";
    let res = get(URL).unwrap();
    let content = vec![123, 10, 32, 32, 34, 104, 101, 97, 100, 101, 114, 115, 34, 58, 32, 123, 10,
                       32, 32, 32, 32, 34, 72, 111, 115, 116, 34, 58, 32, 34, 104, 116, 116, 112,
                       98, 105, 110, 46, 111, 114, 103, 34, 44, 32, 10, 32, 32, 32, 32, 34, 85,
                       115, 101, 114, 45, 65, 103, 101, 110, 116, 34, 58, 32, 34, 114, 101, 113,
                       117, 101, 115, 116, 115, 45, 114, 115, 47, 48, 46, 48, 46, 49, 55, 34, 10,
                       32, 32, 125, 10, 125, 10];
    assert_eq!(res.content(), &content);
}

macro_rules! status_code_test {
    ($($name:ident: $numeric:expr,)+) => {
        $(#[test]
        fn $name() {
            let res = get(&format!("http://httpbin.org/status/{}", $numeric)).unwrap();
            assert_eq!(res.status_code(), hyper::status::StatusCode::from_u16($numeric));
        })+
    }
}

status_code_test! {
    status_code_100: 100,
    status_code_101: 101,
    status_code_102: 102,
    status_code_200: 200,
    status_code_201: 201,
    status_code_202: 202,
    status_code_203: 203,
    status_code_400: 400,
    status_code_401: 401,
    status_code_402: 402,
    status_code_403: 403,
    status_code_404: 404,
    status_code_500: 500,
}
<commit_msg>help debug tests<commit_after>extern crate hyper;
extern crate json;
extern crate requests;

use requests::{delete, get, head, post, put};

#[test]
fn simple_get() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    let data = res.json().unwrap();
    println!("{:?}", data);
    assert_eq!(data["url"], URL);
    assert_eq!(data["headers"]["Host"], "httpbin.org");
    assert_eq!(data["headers"]["User-Agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn simple_post() {
    const URL: &'static str = "http://httpbin.org/post";
    let res = post(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_put() {
    const URL: &'static str = "http://httpbin.org/put";
    let res = put(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_head() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = head(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_delete() {
    const URL: &'static str = "http://httpbin.org/delete";
    let res = delete(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn user_agent() {
    let useragent = concat!("{\n  \"user-agent\": \"requests-rs/",
                            env!("CARGO_PKG_VERSION"),
                            "\"\n}\n");
    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    assert_eq!(res.text(), Some(useragent));
}

#[test]
fn user_agent_json() {

    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert!(res.is_json());

    let ua = res.json().unwrap();
    assert_eq!(ua["user-agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn content() {
    const URL: &'static str = "http://httpbin.org/headers";
    let res = get(URL).unwrap();
    let content = vec![123, 10, 32, 32, 34, 104, 101, 97, 100, 101, 114, 115, 34, 58, 32, 123, 10,
                       32, 32, 32, 32, 34, 72, 111, 115, 116, 34, 58, 32, 34, 104, 116, 116, 112,
                       98, 105, 110, 46, 111, 114, 103, 34, 44, 32, 10, 32, 32, 32, 32, 34, 85,
                       115, 101, 114, 45, 65, 103, 101, 110, 116, 34, 58, 32, 34, 114, 101, 113,
                       117, 101, 115, 116, 115, 45, 114, 115, 47, 48, 46, 48, 46, 49, 55, 34, 10,
                       32, 32, 125, 10, 125, 10];
    assert_eq!(res.content(), &content);
}

macro_rules! status_code_test {
    ($($name:ident: $numeric:expr,)+) => {
        $(#[test]
        fn $name() {
            let res = get(&format!("http://httpbin.org/status/{}", $numeric)).unwrap();
            println!("{}", res.text().unwrap());
            assert_eq!(res.status_code(), hyper::status::StatusCode::from_u16($numeric));
        })+
    }
}

status_code_test! {
    status_code_100: 100,
    status_code_101: 101,
    status_code_102: 102,
    status_code_200: 200,
    status_code_201: 201,
    status_code_202: 202,
    status_code_203: 203,
    status_code_400: 400,
    status_code_401: 401,
    status_code_402: 402,
    status_code_403: 403,
    status_code_404: 404,
    status_code_500: 500,
}
<|endoftext|>


<commit_before>extern crate opentype;

use opentype::Font;
use opentype::compound::{CharMapping, MaxProfile};
use std::fs::{self, File};
use std::path::PathBuf;

#[test]
fn char_mapping_header() {
    let mut file = open("SourceSerifPro-Regular.otf");
    let font = Font::read(&mut file).unwrap();

    let header = font.char_mapping_header.as_ref().unwrap();
    assert_eq!(header.version, 0);
    assert_eq!(header.numTables, 3);
}

#[test]
fn char_mappings() {
    let mut file = open("SourceSerifPro-Regular.otf");
    let font = Font::read(&mut file).unwrap();

    assert_eq!(font.char_mappings.len(), 3);
    match &font.char_mappings[0] {
        &CharMapping::Format4(ref mapping) => {
            assert_eq!(mapping.segCountX2, 2 * 115);
            assert_eq!(mapping.searchRange, 2 * (1 << 115f64.log2().floor() as usize));
            assert_eq!(mapping.endCount.len(), 115);
        },
        _ => unreachable!(),
    }
    match &font.char_mappings[1] {
        &CharMapping::Format6(..) => {},
        _ => unreachable!(),
    }
    match &font.char_mappings[2] {
        &CharMapping::Format4(..) => {},
        _ => unreachable!(),
    }

    match font.max_profile {
        Some(MaxProfile::Version05(ref profile)) => {
            assert_eq!(profile.numGlyphs, 545);
        },
        _ => unreachable!(),
    }
}

#[test]
fn encoding_records() {
    let mut file = open("SourceSerifPro-Regular.otf");
    let font = Font::read(&mut file).unwrap();

    let records = &font.encoding_records;
    assert_eq!(records.len(), 3);

    let (platforms, encodings) = ([0, 1, 3], [3, 0, 1]);
    for i in 0..3 {
        assert_eq!(records[i].platformID, platforms[i]);
        assert_eq!(records[i].encodingID, encodings[i]);
    }
}

#[test]
fn font_header() {
    let mut file = open("SourceSerifPro-Regular.otf");
    let font = Font::read(&mut file).unwrap();

    match font.font_header {
        Some(ref header) => {
            assert_eq!(header.fontRevision.as_f32(), 1.014);
            assert_eq!(header.unitsPerEm, 1000);
            assert_eq!(header.macStyle, 0);
        },
        _ => unreachable!(),
    }
}

#[test]
fn offset_table() {
    let mut file = open("SourceSerifPro-Regular.otf");
    let font = Font::read(&mut file).unwrap();
    let table = &font.offset_table;

    assert_eq!(table.version.0, 0x4f54544f);
    assert_eq!(table.numTables, 12);
    assert_eq!(table.searchRange, 8 * 16);
    assert_eq!(table.entrySelector, 3);
    assert_eq!(table.rangeShift, table.numTables * 16 - table.searchRange);
}

fn open(name: &str) -> File {
    let path = PathBuf::from("tests/fixtures").join(name);
    assert!(fs::metadata(&path).is_ok());
    File::open(&path).unwrap()
}
<commit_msg>Revisit the tests<commit_after>extern crate opentype;

use opentype::Font;
use opentype::compound::{CharMapping, MaxProfile};
use std::fs::{self, File};
use std::path::PathBuf;

#[test]
fn char_mapping_header() {
    let mut file = open("SourceSerifPro-Regular.otf");
    let font = Font::read(&mut file).unwrap();
    let header = font.char_mapping_header.as_ref().unwrap();

    assert_eq!(header.version, 0);
    assert_eq!(header.numTables, 3);
}

#[test]
fn char_mappings() {
    let mut file = open("SourceSerifPro-Regular.otf");
    let font = Font::read(&mut file).unwrap();
    let mappings = &font.char_mappings;

    assert_eq!(mappings.len(), 3);
    match &mappings[0] {
        &CharMapping::Format4(ref mapping) => {
            assert_eq!(mapping.segCountX2, 2 * 115);
            assert_eq!(mapping.searchRange, 2 * (1 << 115f64.log2().floor() as usize));
            assert_eq!(mapping.endCount.len(), 115);
        },
        _ => unreachable!(),
    }
    match &mappings[1] {
        &CharMapping::Format6(..) => {},
        _ => unreachable!(),
    }
    match &mappings[2] {
        &CharMapping::Format4(..) => {},
        _ => unreachable!(),
    }
}

#[test]
fn encoding_records() {
    let mut file = open("SourceSerifPro-Regular.otf");
    let font = Font::read(&mut file).unwrap();
    let records = &font.encoding_records;

    assert_eq!(records.len(), 3);
    assert_eq!(records[0].platformID, 0);
    assert_eq!(records[0].encodingID, 3);
    assert_eq!(records[1].platformID, 1);
    assert_eq!(records[1].encodingID, 0);
    assert_eq!(records[2].platformID, 3);
    assert_eq!(records[2].encodingID, 1);
}

#[test]
fn font_header() {
    let mut file = open("SourceSerifPro-Regular.otf");
    let font = Font::read(&mut file).unwrap();
    let header = font.font_header.as_ref().unwrap();

    assert_eq!(header.fontRevision.as_f32(), 1.014);
    assert_eq!(header.unitsPerEm, 1000);
    assert_eq!(header.macStyle, 0);
}

#[test]
fn offset_table() {
    let mut file = open("SourceSerifPro-Regular.otf");
    let font = Font::read(&mut file).unwrap();
    let table = &font.offset_table;

    assert_eq!(table.version.0, 0x4f54544f);
    assert_eq!(table.numTables, 12);
    assert_eq!(table.searchRange, 8 * 16);
    assert_eq!(table.entrySelector, 3);
    assert_eq!(table.rangeShift, table.numTables * 16 - table.searchRange);
}

#[test]
fn max_profile() {
    let mut file = open("SourceSerifPro-Regular.otf");
    let font = Font::read(&mut file).unwrap();
    let profile = font.max_profile.as_ref().unwrap();

    match profile {
        &MaxProfile::Version05(ref profile) => {
            assert_eq!(profile.numGlyphs, 545);
        },
        _ => unreachable!(),
    }
}

fn open(name: &str) -> File {
    let path = PathBuf::from("tests/fixtures").join(name);
    assert!(fs::metadata(&path).is_ok());
    File::open(&path).unwrap()
}
<|endoftext|>