<commit_before>use {
    AddBevel,
    AddBorder,
    AddRound,
    AddPolygons,
};
use internal::{
    CanRectangle,
    CanSourceRectangle,
    Color,
    HasColor,
    HasRectangle,
    HasSourceRectangle,
    Line,
    Polygon,
    Polygons,
    Radius,
    Rectangle,
    SourceRectangle,
};
use vecmath::Scalar;

pub struct RectangleVariant {
    pub rect: Rectangle
}
pub struct EllipseVariant {
    pub rect: Rectangle
}
pub struct LineVariant {
    pub line: Line
}
pub struct ImageVariant<'a, I, TRectangle=()> {
    pub image: &'a I,
    pub src_rect: SourceRectangle,
    pub rect: TRectangle,
}
pub struct LerpTweenVariant<TShapes=()> {
    pub lerp: Scalar,
    pub shapes: TShapes,
}
pub struct PolygonVariant<'a> {
    pub polygon: Polygon<'a>
}

pub struct BevelCorner {
    pub bevel_radius: Radius
}
pub struct RoundCorner {
    pub round_radius: Radius
}
pub struct SquareCorner {
    pub square_radius: Radius
}

pub type EllipseShape = Shape<EllipseVariant>;
pub type EllipseBorderShape = Shape<EllipseVariant, Radius>;
pub type BevelRectangleShape = Shape<RectangleVariant, (), BevelCorner>;
pub type BevelRectangleBorderShape = Shape<RectangleVariant, Radius, BevelCorner>;
pub type ImageShape<'a, I> = Shape<ImageVariant<'a, I>>;
pub type ImageRectangleShape<'a, I> = Shape<ImageVariant<'a, I, Rectangle>>;
pub type LerpTweenShape = Shape<LerpTweenVariant>;
pub type LerpTweenPolygonsShape<'a> = Shape<LerpTweenVariant<Polygons<'a>>>;
pub type LineShape = Shape<LineVariant>;
pub type BevelBorderLineShape = Shape<LineVariant, (), BevelCorner>;
pub type RoundBorderLineShape = Shape<LineVariant, (), RoundCorner>;
pub type SquareBorderLineShape = Shape<LineVariant, (), SquareCorner>;
pub type PolygonShape<'a> = Shape<PolygonVariant<'a>, (), ()>;
pub type RectangleShape = Shape<RectangleVariant>;
pub type RectangleBorderShape = Shape<RectangleVariant, Radius>;
pub type RoundRectangleShape = Shape<RectangleVariant, (), RoundCorner>;
pub type RoundRectangleBorderShape = Shape<RectangleVariant, Radius, RoundCorner>;

/// A rectangle shape.
#[deriving(Copy)]
pub struct Shape<
    TVariant,
    TBorderRadius=(),
    TCorner=()
> {
    /// Rectangle.
    pub variant: TVariant,
    /// Border radius.
    pub border_radius: TBorderRadius,
    /// Round radius.
    pub corner: TCorner,
}

impl<S: Copy, B: Copy>
AddBevel<Shape<S, B, BevelCorner>>
for Shape<S, B> {
    #[inline(always)]
    fn bevel(
        &self,
        radius: Radius
    ) -> Shape<S, B, BevelCorner> {
        Shape {
            variant: self.variant,
            corner: BevelCorner { bevel_radius: radius },
            border_radius: self.border_radius,
        }
    }
}

impl<S: Copy, B: Copy>
AddRound<Shape<S, B, RoundCorner>>
for Shape<S, B> {
    #[inline(always)]
    fn round(
        &self,
        radius: Radius
    ) -> Shape<S, B, RoundCorner> {
        Shape {
            variant: self.variant,
            corner: RoundCorner { round_radius: radius },
            border_radius: self.border_radius,
        }
    }
}

impl<S: Copy, C: Copy>
AddBorder<Shape<S, Radius, C>>
for Shape<S, (), C> {
    #[inline(always)]
    fn border_radius(
        &self,
        radius: Radius
    ) -> Shape<S, Radius, C> {
        Shape {
            variant: self.variant,
            corner: self.corner,
            border_radius: radius,
        }
    }
}

/// Shapes containing a rectangle can change rectangle.
///
/// Can not contain an ellipse.
impl<B: Copy, C: Copy>
CanRectangle<Shape<RectangleVariant, B, C>, Rectangle>
for Shape<RectangleVariant, B, C> {
    #[inline(always)]
    fn rectangle(&self, rect: Rectangle) -> Shape<RectangleVariant, B, C> {
        Shape {
            variant: RectangleVariant { rect: rect },
            ..*self
        }
    }
}

/// Shapes containing an ellipse can change rectangle.
///
/// Can not contain a rectangle.
impl<B: Copy, C: Copy>
CanRectangle<Shape<EllipseVariant, B, C>, Rectangle>
for Shape<EllipseVariant, B, C> {
    #[inline(always)]
    fn rectangle(&self, rect: Rectangle) -> Shape<EllipseVariant, B, C> {
        Shape {
            variant: EllipseVariant { rect: rect },
            ..*self
        }
    }
}

impl<'b, I, B: Copy, C: Copy>
CanRectangle<Shape<ImageVariant<'b, I, Rectangle>, B, C>, Rectangle>
for Shape<ImageVariant<'b, I, Rectangle>, B, C> {
    #[inline(always)]
    fn rectangle(
        &self,
        rect: Rectangle
    ) -> Shape<ImageVariant<'b, I, Rectangle>, B, C> {
        Shape {
            variant: ImageVariant {
                    rect: rect,
                    image: self.variant.image,
                    src_rect: self.variant.src_rect
                },
            border_radius: self.border_radius,
            corner: self.corner,
        }
    }
}

/// Gets rectangle of rectangle shape.
impl<B, C>
HasRectangle<Rectangle>
for Shape<RectangleVariant, B, C> {
    #[inline(always)]
    fn get_rectangle(&self) -> Rectangle {
        self.variant.rect
    }
}

/// Gets ellipse of ellipse shape.
impl<B, C>
HasRectangle<Rectangle>
for Shape<EllipseVariant, B, C> {
    #[inline(always)]
    fn get_rectangle(&self) -> Rectangle {
        self.variant.rect
    }
}

impl<'b, I, B, C>
HasRectangle<Rectangle>
for Shape<ImageVariant<'b, I, Rectangle>, B, C> {
    #[inline(always)]
    fn get_rectangle(&self) -> Rectangle {
        self.variant.rect
    }
}

impl<'b, I, R, B, C>
HasSourceRectangle<SourceRectangle>
for Shape<ImageVariant<'b, I, R>, B, C> {
    #[inline(always)]
    fn get_source_rectangle(&self) -> SourceRectangle {
        self.variant.src_rect
    }
}

impl<'b, I, R: Copy, B: Copy, C: Copy>
CanSourceRectangle<Shape<ImageVariant<'b, I, R>, B, C>, SourceRectangle>
for Shape<ImageVariant<'b, I, R>, B, C> {
    #[inline(always)]
    fn source_rectangle(
        &self,
        source_rect: SourceRectangle
    ) -> Shape<ImageVariant<'b, I, R>, B, C> {
        Shape {
            variant: ImageVariant {
                    image: self.variant.image,
                    rect: self.variant.rect,
                    src_rect: source_rect,
                },
            border_radius: self.border_radius,
            corner: self.corner,
        }
    }
}

impl<'b>
AddPolygons<'b, LerpTweenPolygonsShape<'b>>
for LerpTweenShape {
    #[inline(always)]
    fn polygons(
        &self,
        polygons: Polygons<'b>
    ) -> LerpTweenPolygonsShape<'b> {
        Shape {
            variant: LerpTweenVariant {
                    lerp: self.variant.lerp,
                    shapes: polygons,
                },
            border_radius: self.border_radius,
            corner: self.corner,
        }
    }
}

static WHITE: Color = [1.0, ..4];

// Use white color per vertex.
impl<'b, I, R, B, C>
HasColor<Color>
for Shape<ImageVariant<'b, I, R>, B, C> {
    #[inline(always)]
    fn get_color(&self) -> Color {
        WHITE
    }
}

<commit_msg>new rustc<commit_after>use {
    AddBevel,
    AddBorder,
    AddRound,
    AddPolygons,
};
use internal::{
    CanRectangle,
    CanSourceRectangle,
    Color,
    HasColor,
    HasRectangle,
    HasSourceRectangle,
    Line,
    Polygon,
    Polygons,
    Radius,
    Rectangle,
    SourceRectangle,
};
use vecmath::Scalar;

pub struct RectangleVariant {
    pub rect: Rectangle
}
pub struct EllipseVariant {
    pub rect: Rectangle
}
pub struct LineVariant {
    pub line: Line
}
pub struct ImageVariant<'a, I:'a, TRectangle=()> {
    pub image: &'a I,
    pub src_rect: SourceRectangle,
    pub rect: TRectangle,
}
pub struct LerpTweenVariant<TShapes=()> {
    pub lerp: Scalar,
    pub shapes: TShapes,
}
pub struct PolygonVariant<'a> {
    pub polygon: Polygon<'a>
}

pub struct BevelCorner {
    pub bevel_radius: Radius
}
pub struct RoundCorner {
    pub round_radius: Radius
}
pub struct SquareCorner {
    pub square_radius: Radius
}

pub type EllipseShape = Shape<EllipseVariant>;
pub type EllipseBorderShape = Shape<EllipseVariant, Radius>;
pub type BevelRectangleShape = Shape<RectangleVariant, (), BevelCorner>;
pub type BevelRectangleBorderShape = Shape<RectangleVariant, Radius, BevelCorner>;
pub type ImageShape<'a, I> = Shape<ImageVariant<'a, I>>;
pub type ImageRectangleShape<'a, I> = Shape<ImageVariant<'a, I, Rectangle>>;
pub type LerpTweenShape = Shape<LerpTweenVariant>;
pub type LerpTweenPolygonsShape<'a> = Shape<LerpTweenVariant<Polygons<'a>>>;
pub type LineShape = Shape<LineVariant>;
pub type BevelBorderLineShape = Shape<LineVariant, (), BevelCorner>;
pub type RoundBorderLineShape = Shape<LineVariant, (), RoundCorner>;
pub type SquareBorderLineShape = Shape<LineVariant, (), SquareCorner>;
pub type PolygonShape<'a> = Shape<PolygonVariant<'a>, (), ()>;
pub type RectangleShape = Shape<RectangleVariant>;
pub type RectangleBorderShape = Shape<RectangleVariant, Radius>;
pub type RoundRectangleShape = Shape<RectangleVariant, (), RoundCorner>;
pub type RoundRectangleBorderShape = Shape<RectangleVariant, Radius, RoundCorner>;

/// A rectangle shape.
#[deriving(Copy)]
pub struct Shape<
    TVariant,
    TBorderRadius=(),
    TCorner=()
> {
    /// Rectangle.
    pub variant: TVariant,
    /// Border radius.
    pub border_radius: TBorderRadius,
    /// Round radius.
    pub corner: TCorner,
}

impl<S: Copy, B: Copy>
AddBevel<Shape<S, B, BevelCorner>>
for Shape<S, B> {
    #[inline(always)]
    fn bevel(
        &self,
        radius: Radius
    ) -> Shape<S, B, BevelCorner> {
        Shape {
            variant: self.variant,
            corner: BevelCorner { bevel_radius: radius },
            border_radius: self.border_radius,
        }
    }
}

impl<S: Copy, B: Copy>
AddRound<Shape<S, B, RoundCorner>>
for Shape<S, B> {
    #[inline(always)]
    fn round(
        &self,
        radius: Radius
    ) -> Shape<S, B, RoundCorner> {
        Shape {
            variant: self.variant,
            corner: RoundCorner { round_radius: radius },
            border_radius: self.border_radius,
        }
    }
}

impl<S: Copy, C: Copy>
AddBorder<Shape<S, Radius, C>>
for Shape<S, (), C> {
    #[inline(always)]
    fn border_radius(
        &self,
        radius: Radius
    ) -> Shape<S, Radius, C> {
        Shape {
            variant: self.variant,
            corner: self.corner,
            border_radius: radius,
        }
    }
}

/// Shapes containing a rectangle can change rectangle.
///
/// Can not contain an ellipse.
impl<B: Copy, C: Copy>
CanRectangle<Shape<RectangleVariant, B, C>, Rectangle>
for Shape<RectangleVariant, B, C> {
    #[inline(always)]
    fn rectangle(&self, rect: Rectangle) -> Shape<RectangleVariant, B, C> {
        Shape {
            variant: RectangleVariant { rect: rect },
            ..*self
        }
    }
}

/// Shapes containing an ellipse can change rectangle.
///
/// Can not contain a rectangle.
impl<B: Copy, C: Copy>
CanRectangle<Shape<EllipseVariant, B, C>, Rectangle>
for Shape<EllipseVariant, B, C> {
    #[inline(always)]
    fn rectangle(&self, rect: Rectangle) -> Shape<EllipseVariant, B, C> {
        Shape {
            variant: EllipseVariant { rect: rect },
            ..*self
        }
    }
}

impl<'b, I, B: Copy, C: Copy>
CanRectangle<Shape<ImageVariant<'b, I, Rectangle>, B, C>, Rectangle>
for Shape<ImageVariant<'b, I, Rectangle>, B, C> {
    #[inline(always)]
    fn rectangle(
        &self,
        rect: Rectangle
    ) -> Shape<ImageVariant<'b, I, Rectangle>, B, C> {
        Shape {
            variant: ImageVariant {
                    rect: rect,
                    image: self.variant.image,
                    src_rect: self.variant.src_rect
                },
            border_radius: self.border_radius,
            corner: self.corner,
        }
    }
}

/// Gets rectangle of rectangle shape.
impl<B, C>
HasRectangle<Rectangle>
for Shape<RectangleVariant, B, C> {
    #[inline(always)]
    fn get_rectangle(&self) -> Rectangle {
        self.variant.rect
    }
}

/// Gets ellipse of ellipse shape.
impl<B, C>
HasRectangle<Rectangle>
for Shape<EllipseVariant, B, C> {
    #[inline(always)]
    fn get_rectangle(&self) -> Rectangle {
        self.variant.rect
    }
}

impl<'b, I, B, C>
HasRectangle<Rectangle>
for Shape<ImageVariant<'b, I, Rectangle>, B, C> {
    #[inline(always)]
    fn get_rectangle(&self) -> Rectangle {
        self.variant.rect
    }
}

impl<'b, I, R, B, C>
HasSourceRectangle<SourceRectangle>
for Shape<ImageVariant<'b, I, R>, B, C> {
    #[inline(always)]
    fn get_source_rectangle(&self) -> SourceRectangle {
        self.variant.src_rect
    }
}

impl<'b, I, R: Copy, B: Copy, C: Copy>
CanSourceRectangle<Shape<ImageVariant<'b, I, R>, B, C>, SourceRectangle>
for Shape<ImageVariant<'b, I, R>, B, C> {
    #[inline(always)]
    fn source_rectangle(
        &self,
        source_rect: SourceRectangle
    ) -> Shape<ImageVariant<'b, I, R>, B, C> {
        Shape {
            variant: ImageVariant {
                    image: self.variant.image,
                    rect: self.variant.rect,
                    src_rect: source_rect,
                },
            border_radius: self.border_radius,
            corner: self.corner,
        }
    }
}

impl<'b>
AddPolygons<'b, LerpTweenPolygonsShape<'b>>
for LerpTweenShape {
    #[inline(always)]
    fn polygons(
        &self,
        polygons: Polygons<'b>
    ) -> LerpTweenPolygonsShape<'b> {
        Shape {
            variant: LerpTweenVariant {
                    lerp: self.variant.lerp,
                    shapes: polygons,
                },
            border_radius: self.border_radius,
            corner: self.corner,
        }
    }
}

static WHITE: Color = [1.0, ..4];

// Use white color per vertex.
impl<'b, I, R, B, C>
HasColor<Color>
for Shape<ImageVariant<'b, I, R>, B, C> {
    #[inline(always)]
    fn get_color(&self) -> Color {
        WHITE
    }
}

<|endoftext|>


<commit_before>use config::{Benchmark, Config, parse_config};
use Commit;
use Push;
use repo::Workspace;

use std::collections::HashMap;
use std::io;
use std::path::Path;
use std::process::{Command, ExitStatus};
use std::str;

/// `(val, percentage_change)`
#[derive(Debug, Clone)]
pub enum BenchmarkResult<T> {
    Improvement(T, f64),
    Regression(T, f64),
    Neutral(T, f64),
}

#[derive(Debug, Clone)]
pub struct TastingResult {
    pub branch: Option<String>,
    pub commit: Commit,
    pub build: bool,
    pub test: bool,
    pub bench: bool,
    pub results: Option<Vec<HashMap<String, BenchmarkResult<f64>>>>,
}

fn benchmark(workdir: &str,
             cfg: &Benchmark,
             previous_result: Option<&HashMap<String, BenchmarkResult<f64>>>)
             -> (ExitStatus, HashMap<String, BenchmarkResult<f64>>) {
    let mut cmd = Command::new("cargo");
    cmd.current_dir(workdir)
        .env("RUST_BACKTRACE", "1")
        .arg(&cfg.cmd)
        .args(cfg.args.as_slice());

    let output = cmd.output()
        .expect(&format!("Failed to execute benchmark '{}'!", cfg.name));

    let lines = str::from_utf8(output.stdout.as_slice()).unwrap().lines();
    let mut res = HashMap::new();

    // Don't try parsing the output if we didn't succeed
    if !output.status.success() {
        return (output.status, res);
    }

    // Success, so let's look for the results
    for l in lines {
        for (i, regex) in cfg.result_expr.iter().enumerate() {
            for cap in regex.captures_iter(l) {
                let (metric, value) = if cap.len() > 2 {
                    (String::from(cap.at(1).unwrap()), cap.at(2))
                } else {
                    (format!("{}", i), cap.at(1))
                };
                let bm_name = format!("{}/{}", cfg.name, &metric);
                if let Some(c) = value {
                    use std::str::FromStr;
                    let val = match f64::from_str(&c) {
                        Ok(f) => f,
                        Err(_) => {
                            println!("failed to parse value '{}' for {} into f64 number, ignoring",
                                     c,
                                     bm_name);
                            continue;
                        }
                    };
                    let new_result = match previous_result {
                        None => BenchmarkResult::Improvement(val, 0.0),
                        Some(prev_res) => {
                            let old_val = match prev_res.get(&bm_name) {
                                None => val,
                                Some(pv) => {
                                    match *pv {
                                        BenchmarkResult::Improvement(v, _) => v,
                                        BenchmarkResult::Regression(v, _) => v,
                                        BenchmarkResult::Neutral(v, _) => v,
                                    }
                                }
                            };
                            let new_result = if cfg.lower_is_better {
                                if val >= old_val * (1.0 + cfg.regression_threshold) {
                                    BenchmarkResult::Regression(val, (val / old_val) - 1.0)
                                } else if val < old_val * (1.0 - cfg.improvement_threshold) {
                                    BenchmarkResult::Improvement(val, (val / old_val) - 1.0)
                                } else {
                                    BenchmarkResult::Neutral(val, (val / old_val) - 1.0)
                                }
                            } else {
                                if val >= old_val * (1.0 + cfg.improvement_threshold) {
                                    BenchmarkResult::Improvement(val, (val / old_val) - 1.0)
                                } else if val < old_val * (1.0 - cfg.regression_threshold) {
                                    BenchmarkResult::Regression(val, (val / old_val) - 1.0)
                                } else {
                                    BenchmarkResult::Neutral(val, (val / old_val) - 1.0)
                                }
                            };
                            new_result
                        }
                    };
                    res.insert(bm_name, new_result);
                }
            }
        }
    }
    (output.status, res)
}

fn build(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("build")
        .arg("--release")
        .env("RUST_BACKTRACE", "1")
        .status()
        .expect("Failed to execute 'cargo build'!")
}

pub fn taste_commit(ws: &Workspace,
                    history: &mut HashMap<String,
                                          HashMap<String, HashMap<String, BenchmarkResult<f64>>>>,
                    push: &Push,
                    commit: &Commit,
                    def_improvement_threshold: f64,
                    def_regression_threshold: f64)
                    -> Result<(Option<Config>, TastingResult), String> {
    println!("Tasting commit {}", commit.id);
    ws.checkout_commit(&commit.id)?;

    let branch = match push.push_ref {
        None => None,
        Some(ref pr) => {
            match pr.rfind("/") {
                None => None,
                Some(i) => Some(String::from(&pr[i + 1..])),
            }
        }
    };

    let build_success = update(&ws.path).success() && build(&ws.path).success();
    let test_success = test(&ws.path).success();

    let cfg = match parse_config(Path::new(&format!("{}/taster.toml", ws.path)),
                                 def_improvement_threshold,
                                 def_regression_threshold) {
        Ok(c) => c,
        Err(e) => {
            match e.kind() {
                io::ErrorKind::NotFound => {
                    println!("Skipping commit {} which doesn't have a Taster config.",
                             commit.id);
                    return Ok((None,
                               TastingResult {
                                   branch: branch,
                                   commit: commit.clone(),
                                   build: build_success,
                                   test: test_success,
                                   bench: false,
                                   results: None,
                               }));
                }
                io::ErrorKind::InvalidData => {
                    println!("Skipping commit {} which has an invalid Taster config.",
                             commit.id);
                    return Ok((None,
                               TastingResult {
                                   branch: branch,
                                   commit: commit.clone(),
                                   build: build_success,
                                   test: test_success,
                                   bench: false,
                                   results: None,
                               }));
                }
                _ => unimplemented!(),
            }
        }
    };

    let bench_out = match branch {
        Some(ref branch) => {
            let branch_history = history.entry(branch.clone()).or_insert(HashMap::new());
            cfg.benchmarks
                .iter()
                .map(|b| {
                    let new_result = benchmark(&ws.path, b, branch_history.get(&b.name));
                    branch_history.insert(b.name.clone(), new_result.1.clone());
                    new_result
                })
                .collect::<Vec<(ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>()
        }
        None => {
            cfg.benchmarks
                .iter()
                .map(|b| benchmark(&ws.path, b, None))
                .collect::<Vec<(ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>()
        }
    };
    let bench_success = bench_out.iter().all(|x| x.0.success());
    let bench_results = bench_out.iter().map(|x| x.1.clone()).collect();

    Ok((Some(cfg),
        TastingResult {
            branch: branch,
            commit: commit.clone(),
            build: build_success,
            test: test_success,
            bench: bench_success,
            results: Some(bench_results),
        }))
}

fn test(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("test")
        .env("RUST_BACKTRACE", "1")
        .env("RUST_TEST_THREADS", "1")
        .status()
        .expect("Failed to execute 'cargo test'!")
}

fn update(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("update")
        .status()
        .expect("Failed to execute 'cargo update'!")
}
<commit_msg>It's InvalidInput, not InvalidData...<commit_after>use config::{Benchmark, Config, parse_config};
use Commit;
use Push;
use repo::Workspace;

use std::collections::HashMap;
use std::io;
use std::path::Path;
use std::process::{Command, ExitStatus};
use std::str;

/// `(val, percentage_change)`
#[derive(Debug, Clone)]
pub enum BenchmarkResult<T> {
    Improvement(T, f64),
    Regression(T, f64),
    Neutral(T, f64),
}

#[derive(Debug, Clone)]
pub struct TastingResult {
    pub branch: Option<String>,
    pub commit: Commit,
    pub build: bool,
    pub test: bool,
    pub bench: bool,
    pub results: Option<Vec<HashMap<String, BenchmarkResult<f64>>>>,
}

fn benchmark(workdir: &str,
             cfg: &Benchmark,
             previous_result: Option<&HashMap<String, BenchmarkResult<f64>>>)
             -> (ExitStatus, HashMap<String, BenchmarkResult<f64>>) {
    let mut cmd = Command::new("cargo");
    cmd.current_dir(workdir)
        .env("RUST_BACKTRACE", "1")
        .arg(&cfg.cmd)
        .args(cfg.args.as_slice());

    let output = cmd.output()
        .expect(&format!("Failed to execute benchmark '{}'!", cfg.name));

    let lines = str::from_utf8(output.stdout.as_slice()).unwrap().lines();
    let mut res = HashMap::new();

    // Don't try parsing the output if we didn't succeed
    if !output.status.success() {
        return (output.status, res);
    }

    // Success, so let's look for the results
    for l in lines {
        for (i, regex) in cfg.result_expr.iter().enumerate() {
            for cap in regex.captures_iter(l) {
                let (metric, value) = if cap.len() > 2 {
                    (String::from(cap.at(1).unwrap()), cap.at(2))
                } else {
                    (format!("{}", i), cap.at(1))
                };
                let bm_name = format!("{}/{}", cfg.name, &metric);
                if let Some(c) = value {
                    use std::str::FromStr;
                    let val = match f64::from_str(&c) {
                        Ok(f) => f,
                        Err(_) => {
                            println!("failed to parse value '{}' for {} into f64 number, ignoring",
                                     c,
                                     bm_name);
                            continue;
                        }
                    };
                    let new_result = match previous_result {
                        None => BenchmarkResult::Improvement(val, 0.0),
                        Some(prev_res) => {
                            let old_val = match prev_res.get(&bm_name) {
                                None => val,
                                Some(pv) => {
                                    match *pv {
                                        BenchmarkResult::Improvement(v, _) => v,
                                        BenchmarkResult::Regression(v, _) => v,
                                        BenchmarkResult::Neutral(v, _) => v,
                                    }
                                }
                            };
                            let new_result = if cfg.lower_is_better {
                                if val >= old_val * (1.0 + cfg.regression_threshold) {
                                    BenchmarkResult::Regression(val, (val / old_val) - 1.0)
                                } else if val < old_val * (1.0 - cfg.improvement_threshold) {
                                    BenchmarkResult::Improvement(val, (val / old_val) - 1.0)
                                } else {
                                    BenchmarkResult::Neutral(val, (val / old_val) - 1.0)
                                }
                            } else {
                                if val >= old_val * (1.0 + cfg.improvement_threshold) {
                                    BenchmarkResult::Improvement(val, (val / old_val) - 1.0)
                                } else if val < old_val * (1.0 - cfg.regression_threshold) {
                                    BenchmarkResult::Regression(val, (val / old_val) - 1.0)
                                } else {
                                    BenchmarkResult::Neutral(val, (val / old_val) - 1.0)
                                }
                            };
                            new_result
                        }
                    };
                    res.insert(bm_name, new_result);
                }
            }
        }
    }
    (output.status, res)
}

fn build(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("build")
        .arg("--release")
        .env("RUST_BACKTRACE", "1")
        .status()
        .expect("Failed to execute 'cargo build'!")
}

pub fn taste_commit(ws: &Workspace,
                    history: &mut HashMap<String,
                                          HashMap<String, HashMap<String, BenchmarkResult<f64>>>>,
                    push: &Push,
                    commit: &Commit,
                    def_improvement_threshold: f64,
                    def_regression_threshold: f64)
                    -> Result<(Option<Config>, TastingResult), String> {
    println!("Tasting commit {}", commit.id);
    ws.checkout_commit(&commit.id)?;

    let branch = match push.push_ref {
        None => None,
        Some(ref pr) => {
            match pr.rfind("/") {
                None => None,
                Some(i) => Some(String::from(&pr[i + 1..])),
            }
        }
    };

    let build_success = update(&ws.path).success() && build(&ws.path).success();
    let test_success = test(&ws.path).success();

    let cfg = match parse_config(Path::new(&format!("{}/taster.toml", ws.path)),
                                 def_improvement_threshold,
                                 def_regression_threshold) {
        Ok(c) => c,
        Err(e) => {
            match e.kind() {
                io::ErrorKind::NotFound => {
                    println!("Skipping commit {} which doesn't have a Taster config.",
                             commit.id);
                    return Ok((None,
                               TastingResult {
                                   branch: branch,
                                   commit: commit.clone(),
                                   build: build_success,
                                   test: test_success,
                                   bench: false,
                                   results: None,
                               }));
                }
                io::ErrorKind::InvalidInput => {
                    println!("Skipping commit {} which has an invalid Taster config.",
                             commit.id);
                    return Ok((None,
                               TastingResult {
                                   branch: branch,
                                   commit: commit.clone(),
                                   build: build_success,
                                   test: test_success,
                                   bench: false,
                                   results: None,
                               }));
                }
                _ => unimplemented!(),
            }
        }
    };

    let bench_out = match branch {
        Some(ref branch) => {
            let branch_history = history.entry(branch.clone()).or_insert(HashMap::new());
            cfg.benchmarks
                .iter()
                .map(|b| {
                    let new_result = benchmark(&ws.path, b, branch_history.get(&b.name));
                    branch_history.insert(b.name.clone(), new_result.1.clone());
                    new_result
                })
                .collect::<Vec<(ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>()
        }
        None => {
            cfg.benchmarks
                .iter()
                .map(|b| benchmark(&ws.path, b, None))
                .collect::<Vec<(ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>()
        }
    };
    let bench_success = bench_out.iter().all(|x| x.0.success());
    let bench_results = bench_out.iter().map(|x| x.1.clone()).collect();

    Ok((Some(cfg),
        TastingResult {
            branch: branch,
            commit: commit.clone(),
            build: build_success,
            test: test_success,
            bench: bench_success,
            results: Some(bench_results),
        }))
}

fn test(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("test")
        .env("RUST_BACKTRACE", "1")
        .env("RUST_TEST_THREADS", "1")
        .status()
        .expect("Failed to execute 'cargo test'!")
}

fn update(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("update")
        .status()
        .expect("Failed to execute 'cargo update'!")
}
<|endoftext|>


<commit_before>use super::Checked;

macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
            assert_eq!($op &x, y);
        }
    };
}

macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };
}

test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
// Strictly speaking the macro requires all the ints to be the same type, so we have to use u32.
test_binop! (shl u32: 10 << 3 == 80);
test_binop! (shr u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));
<commit_msg>Add potentially more types to binary macro<commit_after>use super::Checked;

// Test a unary operator
macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
            assert_eq!($op &x, y);
        }
    };
}

// Test a binary operator
macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty, $v:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$v>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };
}

// These tests use None to indicate over/underflow.
test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
test_binop! (shl u8, u32: 10 << 3 == 80);
test_binop! (shr u8, u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));
<|endoftext|>


<commit_before>macro_rules! generate_test {
    ( $(($m: ident $nbits: ident => $($block: ident)*)) * ) => {
        $(
            mod $m {
                $(
                    mod $block {
                        use num::{Zero, One};
                        use ::{NbitsVec, $nbits};
                        type NV = NbitsVec<$nbits, $block>;

                        fn mask(n: usize) -> $block {
                            (0..n).fold($block::zero(), |b, _x| b << 1 | $block::one())
                        }

                        mod struct_static {
                            use ::std::mem::size_of;
                            use super::{mask, NV};

                            #[test]
                            fn nbits() {
                                assert!(NV::nbits() > 0);
                            }

                            #[test]
                            fn block_bits() {
                                assert_eq!(NV::block_bits(), size_of::<$block>() * 8);
                            }

                            #[test]
                            fn bit_loc() {
                                assert_eq!(NV::bit_loc(0), (0, 0));
                                assert_eq!(NV::bit_loc(1), (0, 1));
                                let block_bits = NV::block_bits();
                                for i in 3..79 {
                                    assert_eq!(NV::bit_loc(i),
                                                (i / block_bits, i % block_bits));
                                }
                            }

                            #[test]
                            fn mask_ok() {
                                assert_eq!(NV::mask(), mask(NV::nbits()));
                            }

                        }
                        mod private_api {
                            use super::{mask, NV};

                            #[test]
                            fn raw_bit() {
                                let mut vec = NV::with_capacity(100);
                                unsafe {
                                    for i in 0..(100 * NV::nbits()) {
                                        vec.set_raw_bit(i, true);
                                        assert_eq!(vec.get_raw_bit(i), 0b1);
                                        vec.set_raw_bit(i, false);
                                        assert_eq!(vec.get_raw_bit(i), 0b0);
                                    }
                                }
                            }

                            #[test]
                            fn raw_bits() {
                                let mut vec = NV::with_capacity(100);
                                unsafe {
                                    for n in 2..8 {
                                        for i in 0..(100 * NV::nbits() - n) {
                                            vec.set_raw_bits(i, n, 0b1001);
                                            println!("N = {}, i = {}", n, i);
                                            vec.get_raw_bits(i, n);
                                            assert_eq!(vec.get_raw_bits(i, n), 0b1001 & mask(n));
                                        }
                                        for i in 0..n {
                                            let j = 100 * NV::nbits() - i;
                                            vec.get_raw_bits(j, n);
                                        }
                                    }
                                }
                            }

                            #[test]
                            fn get_raw_bits() {
                                let vec = NV::with_capacity(100);
                                unsafe {
                                    vec.get_raw_bits(1, 1);
                                    vec.get_raw_bits(2, 2);
                                    vec.get_raw_bits(3, 3);
                                }
                            }

                            #[cfg(build = "debug")]
                            #[test]
                            #[should_panic]
                            fn failed_get_raw_bits() {
                                let vec = NV::with_capacity(100);
                                unsafe {
                                    vec.get_raw_bits(0, 100);
                                }
                            }
                        }
                        mod public_api {
                            use super::{NV};

                            #[test]
                            fn new() {
                                let vec = NV::new();
                                assert_eq!(vec.capacity(), 0);
                                assert_eq!(vec.len(), 0);
                                assert_eq!(vec.used_raw_cap(), 0);
                                assert_eq!(vec.raw_cap(), 0);
                            }
                            #[test]
                            fn push_pop() {
                                let mut vec = NV::new();
                                vec.push(1);
                                assert!(vec.capacity() >= 1);
                                assert_eq!(vec.len(), 1);
                                assert_eq!(vec.used_raw_cap(), 1);
                                assert_eq!(vec.raw_cap(), 1);
                                println!("{:?}", vec);
                                assert_eq!(vec.pop(), Some(1));
                                println!("Push...");
                                for _i in 0..100 {
                                    vec.push(1);
                                }
                                for _i in 0..100 {
                                    println!("{}", _i);
                                    assert_eq!(vec.pop(), Some(1));
                                }
                            }
                            #[test]
                            fn resize() {
                                let mut vec = NV::new();
                                println!("resize 100 `1`");
                                vec.resize(100, 1);
                                assert_eq!(vec.len(), 100);
                                assert!(vec.capacity() >= 100);
                                let bigger_cap = vec.capacity();
                                println!("resize to 10 `0`");
                                vec.resize(10, 0);
                                assert_eq!(vec.len(), 10);
                                assert!(vec.capacity() < bigger_cap);
                            }
                            #[test]
                            fn resize_large() {
                                let mut vec = NV::new();
                                const LEN: usize = 10000;
                                vec.resize(LEN, 1);
                                vec.resize(LEN * 2, 2);
                                vec.resize(LEN * 3, 3);
                            }
                            #[test]
                            fn get_set() {
                                let mut vec = NV::new();
                                vec.resize(100, 0b1111);
                                for i in 0..100 {
                                    vec.set(i, 0);
                                }
                                for i in 0..100 {
                                    let v = vec.get(i);
                                    assert_eq!(v, 0);
                                }
                            }
                        }

                        mod threadsafe {
                            use ::{NbitsVec, $nbits};
                            type NV = NbitsVec<$nbits, $block>;

                            #[test]
                            fn new() {
                                use std::thread;
                                use std::sync::mpsc::channel;
                                let (tx, rx) = channel();
                                for _ in 0..10 {
                                    let tx = tx.clone();
                                    thread::spawn(move || {
                                        tx.send(NV::new()).unwrap();
                                    });
                                }
                                for _ in 0..10 {
                                    let _ = rx.recv().unwrap();
                                }
                            }
                            #[test]
                            fn with_capacity() {
                                use std::thread;
                                use std::sync::mpsc::channel;
                                let (tx, rx) = channel();
                                for i in 0..10 {
                                    let tx = tx.clone();
                                    thread::spawn(move || {
                                        tx.send(NV::with_capacity(i)).unwrap();
                                    });
                                }
                                for i in 0..10 {
                                    let j = rx.recv().unwrap();
                                    println!("{} capacity: {}", i, j.capacity());
                                }
                            }
                        }
                    }
                 )*
            }
         )*
    }
}

generate_test! {
    (n1 N1 => u8 u16 u32 u64 usize)
    (n2 N2 => u8 u16 u32 u64 usize)
    (n3 N3 => u8 u16 u32 u64 usize)
    (n4 N4 => u8 u16 u32 u64 usize)
    (n8 N8 => u8 u16 u32 u64 usize)
}

macro_rules! panic_test {
    ( $(($m: ident $nbits: ident => $($block: ident)*)) * ) => {
        $(
            mod $m {
                $(
                    mod $block {
                        use ::{NbitsVec, $nbits};
                        type NV = NbitsVec<$nbits, $block>;
                        #[test]
                        #[should_panic]
                        fn panic_new() {
                            NV::new();
                        }
                        #[test]
                        #[should_panic]
                        fn panic_with_capacity() {
                            NV::with_capacity(10);
                        }
                        #[test]
                        #[should_panic]
                        fn panic_from_raw_parts() {
                            unsafe {
                                NV::from_raw_parts(::std::ptr::null_mut(), 0, 0);
                            }
                        }
                    }
                 )*
            }
         )*
    }
}

panic_test! {
    (n9 N9 => u8)
    (n17 N17 => u8 u16)
    (n33 N33 => u8 u16 u32)
}
<commit_msg>Add test for `fill` and `align`.<commit_after>macro_rules! generate_test {
    ( $(($m: ident $nbits: ident => $($block: ident)*)) * ) => {
        $(
            mod $m {
                $(
                    mod $block {
                        use num::{Zero, One};
                        use ::{NbitsVec, $nbits};
                        type NV = NbitsVec<$nbits, $block>;

                        fn mask(n: usize) -> $block {
                            (0..n).fold($block::zero(), |b, _x| b << 1 | $block::one())
                        }

                        mod struct_static {
                            use ::std::mem::size_of;
                            use super::{mask, NV};

                            #[test]
                            fn nbits() {
                                assert!(NV::nbits() > 0);
                            }

                            #[test]
                            fn block_bits() {
                                assert_eq!(NV::block_bits(), size_of::<$block>() * 8);
                            }

                            #[test]
                            fn bit_loc() {
                                assert_eq!(NV::bit_loc(0), (0, 0));
                                assert_eq!(NV::bit_loc(1), (0, 1));
                                let block_bits = NV::block_bits();
                                for i in 3..79 {
                                    assert_eq!(NV::bit_loc(i),
                                                (i / block_bits, i % block_bits));
                                }
                            }

                            #[test]
                            fn mask_ok() {
                                assert_eq!(NV::mask(), mask(NV::nbits()));
                            }

                        }
                        mod private_api {
                            use super::{mask, NV};

                            #[test]
                            fn raw_bit() {
                                let mut vec = NV::with_capacity(100);
                                unsafe {
                                    for i in 0..(100 * NV::nbits()) {
                                        vec.set_raw_bit(i, true);
                                        assert_eq!(vec.get_raw_bit(i), 0b1);
                                        vec.set_raw_bit(i, false);
                                        assert_eq!(vec.get_raw_bit(i), 0b0);
                                    }
                                }
                            }

                            #[test]
                            fn raw_bits() {
                                let mut vec = NV::with_capacity(100);
                                unsafe {
                                    for n in 2..8 {
                                        for i in 0..(100 * NV::nbits() - n) {
                                            vec.set_raw_bits(i, n, 0b1001);
                                            println!("N = {}, i = {}", n, i);
                                            vec.get_raw_bits(i, n);
                                            assert_eq!(vec.get_raw_bits(i, n), 0b1001 & mask(n));
                                        }
                                        for i in 0..n {
                                            let j = 100 * NV::nbits() - i;
                                            vec.get_raw_bits(j, n);
                                        }
                                    }
                                }
                            }

                            #[test]
                            fn get_raw_bits() {
                                let vec = NV::with_capacity(100);
                                unsafe {
                                    vec.get_raw_bits(1, 1);
                                    vec.get_raw_bits(2, 2);
                                    vec.get_raw_bits(3, 3);
                                }
                            }

                            #[cfg(build = "debug")]
                            #[test]
                            #[should_panic]
                            fn failed_get_raw_bits() {
                                let vec = NV::with_capacity(100);
                                unsafe {
                                    vec.get_raw_bits(0, 100);
                                }
                            }
                        }
                        mod public_api {
                            use super::{NV};

                            #[test]
                            fn new() {
                                let vec = NV::new();
                                assert_eq!(vec.capacity(), 0);
                                assert_eq!(vec.len(), 0);
                                assert_eq!(vec.used_raw_cap(), 0);
                                assert_eq!(vec.raw_cap(), 0);
                            }
                            #[test]
                            fn push_pop() {
                                let mut vec = NV::new();
                                vec.push(1);
                                assert!(vec.capacity() >= 1);
                                assert_eq!(vec.len(), 1);
                                assert_eq!(vec.used_raw_cap(), 1);
                                assert_eq!(vec.raw_cap(), 1);
                                println!("{:?}", vec);
                                assert_eq!(vec.pop(), Some(1));
                                println!("Push...");
                                for _i in 0..100 {
                                    vec.push(1);
                                }
                                for _i in 0..100 {
                                    println!("{}", _i);
                                    assert_eq!(vec.pop(), Some(1));
                                }
                            }
                            #[test]
                            fn resize() {
                                let mut vec = NV::new();
                                println!("resize 100 `1`");
                                vec.resize(100, 1);
                                assert_eq!(vec.len(), 100);
                                assert!(vec.capacity() >= 100);
                                let bigger_cap = vec.capacity();
                                println!("resize to 10 `0`");
                                vec.resize(10, 0);
                                assert_eq!(vec.len(), 10);
                                assert!(vec.capacity() < bigger_cap);
                            }
                            #[test]
                            fn resize_large() {
                                let mut vec = NV::new();
                                const LEN: usize = 10000;
                                vec.resize(LEN, 1);
                                vec.resize(LEN * 2, 2);
                                vec.resize(LEN * 3, 3);
                            }
                            #[test]
                            fn get_set() {
                                let mut vec = NV::new();
                                vec.resize(100, 0b1111);
                                for i in 0..100 {
                                    vec.set(i, 0);
                                }
                                for i in 0..100 {
                                    let v = vec.get(i);
                                    assert_eq!(v, 0);
                                }
                            }
                            #[test]
                            fn fill() {
                                let mut vec = NV::new();
                                vec.resize(1000, 0b11111);
                                for i in 0..500 {
                                    vec.fill(i, i, 0b111001 >> (i / 100));
                                    for j in (i..).take(i) {
                                        assert_eq!(vec.get(j), 0b111001 >> (i / 100) & NV::mask());
                                    }
                                }
                            }
                            #[test]
                            fn align() {
                                let mut vec = NV::new();
                                println!("Align to right");
                                vec.align(0, 100);
                                assert_eq!(vec.len(), 100);
                                vec.align(50, 950);
                                assert_eq!(vec.len(), 1000);
                                vec.align(900, 1900);
                                assert_eq!(vec.len(), 2000);
                                println!("Align to left");
                                vec.align(987, 923);
                                assert_eq!(vec.len(), 2000 - (987 - 923));
                                vec.align(640, 576);
                                assert_eq!(vec.len(), 2000 - (987 - 923) - 64);
                                vec.align(555, 444);
                                assert_eq!(vec.len(), 2000 - (987 - 923) - 64 - 111);
                                vec.align(432, 319);
                                assert_eq!(vec.len(), 2000 - (987 - 923) - 64 - 111 - 113);
                                vec.align(200, 0);
                                assert_eq!(vec.len(), 2000 - (987 - 923) - 64 - 111 - 113 - 200);
                            }
                        }

                        mod threadsafe {
                            use ::{NbitsVec, $nbits};
                            type NV = NbitsVec<$nbits, $block>;

                            #[test]
                            fn new() {
                                use std::thread;
                                use std::sync::mpsc::channel;
                                let (tx, rx) = channel();
                                for _ in 0..10 {
                                    let tx = tx.clone();
                                    thread::spawn(move || {
                                        tx.send(NV::new()).unwrap();
                                    });
                                }
                                for _ in 0..10 {
                                    let _ = rx.recv().unwrap();
                                }
                            }
                            #[test]
                            fn with_capacity() {
                                use std::thread;
                                use std::sync::mpsc::channel;
                                let (tx, rx) = channel();
                                for i in 0..10 {
                                    let tx = tx.clone();
                                    thread::spawn(move || {
                                        tx.send(NV::with_capacity(i)).unwrap();
                                    });
                                }
                                for i in 0..10 {
                                    let j = rx.recv().unwrap();
                                    println!("{} capacity: {}", i, j.capacity());
                                }
                            }
                        }
                    }
                 )*
            }
         )*
    }
}

generate_test! {
    (n1 N1 => u8 u16 u32 u64 usize)
    (n2 N2 => u8 u16 u32 u64 usize)
    (n3 N3 => u8 u16 u32 u64 usize)
    (n4 N4 => u8 u16 u32 u64 usize)
    (n8 N8 => u8 u16 u32 u64 usize)
}

macro_rules! panic_test {
    ( $(($m: ident $nbits: ident => $($block: ident)*)) * ) => {
        $(
            mod $m {
                $(
                    mod $block {
                        use ::{NbitsVec, $nbits};
                        type NV = NbitsVec<$nbits, $block>;
                        #[test]
                        #[should_panic]
                        fn panic_new() {
                            NV::new();
                        }
                        #[test]
                        #[should_panic]
                        fn panic_with_capacity() {
                            NV::with_capacity(10);
                        }
                        #[test]
                        #[should_panic]
                        fn panic_from_raw_parts() {
                            unsafe {
                                NV::from_raw_parts(::std::ptr::null_mut(), 0, 0);
                            }
                        }
                    }
                 )*
            }
         )*
    }
}

panic_test! {
    (n9 N9 => u8)
    (n17 N17 => u8 u16)
    (n33 N33 => u8 u16 u32)
}
<|endoftext|>


<commit_before>use std::fmt;

/// Mirrors parquet::Type
#[derive(Debug)]
enum Type {
  BOOLEAN,
  INT32,
  INT64,
  INT96,
  FLOAT,
  DOUBLE,
  BYTE_ARRAY,
  FIXED_LEN_BYTE_ARRAY
}

/// Mirrors parquet::ConvertedType
#[derive(Debug)]
enum LogicalType {
  NONE,
  UTF8,
  MAP,
  MAP_KEY_VALUE,
  LIST,
  ENUM,
  DECIMAL,
  DATE,
  TIME_MILLIS,
  TIME_MICROS,
  TIMESTAMP_MILLIS,
  TIMESTAMP_MICROS,
  UINT_8,
  UINT_16,
  UINT_32,
  UINT_64,
  INT_8,
  INT_16,
  INT_32,
  INT_64,
  JSON,
  BSON,
  INTERVAL
}

/// Mirrors parquet::FieldRepetitionType
#[derive(Debug)]
enum Repetition {
  REQUIRED,
  OPTIONAL,
  REPEATED
}

/// Mirrors parquet::Encoding
#[derive(Debug)]
enum Encoding {
  PLAIN,
  PLAIN_DICTIONARY,
  RLE,
  BIT_PACKED,
  DELTA_BINARY_PACKED,
  DELTA_LENGTH_BYTE_ARRAY,
  DELTA_BYTE_ARRAY,
  RLE_DICTIONARY
}

/// Mirrors parquet::CompressionCodec
#[derive(Debug)]
enum Compression {
  UNCOMPRESSED,
  SNAPPY,
  GZIP,
  LZO,
  BROTLI
}

/// Mirrors parquet::PageType
#[derive(Debug)]
enum PageType {
  DATA_PAGE,
  INDEX_PAGE,
  DICTIONARY_PAGE,
  DATA_PAGE_V2
}

impl fmt::Display for Type {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

impl fmt::Display for LogicalType {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

impl fmt::Display for Repetition {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

impl fmt::Display for Encoding {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

impl fmt::Display for Compression {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

impl fmt::Display for PageType {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}
<commit_msg>Adding unit tests for Display of types<commit_after>use std::fmt;

/// Mirrors parquet::Type
#[derive(Debug)]
enum Type {
  BOOLEAN,
  INT32,
  INT64,
  INT96,
  FLOAT,
  DOUBLE,
  BYTE_ARRAY,
  FIXED_LEN_BYTE_ARRAY
}

/// Mirrors parquet::ConvertedType
#[derive(Debug)]
enum LogicalType {
  NONE,
  UTF8,
  MAP,
  MAP_KEY_VALUE,
  LIST,
  ENUM,
  DECIMAL,
  DATE,
  TIME_MILLIS,
  TIME_MICROS,
  TIMESTAMP_MILLIS,
  TIMESTAMP_MICROS,
  UINT_8,
  UINT_16,
  UINT_32,
  UINT_64,
  INT_8,
  INT_16,
  INT_32,
  INT_64,
  JSON,
  BSON,
  INTERVAL
}

/// Mirrors parquet::FieldRepetitionType
#[derive(Debug)]
enum Repetition {
  REQUIRED,
  OPTIONAL,
  REPEATED
}

/// Mirrors parquet::Encoding
#[derive(Debug)]
enum Encoding {
  PLAIN,
  PLAIN_DICTIONARY,
  RLE,
  BIT_PACKED,
  DELTA_BINARY_PACKED,
  DELTA_LENGTH_BYTE_ARRAY,
  DELTA_BYTE_ARRAY,
  RLE_DICTIONARY
}

/// Mirrors parquet::CompressionCodec
#[derive(Debug)]
enum Compression {
  UNCOMPRESSED,
  SNAPPY,
  GZIP,
  LZO,
  BROTLI
}

/// Mirrors parquet::PageType
#[derive(Debug)]
enum PageType {
  DATA_PAGE,
  INDEX_PAGE,
  DICTIONARY_PAGE,
  DATA_PAGE_V2
}

impl fmt::Display for Type {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

impl fmt::Display for LogicalType {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

impl fmt::Display for Repetition {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

impl fmt::Display for Encoding {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

impl fmt::Display for Compression {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

impl fmt::Display for PageType {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:?}", self)
  }
}

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

  #[test]
  fn test_display_type() {
    assert_eq!(Type::BOOLEAN.to_string(), "BOOLEAN");
    assert_eq!(Type::INT32.to_string(), "INT32");
    assert_eq!(Type::INT64.to_string(), "INT64");
    assert_eq!(Type::INT96.to_string(), "INT96");
    assert_eq!(Type::FLOAT.to_string(), "FLOAT");
    assert_eq!(Type::DOUBLE.to_string(), "DOUBLE");
    assert_eq!(Type::BYTE_ARRAY.to_string(), "BYTE_ARRAY");
    assert_eq!(Type::FIXED_LEN_BYTE_ARRAY.to_string(), "FIXED_LEN_BYTE_ARRAY");
  }

  #[test]
  fn test_display_logical_type() {
    assert_eq!(LogicalType::NONE.to_string(), "NONE");
    assert_eq!(LogicalType::UTF8.to_string(), "UTF8");
    assert_eq!(LogicalType::MAP.to_string(), "MAP");
    assert_eq!(LogicalType::MAP_KEY_VALUE.to_string(), "MAP_KEY_VALUE");
    assert_eq!(LogicalType::LIST.to_string(), "LIST");
    assert_eq!(LogicalType::ENUM.to_string(), "ENUM");
    assert_eq!(LogicalType::DECIMAL.to_string(), "DECIMAL");
    assert_eq!(LogicalType::DATE.to_string(), "DATE");
    assert_eq!(LogicalType::TIME_MILLIS.to_string(), "TIME_MILLIS");
    assert_eq!(LogicalType::DATE.to_string(), "DATE");
    assert_eq!(LogicalType::TIME_MICROS.to_string(), "TIME_MICROS");
    assert_eq!(LogicalType::TIMESTAMP_MILLIS.to_string(), "TIMESTAMP_MILLIS");
    assert_eq!(LogicalType::TIMESTAMP_MICROS.to_string(), "TIMESTAMP_MICROS");
    assert_eq!(LogicalType::UINT_8.to_string(), "UINT_8");
    assert_eq!(LogicalType::UINT_16.to_string(), "UINT_16");
    assert_eq!(LogicalType::UINT_32.to_string(), "UINT_32");
    assert_eq!(LogicalType::UINT_64.to_string(), "UINT_64");
    assert_eq!(LogicalType::INT_8.to_string(), "INT_8");
    assert_eq!(LogicalType::INT_16.to_string(), "INT_16");
    assert_eq!(LogicalType::INT_32.to_string(), "INT_32");
    assert_eq!(LogicalType::INT_64.to_string(), "INT_64");
    assert_eq!(LogicalType::JSON.to_string(), "JSON");
    assert_eq!(LogicalType::BSON.to_string(), "BSON");
    assert_eq!(LogicalType::INTERVAL.to_string(), "INTERVAL");
  }

  #[test]
  fn test_display_repetition() {
    assert_eq!(Repetition::REQUIRED.to_string(), "REQUIRED");
    assert_eq!(Repetition::OPTIONAL.to_string(), "OPTIONAL");
    assert_eq!(Repetition::REPEATED.to_string(), "REPEATED");
  }

  #[test]
  fn test_display_encoding() {
    assert_eq!(Encoding::PLAIN.to_string(), "PLAIN");
    assert_eq!(Encoding::PLAIN_DICTIONARY.to_string(), "PLAIN_DICTIONARY");
    assert_eq!(Encoding::RLE.to_string(), "RLE");
    assert_eq!(Encoding::BIT_PACKED.to_string(), "BIT_PACKED");
    assert_eq!(Encoding::DELTA_BINARY_PACKED.to_string(), "DELTA_BINARY_PACKED");
    assert_eq!(Encoding::DELTA_LENGTH_BYTE_ARRAY.to_string(), "DELTA_LENGTH_BYTE_ARRAY");
    assert_eq!(Encoding::DELTA_BYTE_ARRAY.to_string(), "DELTA_BYTE_ARRAY");
    assert_eq!(Encoding::RLE_DICTIONARY.to_string(), "RLE_DICTIONARY");
  }

  #[test]
  fn test_display_compression() {
    assert_eq!(Compression::UNCOMPRESSED.to_string(), "UNCOMPRESSED");
    assert_eq!(Compression::SNAPPY.to_string(), "SNAPPY");
    assert_eq!(Compression::GZIP.to_string(), "GZIP");
    assert_eq!(Compression::LZO.to_string(), "LZO");
    assert_eq!(Compression::BROTLI.to_string(), "BROTLI");
  }

  #[test]
  fn test_display_page_type() {
    assert_eq!(PageType::DATA_PAGE.to_string(), "DATA_PAGE");
    assert_eq!(PageType::INDEX_PAGE.to_string(), "INDEX_PAGE");
    assert_eq!(PageType::DICTIONARY_PAGE.to_string(), "DICTIONARY_PAGE");
    assert_eq!(PageType::DATA_PAGE_V2.to_string(), "DATA_PAGE_V2");
  }
}
<|endoftext|>


<commit_before>use itertools::Itertools;
use std::collections::{HashMap, HashSet};
use std::fmt;
use rand::random;

type Point = (isize, isize);

#[derive(Debug, Clone)]
pub struct World {
    width: isize,
    height: isize,
    generation: HashSet<Point>,
    neighbours: HashMap<Point, usize>,
    age: usize,
}

impl World {
    pub fn new(width: isize, height: isize)  -> World {
        World { width: width, height: height, age: 0, generation: HashSet::new(),
                neighbours: HashMap::with_capacity((width * height * 8) as usize) }
    }

    pub fn seed(mut self) -> World {
        self.generation = (0..self.width).cartesian_product(0..self.height)
                                         .filter(|_| random())
                                         .collect::<HashSet<Point>>();
        self.calculate_neighbours();
        self
    }

    pub fn evolve(&mut self) -> &World {
        self.generation = self.neighbours.iter()
                              .filter(|&(n, c)| self.decide_fate(n, *c))
                              .map(|(n, _)| *n)
                              .collect::<HashSet<Point>>();
        self.calculate_neighbours();
        self.age += 1;
        self
    }

    fn calculate_neighbours(&mut self) {
        self.neighbours.clear();
        for &(x, y) in self.generation.iter() {
            let neighbours = (-1..2).cartesian_product(-1..2)
                                    .filter(|&(dx, dy)| dx != 0 || dy != 0)
                                    .map(|(dx, dy)| (dx + x, dy + y));
            for n in neighbours {
                *self.neighbours.entry(n).or_insert(0) += 1;
            }
        }
    }

    fn decide_fate(&self, p: &Point, c: usize) -> bool {
        if self.generation.contains(p) {
            c == 3 || c == 2
        } else {
            c == 3
        }
    }
}

impl fmt::Display for World {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buf = String::with_capacity(((self.width + 2) * (self.height + 2) + 50) as usize);
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '┌' } else if x == self.width + 1 { '┐' } else { '─' });
        }
        buf.push('\n');
        for y in 0..self.height {
            buf.push('│');
            for x in 0..self.width {
                buf.push(if self.generation.contains(&(x, y)) { '*' } else { ' ' });
            }
            buf.push('|');
            if y == 0 {
                buf.push_str(&format!(" cells: {}", self.generation.len()));
            }
            if y == 1 {
                buf.push_str(&format!(" age: {}", self.age));
            }
            buf.push('\n');
        }
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '└' } else if x == self.width + 1 { '┘' } else { '─' });
        }
        write!(f, "{}", buf)
    }
}
<commit_msg>get rid of magic number<commit_after>use itertools::Itertools;
use std::collections::{HashMap, HashSet};
use std::fmt;
use std::mem;
use rand::random;

type Point = (isize, isize);

#[derive(Debug, Clone)]
pub struct World {
    width: isize,
    height: isize,
    generation: HashSet<Point>,
    neighbours: HashMap<Point, usize>,
    age: usize,
}

impl World {
    pub fn new(width: isize, height: isize)  -> World {
        World {
            width: width,
            height: height,
            age: 0,
            generation: HashSet::new(),
            neighbours: HashMap::with_capacity(((width * height) as usize ) * mem::size_of::<usize>())
        }
    }

    pub fn seed(mut self) -> World {
        self.generation = (0..self.width).cartesian_product(0..self.height)
                                         .filter(|_| random())
                                         .collect::<HashSet<Point>>();
        self.calculate_neighbours();
        self
    }

    pub fn evolve(&mut self) -> &World {
        self.generation = self.neighbours.iter()
                              .filter(|&(n, c)| self.decide_fate(n, *c))
                              .map(|(n, _)| *n)
                              .collect::<HashSet<Point>>();
        self.calculate_neighbours();
        self.age += 1;
        self
    }

    fn calculate_neighbours(&mut self) {
        self.neighbours.clear();
        for &(x, y) in self.generation.iter() {
            let neighbours = (-1..2).cartesian_product(-1..2)
                                    .filter(|&(dx, dy)| dx != 0 || dy != 0)
                                    .map(|(dx, dy)| (dx + x, dy + y));
            for n in neighbours {
                *self.neighbours.entry(n).or_insert(0) += 1;
            }
        }
    }

    fn decide_fate(&self, p: &Point, c: usize) -> bool {
        if self.generation.contains(p) {
            c == 3 || c == 2
        } else {
            c == 3
        }
    }
}

impl fmt::Display for World {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buf = String::with_capacity(((self.width + 2) * (self.height + 2) + 50) as usize);
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '┌' } else if x == self.width + 1 { '┐' } else { '─' });
        }
        buf.push('\n');
        for y in 0..self.height {
            buf.push('│');
            for x in 0..self.width {
                buf.push(if self.generation.contains(&(x, y)) { '*' } else { ' ' });
            }
            buf.push('|');
            if y == 0 {
                buf.push_str(&format!(" cells: {}", self.generation.len()));
            }
            if y == 1 {
                buf.push_str(&format!(" age: {}", self.age));
            }
            buf.push('\n');
        }
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '└' } else if x == self.width + 1 { '┘' } else { '─' });
        }
        write!(f, "{}", buf)
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use super::util::*;
use super::cluster::{Cluster, Simulator};
use super::transport_simulate::*;
use super::node::new_node_cluster;
use super::server::new_server_cluster;
use kvproto::eraftpb::MessageType;
use std::time::Duration;
use std::thread;

fn test_basic_transfer_leader<T: Simulator>(cluster: &mut Cluster<T>) {
    cluster.cfg.raft_store.raft_heartbeat_ticks = 20;
    let reserved_time = Duration::from_millis(cluster.cfg.raft_store.raft_base_tick_interval);
    cluster.run();

    // transfer leader to (2, 2)
    cluster.must_transfer_leader(1, new_peer(2, 2));

    let mut region = cluster.get_region(b"k3");

    // check if transfer leader is fast enough.
    let admin_req = new_transfer_leader_cmd(new_peer(3, 3));
    let mut req = new_admin_request(1, region.get_region_epoch(), admin_req);
    req.mut_header().set_peer(new_peer(2, 2));
    cluster.call_command(req, Duration::from_secs(3)).unwrap();
    thread::sleep(reserved_time);
    assert_eq!(cluster.query_leader(3, 1), Some(new_peer(3, 3)));

    let mut req = new_request(region.get_id(),
                              region.take_region_epoch(),
                              vec![new_put_cmd(b"k3", b"v3")],
                              false);
    req.mut_header().set_peer(new_peer(3, 3));
    // transfer leader to (4, 4)
    cluster.must_transfer_leader(1, new_peer(4, 4));
    // send request to old leader (3, 3) directly and verify it fails
    let resp = cluster.call_command(req, Duration::from_secs(5)).unwrap();
    assert!(resp.get_header().get_error().has_not_leader());
}

#[test]
fn test_server_basic_transfer_leader() {
    let mut cluster = new_server_cluster(0, 5);
    test_basic_transfer_leader(&mut cluster);
}

#[test]
fn test_node_basic_transfer_leader() {
    let mut cluster = new_node_cluster(0, 5);
    test_basic_transfer_leader(&mut cluster);
}

fn test_pd_transfer_leader<T: Simulator>(cluster: &mut Cluster<T>) {
    let pd_client = cluster.pd_client.clone();
    pd_client.disable_default_rule();

    cluster.run();

    cluster.must_put(b"k", b"v");

    // call command on this leader directly, must successfully.
    let mut region = cluster.get_region(b"");
    let mut req = new_request(region.get_id(),
                              region.take_region_epoch(),
                              vec![new_get_cmd(b"k")],
                              false);

    for id in 1..4 {
        // select a new leader to transfer
        pd_client.set_rule(box move |_, peer| {
            if peer.get_id() == id {
                return None;
            }
            new_pd_transfer_leader(new_peer(id, id))
        });

        for _ in 0..100 {
            // reset leader and wait transfer successfully.
            cluster.reset_leader_of_region(1);

            sleep_ms(20);

            if let Some(leader) = cluster.leader_of_region(1) {
                if leader.get_id() == id {
                    break;
                }
            }
        }

        assert_eq!(cluster.leader_of_region(1), Some(new_peer(id, id)));
        req.mut_header().set_peer(new_peer(id, id));
        debug!("requesting {:?}", req);
        let resp = cluster.call_command(req.clone(), Duration::from_secs(5)).unwrap();
        assert!(!resp.get_header().has_error(), "{:?}", resp);
        assert_eq!(resp.get_responses()[0].get_get().get_value(), b"v");
    }
}

#[test]
fn test_server_pd_transfer_leader() {
    let mut cluster = new_server_cluster(0, 3);
    test_pd_transfer_leader(&mut cluster);
}

#[test]
fn test_node_pd_transfer_leader() {
    let mut cluster = new_node_cluster(0, 3);
    test_pd_transfer_leader(&mut cluster);
}

fn test_transfer_leader_during_snapshot<T: Simulator>(cluster: &mut Cluster<T>) {
    let pd_client = cluster.pd_client.clone();
    // Disable default max peer count check.
    pd_client.disable_default_rule();
    cluster.cfg.raft_store.raft_log_gc_tick_interval = 20;
    cluster.cfg.raft_store.raft_log_gc_count_limit = 2;

    let r1 = cluster.run_conf_change();
    pd_client.must_add_peer(r1, new_peer(2, 2));

    for i in 0..1024 {
        let key = format!("{:01024}", i);
        let value = format!("{:01024}", i);
        cluster.must_put(key.as_bytes(), value.as_bytes());
    }

    cluster.must_transfer_leader(r1, new_peer(1, 1));

    // hook transport and drop all snapshot packet, so follower's status
    // will stay at snapshot.
    cluster.add_send_filter(DefaultFilterFactory::<SnapshotFilter>::default());
    // don't allow leader transfer succeed if it is actually triggered.
    cluster.add_send_filter(CloneFilterFactory(RegionPacketFilter::new(1, 2)
        .msg_type(MessageType::MsgTimeoutNow)
        .direction(Direction::Recv)));

    pd_client.must_add_peer(r1, new_peer(3, 3));
    // a just added peer needs wait a couple of ticks, it'll communicate with leader
    // before getting snapshot
    sleep_ms(1000);

    let epoch = cluster.get_region_epoch(1);
    let put = new_request(1, epoch, vec![new_put_cmd(b"k1", b"v1")], false);
    cluster.transfer_leader(r1, new_peer(2, 2));
    let resp = cluster.call_command_on_leader(put, Duration::from_secs(5));
    // if it's transfering leader, resp will timeout.
    assert!(resp.is_ok(), "{:?}", resp);
}

#[test]
fn test_server_transfer_leader_during_snapshot() {
    let mut cluster = new_server_cluster(0, 3);
    test_transfer_leader_during_snapshot(&mut cluster);
}

#[test]
fn test_node_transfer_leader_during_snapshot() {
    let mut cluster = new_node_cluster(0, 3);
    test_transfer_leader_during_snapshot(&mut cluster);
}
<commit_msg>tests: sleep longer (#1710)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use super::util::*;
use super::cluster::{Cluster, Simulator};
use super::transport_simulate::*;
use super::node::new_node_cluster;
use super::server::new_server_cluster;
use kvproto::eraftpb::MessageType;
use std::time::Duration;
use std::thread;

fn test_basic_transfer_leader<T: Simulator>(cluster: &mut Cluster<T>) {
    cluster.cfg.raft_store.raft_heartbeat_ticks = 20;
    let reserved_time = Duration::from_millis(cluster.cfg.raft_store.raft_base_tick_interval *
                                              cluster.cfg.raft_store.raft_heartbeat_ticks as u64);
    cluster.run();

    // transfer leader to (2, 2)
    cluster.must_transfer_leader(1, new_peer(2, 2));

    let mut region = cluster.get_region(b"k3");

    // check if transfer leader is fast enough.
    let admin_req = new_transfer_leader_cmd(new_peer(3, 3));
    let mut req = new_admin_request(1, region.get_region_epoch(), admin_req);
    req.mut_header().set_peer(new_peer(2, 2));
    cluster.call_command(req, Duration::from_secs(3)).unwrap();
    thread::sleep(reserved_time);
    assert_eq!(cluster.query_leader(3, 1), Some(new_peer(3, 3)));

    let mut req = new_request(region.get_id(),
                              region.take_region_epoch(),
                              vec![new_put_cmd(b"k3", b"v3")],
                              false);
    req.mut_header().set_peer(new_peer(3, 3));
    // transfer leader to (4, 4)
    cluster.must_transfer_leader(1, new_peer(4, 4));
    // send request to old leader (3, 3) directly and verify it fails
    let resp = cluster.call_command(req, Duration::from_secs(5)).unwrap();
    assert!(resp.get_header().get_error().has_not_leader());
}

#[test]
fn test_server_basic_transfer_leader() {
    let mut cluster = new_server_cluster(0, 5);
    test_basic_transfer_leader(&mut cluster);
}

#[test]
fn test_node_basic_transfer_leader() {
    let mut cluster = new_node_cluster(0, 5);
    test_basic_transfer_leader(&mut cluster);
}

fn test_pd_transfer_leader<T: Simulator>(cluster: &mut Cluster<T>) {
    let pd_client = cluster.pd_client.clone();
    pd_client.disable_default_rule();

    cluster.run();

    cluster.must_put(b"k", b"v");

    // call command on this leader directly, must successfully.
    let mut region = cluster.get_region(b"");
    let mut req = new_request(region.get_id(),
                              region.take_region_epoch(),
                              vec![new_get_cmd(b"k")],
                              false);

    for id in 1..4 {
        // select a new leader to transfer
        pd_client.set_rule(box move |_, peer| {
            if peer.get_id() == id {
                return None;
            }
            new_pd_transfer_leader(new_peer(id, id))
        });

        for _ in 0..100 {
            // reset leader and wait transfer successfully.
            cluster.reset_leader_of_region(1);

            sleep_ms(20);

            if let Some(leader) = cluster.leader_of_region(1) {
                if leader.get_id() == id {
                    break;
                }
            }
        }

        assert_eq!(cluster.leader_of_region(1), Some(new_peer(id, id)));
        req.mut_header().set_peer(new_peer(id, id));
        debug!("requesting {:?}", req);
        let resp = cluster.call_command(req.clone(), Duration::from_secs(5)).unwrap();
        assert!(!resp.get_header().has_error(), "{:?}", resp);
        assert_eq!(resp.get_responses()[0].get_get().get_value(), b"v");
    }
}

#[test]
fn test_server_pd_transfer_leader() {
    let mut cluster = new_server_cluster(0, 3);
    test_pd_transfer_leader(&mut cluster);
}

#[test]
fn test_node_pd_transfer_leader() {
    let mut cluster = new_node_cluster(0, 3);
    test_pd_transfer_leader(&mut cluster);
}

fn test_transfer_leader_during_snapshot<T: Simulator>(cluster: &mut Cluster<T>) {
    let pd_client = cluster.pd_client.clone();
    // Disable default max peer count check.
    pd_client.disable_default_rule();
    cluster.cfg.raft_store.raft_log_gc_tick_interval = 20;
    cluster.cfg.raft_store.raft_log_gc_count_limit = 2;

    let r1 = cluster.run_conf_change();
    pd_client.must_add_peer(r1, new_peer(2, 2));

    for i in 0..1024 {
        let key = format!("{:01024}", i);
        let value = format!("{:01024}", i);
        cluster.must_put(key.as_bytes(), value.as_bytes());
    }

    cluster.must_transfer_leader(r1, new_peer(1, 1));

    // hook transport and drop all snapshot packet, so follower's status
    // will stay at snapshot.
    cluster.add_send_filter(DefaultFilterFactory::<SnapshotFilter>::default());
    // don't allow leader transfer succeed if it is actually triggered.
    cluster.add_send_filter(CloneFilterFactory(RegionPacketFilter::new(1, 2)
        .msg_type(MessageType::MsgTimeoutNow)
        .direction(Direction::Recv)));

    pd_client.must_add_peer(r1, new_peer(3, 3));
    // a just added peer needs wait a couple of ticks, it'll communicate with leader
    // before getting snapshot
    sleep_ms(1000);

    let epoch = cluster.get_region_epoch(1);
    let put = new_request(1, epoch, vec![new_put_cmd(b"k1", b"v1")], false);
    cluster.transfer_leader(r1, new_peer(2, 2));
    let resp = cluster.call_command_on_leader(put, Duration::from_secs(5));
    // if it's transfering leader, resp will timeout.
    assert!(resp.is_ok(), "{:?}", resp);
}

#[test]
fn test_server_transfer_leader_during_snapshot() {
    let mut cluster = new_server_cluster(0, 3);
    test_transfer_leader_during_snapshot(&mut cluster);
}

#[test]
fn test_node_transfer_leader_during_snapshot() {
    let mut cluster = new_node_cluster(0, 3);
    test_transfer_leader_during_snapshot(&mut cluster);
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{
    common::EmptyRequest,
    types::{
        AccountBalanceRequest, AccountBalanceResponse, BlockRequest, BlockResponse,
        NetworkListResponse, NetworkOptionsResponse, NetworkRequest, NetworkStatusResponse,
    },
};
use aptos_rest_client::aptos_api_types::mime_types::JSON;
use reqwest::{header::CONTENT_TYPE, Client as ReqwestClient};
use url::Url;

/// Client for testing & interacting with a Rosetta service
pub struct RosettaClient {
    address: Url,
    inner: ReqwestClient,
}

impl RosettaClient {
    pub fn new(address: Url) -> RosettaClient {
        RosettaClient {
            address,
            inner: ReqwestClient::new(),
        }
    }

    pub async fn account_balance(
        &self,
        request: &AccountBalanceRequest,
    ) -> anyhow::Result<AccountBalanceResponse> {
        let response = self
            .inner
            .post(self.address.join("account/balance").unwrap())
            .header(CONTENT_TYPE, JSON)
            .body(serde_json::to_string(request)?)
            .send()
            .await?;

        self.json(response).await
    }

    pub async fn block(&self, request: &BlockRequest) -> anyhow::Result<BlockResponse> {
        let response = self
            .inner
            .post(self.address.join("block").unwrap())
            .header(CONTENT_TYPE, JSON)
            .body(serde_json::to_string(request)?)
            .send()
            .await?;

        self.json(response).await
    }

    pub async fn network_list(&self) -> anyhow::Result<NetworkListResponse> {
        let response = self
            .inner
            .post(self.address.join("network/list").unwrap())
            .header(CONTENT_TYPE, JSON)
            .body(serde_json::to_string(&EmptyRequest)?)
            .send()
            .await?;

        self.json(response).await
    }

    pub async fn network_options(
        &self,
        request: &NetworkRequest,
    ) -> anyhow::Result<NetworkOptionsResponse> {
        let response = self
            .inner
            .post(self.address.join("network/options").unwrap())
            .header(CONTENT_TYPE, JSON)
            .body(serde_json::to_string(request)?)
            .send()
            .await?;

        self.json(response).await
    }

    pub async fn network_status(
        &self,
        request: &NetworkRequest,
    ) -> anyhow::Result<NetworkStatusResponse> {
        let response = self
            .inner
            .post(self.address.join("network/status").unwrap())
            .header(CONTENT_TYPE, JSON)
            .body(serde_json::to_string(request)?)
            .send()
            .await?;

        self.json(response).await
    }

    async fn json<T: serde::de::DeserializeOwned>(
        &self,
        response: reqwest::Response,
    ) -> anyhow::Result<T> {
        if !response.status().is_success() {
            return Err(anyhow::anyhow!(
                "Request failed: {:?}",
                response.error_for_status()
            ));
        }

        Ok(response.json().await?)
    }
}
<commit_msg>[aptos-rosetta] Improve error handling in client<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{
    common::EmptyRequest,
    types::{
        AccountBalanceRequest, AccountBalanceResponse, BlockRequest, BlockResponse,
        NetworkListResponse, NetworkOptionsResponse, NetworkRequest, NetworkStatusResponse,
    },
};
use aptos_rest_client::aptos_api_types::mime_types::JSON;
use reqwest::{header::CONTENT_TYPE, Client as ReqwestClient};
use url::Url;

/// Client for testing & interacting with a Rosetta service
pub struct RosettaClient {
    address: Url,
    inner: ReqwestClient,
}

impl RosettaClient {
    pub fn new(address: Url) -> RosettaClient {
        RosettaClient {
            address,
            inner: ReqwestClient::new(),
        }
    }

    pub async fn account_balance(
        &self,
        request: &AccountBalanceRequest,
    ) -> anyhow::Result<AccountBalanceResponse> {
        let response = self
            .inner
            .post(self.address.join("account/balance").unwrap())
            .header(CONTENT_TYPE, JSON)
            .body(serde_json::to_string(request)?)
            .send()
            .await?;

        self.json(response).await
    }

    pub async fn block(&self, request: &BlockRequest) -> anyhow::Result<BlockResponse> {
        let response = self
            .inner
            .post(self.address.join("block").unwrap())
            .header(CONTENT_TYPE, JSON)
            .body(serde_json::to_string(request)?)
            .send()
            .await?;

        self.json(response).await
    }

    pub async fn network_list(&self) -> anyhow::Result<NetworkListResponse> {
        let response = self
            .inner
            .post(self.address.join("network/list").unwrap())
            .header(CONTENT_TYPE, JSON)
            .body(serde_json::to_string(&EmptyRequest)?)
            .send()
            .await?;

        self.json(response).await
    }

    pub async fn network_options(
        &self,
        request: &NetworkRequest,
    ) -> anyhow::Result<NetworkOptionsResponse> {
        let response = self
            .inner
            .post(self.address.join("network/options").unwrap())
            .header(CONTENT_TYPE, JSON)
            .body(serde_json::to_string(request)?)
            .send()
            .await?;

        self.json(response).await
    }

    pub async fn network_status(
        &self,
        request: &NetworkRequest,
    ) -> anyhow::Result<NetworkStatusResponse> {
        let response = self
            .inner
            .post(self.address.join("network/status").unwrap())
            .header(CONTENT_TYPE, JSON)
            .body(serde_json::to_string(request)?)
            .send()
            .await?;

        Ok(response.json().await?)
    }
}
<|endoftext|>