<commit_before>extern crate centralgithook;
extern crate tempdir;
#[macro_use]
extern crate log;
extern crate env_logger;

mod helpers;

use centralgithook::migrate::RepoHost;
use centralgithook::migrate;
use tempdir::TempDir;

struct TestSetup<'a>
{
    td: TempDir,
    central: helpers::TestRepo,
    scratch: migrate::Scratch<'a>,
    shell: migrate::Shell,
    head: String,
}

impl<'a> TestSetup<'a>
{
    fn new(host: &'a RepoHost) -> Self
    {
        env_logger::init().unwrap();
        let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
        let central = helpers::TestRepo::new(&td.path().join("central"));
        let scratch = migrate::Scratch::new(&td.path().join("scratch"), host);
        let shell = migrate::Shell { cwd: td.path().to_path_buf() };

        host.create_project("central");
        central.shell.command(&format!("git remote add origin {}", &host.remote_url("central")));

        central.add_file("modules/module_a/initial_a");
        central.add_file("modules/module_b/initial_b");
        let head = central.commit("initial");

        return TestSetup {
            td: td,
            central: central,
            scratch: scratch,
            shell: shell,
            head: head,
        };
    }
}

#[test]
fn test_initial_import()
{
    let host = helpers::TestHost::new();
    let TestSetup { td, central, scratch, shell, head } = TestSetup::new(&host);

    central.shell.command("git push origin master");
    migrate::central_submit(&scratch, scratch.transfer(&head, &host.repo_dir("central")))
        .expect("call central_submit");

    shell.command(&format!("git clone {}", &host.remote_url("modules/module_a")));
    shell.command(&format!("git clone {}", &host.remote_url("modules/module_b")));
    let module_a = helpers::TestRepo::new(&td.path().join("module_a"));
    let module_b = helpers::TestRepo::new(&td.path().join("module_b"));

    assert!(module_a.has_file("initial_a"));
    assert!(module_b.has_file("initial_b"));

    central.add_file("modules/module_a/added_a");
    central.add_file("modules/module_c/added_c");
    let head = central.commit("add");

    central.shell.command("git push origin master");
    migrate::central_submit(&scratch, scratch.transfer(&head, &host.repo_dir("central")))
        .expect("call central_submit");

    module_a.shell.command("git pull");
    shell.command(&format!("git clone {}", &host.remote_url("modules/module_c")));
    let module_c = helpers::TestRepo::new(&td.path().join("module_c"));

    assert!(module_a.has_file("added_a"));
    assert!(module_c.has_file("added_c"));

    module_a.add_file("added/in_mod_a");
    let head = module_a.commit("module_a_commit");

    migrate::module_review_upload(&scratch,
                                  scratch.transfer(&head, &module_a.path),
                                  "modules/module_a",
                                  "central")
        .expect("module_review_upload failed");

    central.shell.command("git fetch origin for/master:for/master");
    let for_master = central.rev("for/master");

    migrate::central_submit(&scratch,
                            scratch.transfer(&for_master, &host.repo_dir("central")))
        .expect("call central_submit");

    central.shell.command("git rebase for/master");
    assert_eq!(central.rev("master"), central.rev("for/master"));
    assert_eq!(central.rev("master"), central.rev("HEAD"));
    assert!(central.has_file("modules/module_a/added/in_mod_a"));

    module_a.shell.command("git pull");
    assert_eq!(module_a.rev("origin/master"), head);
}
<commit_msg>split test into multiple test cases<commit_after>extern crate centralgithook;
extern crate tempdir;
#[macro_use]
extern crate log;
extern crate env_logger;

mod helpers;

use centralgithook::migrate::RepoHost;
use centralgithook::migrate;
use tempdir::TempDir;

struct TestSetup<'a>
{
    td: TempDir,
    central: helpers::TestRepo,
    scratch: migrate::Scratch<'a>,
    shell: migrate::Shell,
}

impl<'a> TestSetup<'a>
{
    fn new(host: &'a RepoHost) -> Self
    {
        env_logger::init().ok();
        let td = TempDir::new("cgh_test").expect("folder cgh_test should be created");
        let central = helpers::TestRepo::new(&td.path().join("central"));
        let scratch = migrate::Scratch::new(&td.path().join("scratch"), host);
        let shell = migrate::Shell { cwd: td.path().to_path_buf() };

        host.create_project("central");
        central.shell.command(&format!("git remote add origin {}", &host.remote_url("central")));

        return TestSetup {
            td: td,
            central: central,
            scratch: scratch,
            shell: shell,
        };
    }
}

#[test]
fn test_initial_import()
{
    let host = helpers::TestHost::new();
    let TestSetup { td, central, scratch, shell }  = TestSetup::new(&host);

    central.add_file("modules/module_a/initial_a");
    central.add_file("modules/module_b/initial_b");
    let head = central.commit("initial");

    central.shell.command("git push origin master");
    migrate::central_submit(&scratch, scratch.transfer(&head, &host.repo_dir("central")))
        .expect("call central_submit");

    shell.command(&format!("git clone {}", &host.remote_url("modules/module_a")));
    shell.command(&format!("git clone {}", &host.remote_url("modules/module_b")));

    let module_a = helpers::TestRepo::new(&td.path().join("module_a"));
    let module_b = helpers::TestRepo::new(&td.path().join("module_b"));

    assert!(module_a.has_file("initial_a"));
    assert!(module_b.has_file("initial_b"));
}

#[test]
fn test_change_and_add_modules()
{
    let host = helpers::TestHost::new();
    let TestSetup { td, central, scratch, shell }  = TestSetup::new(&host);

    central.add_file("modules/module_a/initial_a");
    let head = central.commit("initial");

    central.shell.command("git push origin master");
    migrate::central_submit(&scratch, scratch.transfer(&head, &host.repo_dir("central")))
        .expect("call central_submit");

    central.add_file("modules/module_a/added_a");
    central.add_file("modules/module_c/added_c");
    let head = central.commit("add_a_and_c");

    central.shell.command("git push origin master");
    migrate::central_submit(&scratch, scratch.transfer(&head, &host.repo_dir("central")))
        .expect("call central_submit");

    shell.command(&format!("git clone {}", &host.remote_url("modules/module_a")));
    shell.command(&format!("git clone {}", &host.remote_url("modules/module_c")));

    let module_a = helpers::TestRepo::new(&td.path().join("module_a"));
    let module_c = helpers::TestRepo::new(&td.path().join("module_c"));

    assert!(module_a.has_file("added_a"));
    assert!(module_c.has_file("added_c"));
}

#[test]
fn test_module_review_upload()
{
    let host = helpers::TestHost::new();
    let TestSetup { td, central, scratch, shell }  = TestSetup::new(&host);

    central.add_file("modules/module_a/initial_a");
    let head = central.commit("initial");

    central.shell.command("git push origin master");
    migrate::central_submit(&scratch, scratch.transfer(&head, &host.repo_dir("central")))
        .expect("call central_submit");

    shell.command(&format!("git clone {}", &host.remote_url("modules/module_a")));
    let module_a = helpers::TestRepo::new(&td.path().join("module_a"));
    module_a.shell.command("git pull");

    module_a.add_file("added/in_mod_a");
    let head = module_a.commit("module_a_commit");

    migrate::module_review_upload(&scratch,
                                  scratch.transfer(&head, &module_a.path),
                                  "modules/module_a",
                                  "central")
        .expect("module_review_upload failed");

    central.shell.command("git fetch origin for/master:for/master");
    let for_master = central.rev("for/master");

    migrate::central_submit(&scratch,
                            scratch.transfer(&for_master, &host.repo_dir("central")))
        .expect("call central_submit");

    central.shell.command("git rebase for/master");
    assert_eq!(central.rev("master"), central.rev("for/master"));
    assert_eq!(central.rev("master"), central.rev("HEAD"));
    assert!(central.has_file("modules/module_a/added/in_mod_a"));

    module_a.shell.command("git pull");
    assert_eq!(module_a.rev("origin/master"), head);
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(unused_imports)]
#![deny(unused_variables)]

extern crate png;
extern crate test;
extern crate regex;
extern crate url;

use std::ascii::AsciiExt;
use std::io;
use std::io::{File, Reader, Command, IoResult};
use std::io::process::ExitStatus;
use std::io::fs::PathExtensions;
use std::os;
use std::path::Path;
use test::{AutoColor, DynTestName, DynTestFn, TestDesc, TestOpts, TestDescAndFn};
use test::run_tests_console;
use regex::Regex;
use url::Url;

bitflags!(
    flags RenderMode: u32 {
        const CPU_RENDERING  = 0x00000001,
        const GPU_RENDERING  = 0x00000010,
        const LINUX_TARGET   = 0x00000100,
        const MACOS_TARGET   = 0x00001000,
        const ANDROID_TARGET = 0x00010000
    }
)

fn main() {
    let args = os::args();
    let mut parts = args.tail().split(|e| "--" == e.as_slice());

    let harness_args = parts.next().unwrap();  // .split() is never empty
    let servo_args = parts.next().unwrap_or(&[]);

    let (render_mode_string, base_path, testname) = match harness_args {
        [] | [_] => panic!("USAGE: cpu|gpu base_path [testname regex]"),
        [ref render_mode_string, ref base_path] => (render_mode_string, base_path, None),
        [ref render_mode_string, ref base_path, ref testname, ..] => (render_mode_string, base_path, Some(Regex::new(testname.as_slice()).unwrap())),
    };

    let mut render_mode = match render_mode_string.as_slice() {
        "cpu" => CPU_RENDERING,
        "gpu" => GPU_RENDERING,
        _ => panic!("First argument must specify cpu or gpu as rendering mode")
    };
    if cfg!(target_os = "linux") {
        render_mode.insert(LINUX_TARGET);
    }
    if cfg!(target_os = "macos") {
        render_mode.insert(MACOS_TARGET);
    }
    if cfg!(target_os = "android") {
        render_mode.insert(ANDROID_TARGET);
    }

    let mut all_tests = vec!();
    println!("Scanning {} for manifests\n", base_path);

    for file in io::fs::walk_dir(&Path::new(base_path.as_slice())).unwrap() {
        let maybe_extension = file.extension_str();
        match maybe_extension {
            Some(extension) => {
                if extension.to_ascii_lower().as_slice() == "list" && file.is_file() {
                    let tests = parse_lists(&file, servo_args, render_mode, all_tests.len());
                    println!("\t{} [{} tests]", file.display(), tests.len());
                    all_tests.extend(tests.into_iter());
                }
            }
            _ => {}
        }
    }

    let test_opts = TestOpts {
        filter: testname,
        run_ignored: false,
        logfile: None,
        run_tests: true,
        run_benchmarks: false,
        ratchet_noise_percent: None,
        ratchet_metrics: None,
        save_metrics: None,
        test_shard: None,
        nocapture: false,
        color: AutoColor
    };

    match run(test_opts,
              all_tests,
              servo_args.iter().map(|x| x.clone()).collect()) {
        Ok(false) => os::set_exit_status(1), // tests failed
        Err(_) => os::set_exit_status(2),    // I/O-related failure
        _ => (),
    }
}

fn run(test_opts: TestOpts, all_tests: Vec<TestDescAndFn>,
       servo_args: Vec<String>) -> IoResult<bool> {
    // Verify that we're passing in valid servo arguments. Otherwise, servo
    // will exit before we've run any tests, and it will appear to us as if
    // all the tests are failing.
    let mut command = match Command::new("target/servo").args(servo_args.as_slice()).spawn() {
        Ok(p) => p,
        Err(e) => panic!("failed to execute process: {}", e),
    };
    let stderr = command.stderr.as_mut().unwrap().read_to_string().unwrap();

    if stderr.as_slice().contains("Unrecognized") {
        println!("Servo: {}", stderr.as_slice());
        return Ok(false);
    }

    run_tests_console(&test_opts, all_tests)
}

#[deriving(PartialEq)]
enum ReftestKind {
    Same,
    Different,
}

struct Reftest {
    name: String,
    kind: ReftestKind,
    files: [Path, ..2],
    id: uint,
    servo_args: Vec<String>,
    render_mode: RenderMode,
    is_flaky: bool,
    experimental: bool,
    fragment_identifier: Option<String>,
}

struct TestLine<'a> {
    conditions: &'a str,
    kind: &'a str,
    file_left: &'a str,
    file_right: &'a str,
}

fn parse_lists(file: &Path, servo_args: &[String], render_mode: RenderMode, id_offset: uint) -> Vec<TestDescAndFn> {
    let mut tests = Vec::new();
    let contents = File::open_mode(file, io::Open, io::Read)
                       .and_then(|mut f| f.read_to_string())
                       .ok().expect("Could not read file");

    for line in contents.as_slice().lines() {
        // ignore comments or empty lines
        if line.starts_with("#") || line.is_empty() {
            continue;
        }

        let parts: Vec<&str> = line.split(' ').filter(|p| !p.is_empty()).collect();

        let test_line = match parts.len() {
            3 => TestLine {
                conditions: "",
                kind: parts[0],
                file_left: parts[1],
                file_right: parts[2],
            },
            4 => TestLine {
                conditions: parts[0],
                kind: parts[1],
                file_left: parts[2],
                file_right: parts[3],
            },
            _ => panic!("reftest line: '{:s}' doesn't match '[CONDITIONS] KIND LEFT RIGHT'", line),
        };

        let kind = match test_line.kind {
            "==" => Same,
            "!=" => Different,
            part => panic!("reftest line: '{:s}' has invalid kind '{:s}'", line, part)
        };

        // If we're running this directly, file.dir_path() might be relative.
        // (see issue #3521)
        let base = match file.dir_path().is_relative() {
            true  => os::getcwd().join(file.dir_path()),
            false => file.dir_path()
        };

        let file_left =  base.join(test_line.file_left);
        let file_right = base.join(test_line.file_right);

        let mut conditions_list = test_line.conditions.split(',');
        let mut flakiness = RenderMode::empty();
        let mut experimental = false;
        let mut fragment_identifier = None;
        for condition in conditions_list {
            match condition {
                "flaky_cpu" => flakiness.insert(CPU_RENDERING),
                "flaky_gpu" => flakiness.insert(GPU_RENDERING),
                "flaky_linux" => flakiness.insert(LINUX_TARGET),
                "flaky_macos" => flakiness.insert(MACOS_TARGET),
                "experimental" => experimental = true,
                _ => (),
            }
            if condition.starts_with("fragment=") {
                fragment_identifier = Some(condition.slice_from("fragment=".len()).to_string());
            }
        }

        let reftest = Reftest {
            name: format!("{} {} {}", test_line.file_left, test_line.kind, test_line.file_right),
            kind: kind,
            files: [file_left, file_right],
            id: id_offset + tests.len(),
            render_mode: render_mode,
            servo_args: servo_args.iter().map(|x| x.clone()).collect(),
            is_flaky: render_mode.intersects(flakiness),
            experimental: experimental,
            fragment_identifier: fragment_identifier,
        };

        tests.push(make_test(reftest));
    }
    tests
}

fn make_test(reftest: Reftest) -> TestDescAndFn {
    let name = reftest.name.clone();
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(name),
            ignore: false,
            should_fail: false,
        },
        testfn: DynTestFn(proc() {
            check_reftest(reftest);
        }),
    }
}

fn capture(reftest: &Reftest, side: uint) -> (u32, u32, Vec<u8>) {
    let png_filename = format!("/tmp/servo-reftest-{:06u}-{:u}.png", reftest.id, side);
    let mut command = Command::new(os::self_exe_path().unwrap().join("servo"));
    command
        .args(reftest.servo_args.as_slice())
        // Allows pixel perfect rendering of Ahem font for reftests.
        .arg("-Z")
        .arg("disable-text-aa")
        .args(["-f", "-o"])
        .arg(png_filename.as_slice())
        .arg({
            let mut url = Url::from_file_path(&reftest.files[side]).unwrap();
            url.fragment = reftest.fragment_identifier.clone();
            url.to_string()
        });
    // CPU rendering is the default
    if reftest.render_mode.contains(CPU_RENDERING) {
        command.arg("-c");
    }
    if reftest.render_mode.contains(GPU_RENDERING) {
        command.arg("-g");
    }
    if reftest.experimental {
        command.arg("--experimental");
    }
    let retval = match command.status() {
        Ok(status) => status,
        Err(e) => panic!("failed to execute process: {}", e),
    };
    assert_eq!(retval, ExitStatus(0));

    let image = png::load_png(&from_str::<Path>(png_filename.as_slice()).unwrap()).unwrap();
    let rgba8_bytes = match image.pixels {
        png::RGBA8(pixels) => pixels,
        _ => panic!(),
    };
    (image.width, image.height, rgba8_bytes)
}

fn check_reftest(reftest: Reftest) {
    let (left_width, left_height, left_bytes) = capture(&reftest, 0);
    let (right_width, right_height, right_bytes) = capture(&reftest, 1);

    assert_eq!(left_width, right_width);
    assert_eq!(left_height, right_height);

    let left_all_white = left_bytes.iter().all(|&p| p == 255);
    let right_all_white = right_bytes.iter().all(|&p| p == 255);

    if left_all_white && right_all_white {
        panic!("Both renderings are empty")
    }

    let pixels = left_bytes.iter().zip(right_bytes.iter()).map(|(&a, &b)| {
        if a as i8 - b as i8 == 0 {
            // White for correct
            0xFF
        } else {
            // "1100" in the RGBA channel with an error for an incorrect value
            // This results in some number of C0 and FFs, which is much more
            // readable (and distinguishable) than the previous difference-wise
            // scaling but does not require reconstructing the actual RGBA pixel.
            0xC0
        }
    }).collect::<Vec<u8>>();

    if pixels.iter().any(|&a| a < 255) {
        let output_str = format!("/tmp/servo-reftest-{:06u}-diff.png", reftest.id);
        let output = from_str::<Path>(output_str.as_slice()).unwrap();

        let mut img = png::Image {
            width: left_width,
            height: left_height,
            pixels: png::RGBA8(pixels),
        };
        let res = png::store_png(&mut img, &output);
        assert!(res.is_ok());

        match (reftest.kind, reftest.is_flaky) {
            (Same, true) => println!("flaky test - rendering difference: {}", output_str),
            (Same, false) => panic!("rendering difference: {}", output_str),
            (Different, _) => {}   // Result was different and that's what was expected
        }
    } else {
        assert!(reftest.is_flaky || reftest.kind == Same);
    }
}
<commit_msg>More target path fixup.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(unused_imports)]
#![deny(unused_variables)]

extern crate png;
extern crate test;
extern crate regex;
extern crate url;

use std::ascii::AsciiExt;
use std::io;
use std::io::{File, Reader, Command, IoResult};
use std::io::process::ExitStatus;
use std::io::fs::PathExtensions;
use std::os;
use std::path::Path;
use test::{AutoColor, DynTestName, DynTestFn, TestDesc, TestOpts, TestDescAndFn};
use test::run_tests_console;
use regex::Regex;
use url::Url;

bitflags!(
    flags RenderMode: u32 {
        const CPU_RENDERING  = 0x00000001,
        const GPU_RENDERING  = 0x00000010,
        const LINUX_TARGET   = 0x00000100,
        const MACOS_TARGET   = 0x00001000,
        const ANDROID_TARGET = 0x00010000
    }
)

fn main() {
    let args = os::args();
    let mut parts = args.tail().split(|e| "--" == e.as_slice());

    let harness_args = parts.next().unwrap();  // .split() is never empty
    let servo_args = parts.next().unwrap_or(&[]);

    let (render_mode_string, base_path, testname) = match harness_args {
        [] | [_] => panic!("USAGE: cpu|gpu base_path [testname regex]"),
        [ref render_mode_string, ref base_path] => (render_mode_string, base_path, None),
        [ref render_mode_string, ref base_path, ref testname, ..] => (render_mode_string, base_path, Some(Regex::new(testname.as_slice()).unwrap())),
    };

    let mut render_mode = match render_mode_string.as_slice() {
        "cpu" => CPU_RENDERING,
        "gpu" => GPU_RENDERING,
        _ => panic!("First argument must specify cpu or gpu as rendering mode")
    };
    if cfg!(target_os = "linux") {
        render_mode.insert(LINUX_TARGET);
    }
    if cfg!(target_os = "macos") {
        render_mode.insert(MACOS_TARGET);
    }
    if cfg!(target_os = "android") {
        render_mode.insert(ANDROID_TARGET);
    }

    let mut all_tests = vec!();
    println!("Scanning {} for manifests\n", base_path);

    for file in io::fs::walk_dir(&Path::new(base_path.as_slice())).unwrap() {
        let maybe_extension = file.extension_str();
        match maybe_extension {
            Some(extension) => {
                if extension.to_ascii_lower().as_slice() == "list" && file.is_file() {
                    let tests = parse_lists(&file, servo_args, render_mode, all_tests.len());
                    println!("\t{} [{} tests]", file.display(), tests.len());
                    all_tests.extend(tests.into_iter());
                }
            }
            _ => {}
        }
    }

    let test_opts = TestOpts {
        filter: testname,
        run_ignored: false,
        logfile: None,
        run_tests: true,
        run_benchmarks: false,
        ratchet_noise_percent: None,
        ratchet_metrics: None,
        save_metrics: None,
        test_shard: None,
        nocapture: false,
        color: AutoColor
    };

    match run(test_opts,
              all_tests,
              servo_args.iter().map(|x| x.clone()).collect()) {
        Ok(false) => os::set_exit_status(1), // tests failed
        Err(_) => os::set_exit_status(2),    // I/O-related failure
        _ => (),
    }
}

fn run(test_opts: TestOpts, all_tests: Vec<TestDescAndFn>,
       servo_args: Vec<String>) -> IoResult<bool> {
    // Verify that we're passing in valid servo arguments. Otherwise, servo
    // will exit before we've run any tests, and it will appear to us as if
    // all the tests are failing.
    let mut command = match Command::new(os::self_exe_path().unwrap().join("servo"))
                            .args(servo_args.as_slice()).spawn() {
        Ok(p) => p,
        Err(e) => panic!("failed to execute process: {}", e),
    };
    let stderr = command.stderr.as_mut().unwrap().read_to_string().unwrap();

    if stderr.as_slice().contains("Unrecognized") {
        println!("Servo: {}", stderr.as_slice());
        return Ok(false);
    }

    run_tests_console(&test_opts, all_tests)
}

#[deriving(PartialEq)]
enum ReftestKind {
    Same,
    Different,
}

struct Reftest {
    name: String,
    kind: ReftestKind,
    files: [Path, ..2],
    id: uint,
    servo_args: Vec<String>,
    render_mode: RenderMode,
    is_flaky: bool,
    experimental: bool,
    fragment_identifier: Option<String>,
}

struct TestLine<'a> {
    conditions: &'a str,
    kind: &'a str,
    file_left: &'a str,
    file_right: &'a str,
}

fn parse_lists(file: &Path, servo_args: &[String], render_mode: RenderMode, id_offset: uint) -> Vec<TestDescAndFn> {
    let mut tests = Vec::new();
    let contents = File::open_mode(file, io::Open, io::Read)
                       .and_then(|mut f| f.read_to_string())
                       .ok().expect("Could not read file");

    for line in contents.as_slice().lines() {
        // ignore comments or empty lines
        if line.starts_with("#") || line.is_empty() {
            continue;
        }

        let parts: Vec<&str> = line.split(' ').filter(|p| !p.is_empty()).collect();

        let test_line = match parts.len() {
            3 => TestLine {
                conditions: "",
                kind: parts[0],
                file_left: parts[1],
                file_right: parts[2],
            },
            4 => TestLine {
                conditions: parts[0],
                kind: parts[1],
                file_left: parts[2],
                file_right: parts[3],
            },
            _ => panic!("reftest line: '{:s}' doesn't match '[CONDITIONS] KIND LEFT RIGHT'", line),
        };

        let kind = match test_line.kind {
            "==" => Same,
            "!=" => Different,
            part => panic!("reftest line: '{:s}' has invalid kind '{:s}'", line, part)
        };

        // If we're running this directly, file.dir_path() might be relative.
        // (see issue #3521)
        let base = match file.dir_path().is_relative() {
            true  => os::getcwd().join(file.dir_path()),
            false => file.dir_path()
        };

        let file_left =  base.join(test_line.file_left);
        let file_right = base.join(test_line.file_right);

        let mut conditions_list = test_line.conditions.split(',');
        let mut flakiness = RenderMode::empty();
        let mut experimental = false;
        let mut fragment_identifier = None;
        for condition in conditions_list {
            match condition {
                "flaky_cpu" => flakiness.insert(CPU_RENDERING),
                "flaky_gpu" => flakiness.insert(GPU_RENDERING),
                "flaky_linux" => flakiness.insert(LINUX_TARGET),
                "flaky_macos" => flakiness.insert(MACOS_TARGET),
                "experimental" => experimental = true,
                _ => (),
            }
            if condition.starts_with("fragment=") {
                fragment_identifier = Some(condition.slice_from("fragment=".len()).to_string());
            }
        }

        let reftest = Reftest {
            name: format!("{} {} {}", test_line.file_left, test_line.kind, test_line.file_right),
            kind: kind,
            files: [file_left, file_right],
            id: id_offset + tests.len(),
            render_mode: render_mode,
            servo_args: servo_args.iter().map(|x| x.clone()).collect(),
            is_flaky: render_mode.intersects(flakiness),
            experimental: experimental,
            fragment_identifier: fragment_identifier,
        };

        tests.push(make_test(reftest));
    }
    tests
}

fn make_test(reftest: Reftest) -> TestDescAndFn {
    let name = reftest.name.clone();
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(name),
            ignore: false,
            should_fail: false,
        },
        testfn: DynTestFn(proc() {
            check_reftest(reftest);
        }),
    }
}

fn capture(reftest: &Reftest, side: uint) -> (u32, u32, Vec<u8>) {
    let png_filename = format!("/tmp/servo-reftest-{:06u}-{:u}.png", reftest.id, side);
    let mut command = Command::new(os::self_exe_path().unwrap().join("servo"));
    command
        .args(reftest.servo_args.as_slice())
        // Allows pixel perfect rendering of Ahem font for reftests.
        .arg("-Z")
        .arg("disable-text-aa")
        .args(["-f", "-o"])
        .arg(png_filename.as_slice())
        .arg({
            let mut url = Url::from_file_path(&reftest.files[side]).unwrap();
            url.fragment = reftest.fragment_identifier.clone();
            url.to_string()
        });
    // CPU rendering is the default
    if reftest.render_mode.contains(CPU_RENDERING) {
        command.arg("-c");
    }
    if reftest.render_mode.contains(GPU_RENDERING) {
        command.arg("-g");
    }
    if reftest.experimental {
        command.arg("--experimental");
    }
    let retval = match command.status() {
        Ok(status) => status,
        Err(e) => panic!("failed to execute process: {}", e),
    };
    assert_eq!(retval, ExitStatus(0));

    let image = png::load_png(&from_str::<Path>(png_filename.as_slice()).unwrap()).unwrap();
    let rgba8_bytes = match image.pixels {
        png::RGBA8(pixels) => pixels,
        _ => panic!(),
    };
    (image.width, image.height, rgba8_bytes)
}

fn check_reftest(reftest: Reftest) {
    let (left_width, left_height, left_bytes) = capture(&reftest, 0);
    let (right_width, right_height, right_bytes) = capture(&reftest, 1);

    assert_eq!(left_width, right_width);
    assert_eq!(left_height, right_height);

    let left_all_white = left_bytes.iter().all(|&p| p == 255);
    let right_all_white = right_bytes.iter().all(|&p| p == 255);

    if left_all_white && right_all_white {
        panic!("Both renderings are empty")
    }

    let pixels = left_bytes.iter().zip(right_bytes.iter()).map(|(&a, &b)| {
        if a as i8 - b as i8 == 0 {
            // White for correct
            0xFF
        } else {
            // "1100" in the RGBA channel with an error for an incorrect value
            // This results in some number of C0 and FFs, which is much more
            // readable (and distinguishable) than the previous difference-wise
            // scaling but does not require reconstructing the actual RGBA pixel.
            0xC0
        }
    }).collect::<Vec<u8>>();

    if pixels.iter().any(|&a| a < 255) {
        let output_str = format!("/tmp/servo-reftest-{:06u}-diff.png", reftest.id);
        let output = from_str::<Path>(output_str.as_slice()).unwrap();

        let mut img = png::Image {
            width: left_width,
            height: left_height,
            pixels: png::RGBA8(pixels),
        };
        let res = png::store_png(&mut img, &output);
        assert!(res.is_ok());

        match (reftest.kind, reftest.is_flaky) {
            (Same, true) => println!("flaky test - rendering difference: {}", output_str),
            (Same, false) => panic!("rendering difference: {}", output_str),
            (Different, _) => {}   // Result was different and that's what was expected
        }
    } else {
        assert!(reftest.is_flaky || reftest.kind == Same);
    }
}
<|endoftext|>


<commit_before>type Deadlock = Option<uint>;

static mut lock: Deadlock = None;
static mut anotherLock: Deadlock = None;

fn grab_lock(id: uint) {
    unsafe {
	while (lock.is_some()) {
	    ;
	}
	lock = Some(id);
    }
}

fn grab_anotherLock(id: uint) {
    unsafe {
	while (anotherLock.is_some()) {
	    ;
	}
	anotherLock = Some(id);
    }
}

fn release_lock() {
    unsafe {
	lock = None;
    }
}

fn release_anotherLock() {
    unsafe {
	anotherLock = None;
    }
}

fn update_process_1(id: uint) {
    unsafe {
	//while (update(id + 1) != id + 1) {
	  //  ;
	//}
	grab_anotherLock(id);
	println("Process 1 grabbed lock 2");
	release_lock();
    }
}

fn update_process_2(id: uint) {
    grab_lock(id);
    println("Process 2 grabbed lock 1");
    release_anotherLock();
}

fn main() {
    grab_lock(1);
    grab_anotherLock(2);
    do spawn {
	update_process_1(1);
	update_process_2(2);
    }
}
<commit_msg>updated<commit_after>type Deadlock = Option<uint>;

static mut lock: Deadlock = None;
static mut anotherLock: Deadlock = None;

fn grab_lock(id: uint) {
    unsafe {
	while (lock.is_some()) {
	    ;
	}
	lock = Some(id);
    }
}

fn grab_anotherLock(id: uint) {
    unsafe {
	while (anotherLock.is_some()) {
	    ;
	}
	anotherLock = Some(id);
    }
}

fn release_lock() {
    unsafe {
	lock = None;
    }
}

fn release_anotherLock() {
    unsafe {
	anotherLock = None;
    }
}

fn update_process_1(id: uint) {
    unsafe {
	//while (update(id + 1) != id + 1) {
	  //  ;
	//}
	grab_lock(id);
	println("Process 1 grabbed lock 1");
	grab_anotherLock(id);
	println("Process 1 grabbed lock 2");
	release_lock();
	release_anotherLock();
    }
}

fn update_process_2(id: uint) {
    grab_anotherLock(id);
    println("Process 2 grabbed lick 2");
    grab_lock(id);
    println("Process 2 grabbed lock 1");
    release_anotherLock();
    release_lock();
}

fn main() {
    let mut i: uint = 0;
    while i < 10000 {
	do spawn {
	    update_process_1(1);
	}
	do spawn {
	    update_process_2(2);
	}
	i += 1;
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
    html_root_url = "https://rust-random.github.io/rand/"
)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![allow(
    clippy::excessive_precision,
    clippy::float_cmp,
    clippy::unreadable_literal
)]
#![allow(clippy::neg_cmp_op_on_partial_ord)] // suggested fix too verbose
#![no_std]
#![cfg_attr(doc_cfg, feature(doc_cfg))]

//! Generating random samples from probability distributions.
//!
//! ## Re-exports
//!
//! This crate is a super-set of the [`rand::distributions`] module. See the
//! [`rand::distributions`] module documentation for an overview of the core
//! [`Distribution`] trait and implementations.
//!
//! The following are re-exported:
//!
//! - The [`Distribution`] trait and [`DistIter`] helper type
//! - The [`Standard`], [`Alphanumeric`], [`Uniform`], [`OpenClosed01`],
//! [`Open01`], [`Bernoulli`], and [`WeightedIndex`] distributions
//!
//! ## Distributions
//!
//! This crate provides the following probability distributions:
//!
//! - Related to real-valued quantities that grow linearly
//!   (e.g. errors, offsets):
//!   - [`Normal`] distribution, and [`StandardNormal`] as a primitive
//!   - [`Cauchy`] distribution
//! - Related to Bernoulli trials (yes/no events, with a given probability):
//!   - [`Binomial`] distribution
//! - Related to positive real-valued quantities that grow exponentially
//!   (e.g. prices, incomes, populations):
//!   - [`LogNormal`] distribution
//! - Related to the occurrence of independent events at a given rate:
//!   - [`Pareto`] distribution
//!   - [`Poisson`] distribution
//!   - [`Exp`]onential distribution, and [`Exp1`] as a primitive
//!   - [`Weibull`] distribution
//! - Gamma and derived distributions:
//!   - [`Gamma`] distribution
//!   - [`ChiSquared`] distribution
//!   - [`StudentT`] distribution
//!   - [`FisherF`] distribution
//! - Triangular distribution:
//!   - [`Beta`] distribution
//!   - [`Triangular`] distribution
//! - Multivariate probability distributions
//!   - [`Dirichlet`] distribution
//!   - [`UnitSphere`] distribution
//!   - [`UnitBall`] distribution
//!   - [`UnitCircle`] distribution
//!   - [`UnitDisc`] distribution
//! - Misc. distributions
//!   - [`InverseGaussian`] distribution
//!   - [`NormalInverseGaussian`] distribution

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "std")]
extern crate std;

pub use rand::distributions::{
    uniform, Alphanumeric, Bernoulli, BernoulliError, DistIter, Distribution, Open01, OpenClosed01,
    Standard, Uniform,
};

pub use self::binomial::{Binomial, Error as BinomialError};
pub use self::cauchy::{Cauchy, Error as CauchyError};
#[cfg(feature = "alloc")]
pub use self::dirichlet::{Dirichlet, Error as DirichletError};
pub use self::exponential::{Error as ExpError, Exp, Exp1};
pub use self::gamma::{
    Beta, BetaError, ChiSquared, ChiSquaredError, Error as GammaError, FisherF, FisherFError,
    Gamma, StudentT,
};
pub use self::inverse_gaussian::{InverseGaussian, Error as InverseGaussianError};
pub use self::normal::{Error as NormalError, LogNormal, Normal, StandardNormal};
pub use self::normal_inverse_gaussian::{NormalInverseGaussian, Error as NormalInverseGaussianError};
pub use self::pareto::{Error as ParetoError, Pareto};
pub use self::pert::{Pert, PertError};
pub use self::poisson::{Error as PoissonError, Poisson};
pub use self::triangular::{Triangular, TriangularError};
pub use self::unit_ball::UnitBall;
pub use self::unit_circle::UnitCircle;
pub use self::unit_disc::UnitDisc;
pub use self::unit_sphere::UnitSphere;
pub use self::weibull::{Error as WeibullError, Weibull};
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub use rand::distributions::{WeightedError, WeightedIndex};
#[cfg(feature = "alloc")]
pub use weighted_alias::WeightedAliasIndex;

pub use num_traits;

#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub mod weighted_alias;

mod binomial;
mod cauchy;
mod dirichlet;
mod exponential;
mod gamma;
mod inverse_gaussian;
mod normal;
mod normal_inverse_gaussian;
mod pareto;
mod pert;
mod poisson;
mod triangular;
mod unit_ball;
mod unit_circle;
mod unit_disc;
mod unit_sphere;
mod utils;
mod weibull;
mod ziggurat_tables;

#[cfg(test)]
mod test {
    // Notes on testing
    //
    // Testing random number distributions correctly is hard. The following
    // testing is desired:
    //
    // - Construction: test initialisation with a few valid parameter sets.
    // - Erroneous usage: test that incorrect usage generates an error.
    // - Vector: test that usage with fixed inputs (including RNG) generates a
    //   fixed output sequence on all platforms.
    // - Correctness at fixed points (optional): using a specific mock RNG,
    //   check that specific values are sampled (e.g. end-points and median of
    //   distribution).
    // - Correctness of PDF (extra): generate a histogram of samples within a
    //   certain range, and check this approximates the PDF. These tests are
    //   expected to be expensive, and should be behind a feature-gate.
    //
    // TODO: Vector and correctness tests are largely absent so far.
    // NOTE: Some distributions have tests checking only that samples can be
    // generated. This is redundant with vector and correctness tests.

    /// Construct a deterministic RNG with the given seed
    pub fn rng(seed: u64) -> impl rand::RngCore {
        // For tests, we want a statistically good, fast, reproducible RNG.
        // PCG32 will do fine, and will be easy to embed if we ever need to.
        const INC: u64 = 11634580027462260723;
        rand_pcg::Pcg32::new(seed, INC)
    }
}
<commit_msg>Mention `WeightedAliasIndex` in list of distributions<commit_after>// Copyright 2019 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
    html_root_url = "https://rust-random.github.io/rand/"
)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![allow(
    clippy::excessive_precision,
    clippy::float_cmp,
    clippy::unreadable_literal
)]
#![allow(clippy::neg_cmp_op_on_partial_ord)] // suggested fix too verbose
#![no_std]
#![cfg_attr(doc_cfg, feature(doc_cfg))]

//! Generating random samples from probability distributions.
//!
//! ## Re-exports
//!
//! This crate is a super-set of the [`rand::distributions`] module. See the
//! [`rand::distributions`] module documentation for an overview of the core
//! [`Distribution`] trait and implementations.
//!
//! The following are re-exported:
//!
//! - The [`Distribution`] trait and [`DistIter`] helper type
//! - The [`Standard`], [`Alphanumeric`], [`Uniform`], [`OpenClosed01`],
//! [`Open01`], [`Bernoulli`], and [`WeightedIndex`] distributions
//!
//! ## Distributions
//!
//! This crate provides the following probability distributions:
//!
//! - Related to real-valued quantities that grow linearly
//!   (e.g. errors, offsets):
//!   - [`Normal`] distribution, and [`StandardNormal`] as a primitive
//!   - [`Cauchy`] distribution
//! - Related to Bernoulli trials (yes/no events, with a given probability):
//!   - [`Binomial`] distribution
//! - Related to positive real-valued quantities that grow exponentially
//!   (e.g. prices, incomes, populations):
//!   - [`LogNormal`] distribution
//! - Related to the occurrence of independent events at a given rate:
//!   - [`Pareto`] distribution
//!   - [`Poisson`] distribution
//!   - [`Exp`]onential distribution, and [`Exp1`] as a primitive
//!   - [`Weibull`] distribution
//! - Gamma and derived distributions:
//!   - [`Gamma`] distribution
//!   - [`ChiSquared`] distribution
//!   - [`StudentT`] distribution
//!   - [`FisherF`] distribution
//! - Triangular distribution:
//!   - [`Beta`] distribution
//!   - [`Triangular`] distribution
//! - Multivariate probability distributions
//!   - [`Dirichlet`] distribution
//!   - [`UnitSphere`] distribution
//!   - [`UnitBall`] distribution
//!   - [`UnitCircle`] distribution
//!   - [`UnitDisc`] distribution
//! - Alternative implementation for weighted index sampling
//!   - [`WeightedAliasIndex`] distribution
//! - Misc. distributions
//!   - [`InverseGaussian`] distribution
//!   - [`NormalInverseGaussian`] distribution

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "std")]
extern crate std;

pub use rand::distributions::{
    uniform, Alphanumeric, Bernoulli, BernoulliError, DistIter, Distribution, Open01, OpenClosed01,
    Standard, Uniform,
};

pub use self::binomial::{Binomial, Error as BinomialError};
pub use self::cauchy::{Cauchy, Error as CauchyError};
#[cfg(feature = "alloc")]
pub use self::dirichlet::{Dirichlet, Error as DirichletError};
pub use self::exponential::{Error as ExpError, Exp, Exp1};
pub use self::gamma::{
    Beta, BetaError, ChiSquared, ChiSquaredError, Error as GammaError, FisherF, FisherFError,
    Gamma, StudentT,
};
pub use self::inverse_gaussian::{InverseGaussian, Error as InverseGaussianError};
pub use self::normal::{Error as NormalError, LogNormal, Normal, StandardNormal};
pub use self::normal_inverse_gaussian::{NormalInverseGaussian, Error as NormalInverseGaussianError};
pub use self::pareto::{Error as ParetoError, Pareto};
pub use self::pert::{Pert, PertError};
pub use self::poisson::{Error as PoissonError, Poisson};
pub use self::triangular::{Triangular, TriangularError};
pub use self::unit_ball::UnitBall;
pub use self::unit_circle::UnitCircle;
pub use self::unit_disc::UnitDisc;
pub use self::unit_sphere::UnitSphere;
pub use self::weibull::{Error as WeibullError, Weibull};
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub use rand::distributions::{WeightedError, WeightedIndex};
#[cfg(feature = "alloc")]
pub use weighted_alias::WeightedAliasIndex;

pub use num_traits;

#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub mod weighted_alias;

mod binomial;
mod cauchy;
mod dirichlet;
mod exponential;
mod gamma;
mod inverse_gaussian;
mod normal;
mod normal_inverse_gaussian;
mod pareto;
mod pert;
mod poisson;
mod triangular;
mod unit_ball;
mod unit_circle;
mod unit_disc;
mod unit_sphere;
mod utils;
mod weibull;
mod ziggurat_tables;

#[cfg(test)]
mod test {
    // Notes on testing
    //
    // Testing random number distributions correctly is hard. The following
    // testing is desired:
    //
    // - Construction: test initialisation with a few valid parameter sets.
    // - Erroneous usage: test that incorrect usage generates an error.
    // - Vector: test that usage with fixed inputs (including RNG) generates a
    //   fixed output sequence on all platforms.
    // - Correctness at fixed points (optional): using a specific mock RNG,
    //   check that specific values are sampled (e.g. end-points and median of
    //   distribution).
    // - Correctness of PDF (extra): generate a histogram of samples within a
    //   certain range, and check this approximates the PDF. These tests are
    //   expected to be expensive, and should be behind a feature-gate.
    //
    // TODO: Vector and correctness tests are largely absent so far.
    // NOTE: Some distributions have tests checking only that samples can be
    // generated. This is redundant with vector and correctness tests.

    /// Construct a deterministic RNG with the given seed
    pub fn rng(seed: u64) -> impl rand::RngCore {
        // For tests, we want a statistically good, fast, reproducible RNG.
        // PCG32 will do fine, and will be easy to embed if we ever need to.
        const INC: u64 = 11634580027462260723;
        rand_pcg::Pcg32::new(seed, INC)
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test for the subregion constraints. In this case, the region R3 on
// `p` includes two disjoint regions of the control-flow graph. The
// borrows in `&v[0]` and `&v[1]` each (in theory) have to outlive R3,
// but only at a particular point, and hence they wind up including
// distinct regions.

// compile-flags:-Zborrowck=mir -Zverbose
//                              ^^^^^^^^^ force compiler to dump more region information

#![allow(warnings)]

fn use_x(_: usize) -> bool { true }

fn main() {
    let mut v = [1, 2, 3];
    let mut p = &v[0];
    if true {
        use_x(*p);
    } else {
        use_x(22);
    }

    p = &v[1];
    use_x(*p);
}

// END RUST SOURCE
// START rustc.main.nll.0.mir
// | '_#2r    | {bb2[0..=1], bb3[0..=1]}
// ...
// | '_#4r    | {bb8[1..=4]}
// | '_#5r    | {bb2[1], bb3[0..=1], bb8[2..=4]}
// ...
// let mut _2: &'_#5r usize;
// ...
// _2 = &'_#2r _1[_3];
// ...
// _2 = &'_#4r (*_10);
// END rustc.main.nll.0.mir
<commit_msg>"fix" test region-liveness-two-disjoint-uses<commit_after>// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test for the subregion constraints. In this case, the region R3 on
// `p` includes two disjoint regions of the control-flow graph. The
// borrows in `&v[0]` and `&v[1]` each (in theory) have to outlive R3,
// but only at a particular point, and hence they wind up including
// distinct regions.
//
// FIXME(#43234) -- Well, this used to be true, but we modified NLL
// for the time being to not take location into account.

// compile-flags:-Zborrowck=mir -Zverbose
//                              ^^^^^^^^^ force compiler to dump more region information

#![allow(warnings)]

fn use_x(_: usize) -> bool { true }

fn main() {
    let mut v = [1, 2, 3];
    let mut p = &v[0];
    if true {
        use_x(*p);
    } else {
        use_x(22);
    }

    p = &v[1];
    use_x(*p);
}

// END RUST SOURCE
// START rustc.main.nll.0.mir
// | '_#2r    | {bb2[0..=1], bb3[0..=1], bb8[2..=4]}
// ...
// | '_#4r    | {bb2[1], bb3[0..=1], bb8[1..=4]}
// | '_#5r    | {bb2[1], bb3[0..=1], bb8[2..=4]}
// ...
// let mut _2: &'_#5r usize;
// ...
// _2 = &'_#2r _1[_3];
// ...
// _2 = &'_#4r (*_10);
// END rustc.main.nll.0.mir
<|endoftext|>


<commit_before>// xfail-test

fn f() -> float { (fail "boo") as float / 2.0 }

fn main() { }<commit_msg>test: Remove pretty/issue-953. Doesn't typecheck<commit_after><|endoftext|>


<commit_before>#![cfg(feature = "toml")]

use serde_derive::Deserialize;
use std::path::PathBuf;

use config::{Config, File, FileFormat, Map, Value};
use float_cmp::ApproxEqUlps;

#[derive(Debug, Deserialize)]
struct Place {
    number: PlaceNumber,
    name: String,
    longitude: f64,
    latitude: f64,
    favorite: bool,
    telephone: Option<String>,
    reviews: u64,
    creator: Map<String, Value>,
    rating: Option<f32>,
}

#[derive(Debug, Deserialize, PartialEq)]
struct PlaceNumber(u8);

#[derive(Debug, Deserialize, PartialEq)]
struct AsciiCode(i8);

#[derive(Debug, Deserialize)]
struct Settings {
    debug: f64,
    production: Option<String>,
    code: AsciiCode,
    place: Place,
    #[serde(rename = "arr")]
    elements: Vec<String>,
}

#[cfg(test)]
fn make() -> Config {
    let mut c = Config::default();
    c.merge(File::new("tests/Settings", FileFormat::Toml))
        .unwrap();

    c
}

#[test]
fn test_file() {
    let c = make();

    // Deserialize the entire file as single struct
    let s: Settings = c.try_deserialize().unwrap();

    assert!(s.debug.approx_eq_ulps(&1.0, 2));
    assert_eq!(s.production, Some("false".to_string()));
    assert_eq!(s.code, AsciiCode(53));
    assert_eq!(s.place.number, PlaceNumber(1));
    assert_eq!(s.place.name, "Torre di Pisa");
    assert!(s.place.longitude.approx_eq_ulps(&43.722_498_5, 2));
    assert!(s.place.latitude.approx_eq_ulps(&10.397_052_2, 2));
    assert!(!s.place.favorite);
    assert_eq!(s.place.reviews, 3866);
    assert_eq!(s.place.rating, Some(4.5));
    assert_eq!(s.place.telephone, None);
    assert_eq!(s.elements.len(), 10);
    assert_eq!(s.elements[3], "4".to_string());
    if cfg!(feature = "preserve_order") {
        assert_eq!(
            s.place
                .creator
                .into_iter()
                .collect::<Vec<(String, config::Value)>>(),
            vec![
                ("name".to_string(), "John Smith".into()),
                ("username".into(), "jsmith".into()),
                ("email".into(), "jsmith@localhost".into()),
            ]
        );
    } else {
        assert_eq!(
            s.place.creator["name"].clone().into_string().unwrap(),
            "John Smith".to_string()
        );
    }
}

#[test]
fn test_error_parse() {
    let mut c = Config::default();
    let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Toml));

    let path_with_extension: PathBuf = ["tests", "Settings-invalid.toml"].iter().collect();

    assert!(res.is_err());
    assert_eq!(
        res.unwrap_err().to_string(),
        format!(
            "invalid TOML value, did you mean to use a quoted string? at line 2 column 9 in {}",
            path_with_extension.display()
        )
    );
}
<commit_msg>Fix clippy: Derive Eq as well<commit_after>#![cfg(feature = "toml")]

use serde_derive::Deserialize;
use std::path::PathBuf;

use config::{Config, File, FileFormat, Map, Value};
use float_cmp::ApproxEqUlps;

#[derive(Debug, Deserialize)]
struct Place {
    number: PlaceNumber,
    name: String,
    longitude: f64,
    latitude: f64,
    favorite: bool,
    telephone: Option<String>,
    reviews: u64,
    creator: Map<String, Value>,
    rating: Option<f32>,
}

#[derive(Debug, Deserialize, PartialEq, Eq)]
struct PlaceNumber(u8);

#[derive(Debug, Deserialize, PartialEq, Eq)]
struct AsciiCode(i8);

#[derive(Debug, Deserialize)]
struct Settings {
    debug: f64,
    production: Option<String>,
    code: AsciiCode,
    place: Place,
    #[serde(rename = "arr")]
    elements: Vec<String>,
}

#[cfg(test)]
fn make() -> Config {
    let mut c = Config::default();
    c.merge(File::new("tests/Settings", FileFormat::Toml))
        .unwrap();

    c
}

#[test]
fn test_file() {
    let c = make();

    // Deserialize the entire file as single struct
    let s: Settings = c.try_deserialize().unwrap();

    assert!(s.debug.approx_eq_ulps(&1.0, 2));
    assert_eq!(s.production, Some("false".to_string()));
    assert_eq!(s.code, AsciiCode(53));
    assert_eq!(s.place.number, PlaceNumber(1));
    assert_eq!(s.place.name, "Torre di Pisa");
    assert!(s.place.longitude.approx_eq_ulps(&43.722_498_5, 2));
    assert!(s.place.latitude.approx_eq_ulps(&10.397_052_2, 2));
    assert!(!s.place.favorite);
    assert_eq!(s.place.reviews, 3866);
    assert_eq!(s.place.rating, Some(4.5));
    assert_eq!(s.place.telephone, None);
    assert_eq!(s.elements.len(), 10);
    assert_eq!(s.elements[3], "4".to_string());
    if cfg!(feature = "preserve_order") {
        assert_eq!(
            s.place
                .creator
                .into_iter()
                .collect::<Vec<(String, config::Value)>>(),
            vec![
                ("name".to_string(), "John Smith".into()),
                ("username".into(), "jsmith".into()),
                ("email".into(), "jsmith@localhost".into()),
            ]
        );
    } else {
        assert_eq!(
            s.place.creator["name"].clone().into_string().unwrap(),
            "John Smith".to_string()
        );
    }
}

#[test]
fn test_error_parse() {
    let mut c = Config::default();
    let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Toml));

    let path_with_extension: PathBuf = ["tests", "Settings-invalid.toml"].iter().collect();

    assert!(res.is_err());
    assert_eq!(
        res.unwrap_err().to_string(),
        format!(
            "invalid TOML value, did you mean to use a quoted string? at line 2 column 9 in {}",
            path_with_extension.display()
        )
    );
}
<|endoftext|>


<commit_before>//! Define [Texture] and [Pixel] for a generic [Image](image::GenericImage).
use crate::texture::{Pixel, Texture};
use image::{GenericImage, Rgb, Rgba};

impl<P: Pixel + image::Pixel, I: GenericImage<Pixel = P>> Texture for I {
    type Pixel = I::Pixel;

    fn width(&self) -> u32 {
        self.dimensions().0
    }

    fn height(&self) -> u32 {
        self.dimensions().1
    }

    fn get(&self, x: u32, y: u32) -> Option<I::Pixel> {
        if self.in_bounds(x, y) {
            Some(self.get_pixel(x, y))
        } else {
            None
        }
    }

    fn set(&mut self, x: u32, y: u32, val: I::Pixel) {
        self.put_pixel(x, y, val);
    }
}

impl Pixel for Rgba<u8> {
    fn is_transparent(&self) -> bool {
        self[3] == 0
    }

    fn transparency() -> Option<Rgba<u8>> {
        Some(Rgba([0; 4]))
    }

    fn outline() -> Rgba<u8> {
        Rgba([255, 0, 0, 255])
    }
}

impl Pixel for Rgb<u8> {
    fn is_transparent(&self) -> bool {
        false
    }

    fn transparency() -> Option<Rgb<u8>> {
        None
    }

    fn outline() -> Rgb<u8> {
        Rgb([255, 0, 0])
    }
}
<commit_msg>Implemented Pixel for all image primitives<commit_after>//! Define [Texture] and [Pixel] for a generic [Image](image::GenericImage).
use crate::texture::{Pixel, Texture};
use image::{GenericImage, Primitive, Rgb, Rgba};

impl<P: Pixel + image::Pixel, I: GenericImage<Pixel = P>> Texture for I {
    type Pixel = I::Pixel;

    fn width(&self) -> u32 {
        self.dimensions().0
    }

    fn height(&self) -> u32 {
        self.dimensions().1
    }

    fn get(&self, x: u32, y: u32) -> Option<I::Pixel> {
        if self.in_bounds(x, y) {
            Some(self.get_pixel(x, y))
        } else {
            None
        }
    }

    fn set(&mut self, x: u32, y: u32, val: I::Pixel) {
        self.put_pixel(x, y, val);
    }
}

impl<T: Primitive> Pixel for Rgb<T> {
    fn is_transparent(&self) -> bool {
        false
    }

    fn transparency() -> Option<Rgb<T>> {
        None
    }

    fn outline() -> Rgb<T> {
        Rgb([
            T::DEFAULT_MAX_VALUE,
            T::DEFAULT_MIN_VALUE,
            T::DEFAULT_MIN_VALUE,
        ])
    }
}

impl<T: Primitive> Pixel for Rgba<T> {
    fn is_transparent(&self) -> bool {
        self[3] == T::DEFAULT_MIN_VALUE
    }

    fn transparency() -> Option<Rgba<T>> {
        Some(Rgba([T::DEFAULT_MIN_VALUE; 4]))
    }

    fn outline() -> Rgba<T> {
        Rgba([
            T::DEFAULT_MAX_VALUE,
            T::DEFAULT_MIN_VALUE,
            T::DEFAULT_MIN_VALUE,
            T::DEFAULT_MAX_VALUE,
        ])
    }
}
<|endoftext|>


<commit_before>use std::path::MAIN_SEPARATOR as SEP;

use support::{execs, project};
use support::{COMPILING, RUNNING};

use hamcrest::assert_that;

fn setup() {
}

test!(no_package {
    let p = project("foo");
    assert_that(p.process("cargo")
                 .arg("run")
                 .arg("--")
                 .arg("clone"), // To make docopt happy
                execs().with_status(101).with_stderr("\
specify which package to clone.
"));
});

test!(unknown_package {
    let p = project("foo");
    assert_that(p.process("cargo")
                 .arg("run")
                 .arg("--")
                 .arg("clone") // To make docopt happy
                 .arg("foobarfoofoobarbar"), // Hopefully this package does not exist
                execs().with_status(101).with_stderr("\
BLABLA
"));
});

test!(clone_package {
    let p = project("foo");
    assert_eq!(p.process("top"), 101);
});
<commit_msg>Fix error messages<commit_after>use std::path::MAIN_SEPARATOR as SEP;

use support::{execs, project};
use support::{COMPILING, RUNNING};

use hamcrest::assert_that;

fn setup() {
}

test!(no_package {
    let p = project("foo");
    assert_that(p.process("cargo")
                 .arg("run")
                 .arg("--")
                 .arg("clone"), // To make docopt happy
                execs().with_status(101).with_stderr("\
specify which package to clone.
"));
});

test!(unknown_package {
    let p = project("foo");
    assert_that(p.process("cargo")
                 .arg("run")
                 .arg("--")
                 .arg("clone") // To make docopt happy
                 .arg("foobarfoofoobarbar"), // Hopefully this package does not exist
                execs().with_status(101).with_stderr("\
package `foobarfoofoobarbar` not found.
"));
});

test!(clone_package {
    let p = project("foo");
    assert_eq!(p.process("top"), 101);
});
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// 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,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Contains serializable utility structs which are useful for other config structs.

/// Fully generic serializable vector. xsecurelock::engine::components::physics::Vector should be
/// used instead when possible.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Vector<T> {
    pub x: T,
    pub y: T,
}

/// A range over a generic group of elements. May be inclusive or exclusive depending on context.
/// Both parameters must be specified when this is specified explicitly.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Range<T> {
    pub min: T,
    pub max: T,
}

impl<T> Range<T> where T: PartialOrd + Clone {
    /// Clamps the value to be within this range, assuming the range is inclusive.
    pub fn clamp_inclusive(&self, val: T) -> T {
        assert!(self.min <= self.max, "min must be less than max");
        if val < self.min {
            self.min.clone()
        } else if val > self.max {
            self.max.clone()
        } else {
            val
        }
    }
}

/// A random distribution. This enum is used in places where the configuration should have a choice
/// of several different distribution types.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Distribution {
    /// Use an exponential distribution.
    #[serde(rename = "exponential")]
    Exponential(ExponentialDistribution),
    /// Use a normal distribution.
    #[serde(rename = "normal")]
    Normal(NormalDistribution),
    /// Use a uniform distribution.
    #[serde(rename = "uniform")]
    Uniform(UniformDistribution<f64>),
}

impl Distribution {
    /// Fix invalid to the given default, assuming inclusive uniform.
    pub fn fix_invalid_helper_iu(&mut self, path: &str, name: &str, default: fn() -> Self) {
        ::config::fix_invalid_helper(
            path, name,
            "Exponential must have lambda > 0, Normal must have standard_deviation >= 0, \
            or Uniform must have max >= min",
            self,
            |v| match v {
                Distribution::Exponential(ExponentialDistribution(lambda)) => *lambda > 0.,
                Distribution::Normal(NormalDistribution { standard_deviation, .. }) =>
                    *standard_deviation >= 0.,
                Distribution::Uniform(UniformDistribution { min, max }) => max >= min,
            },
            default,
        );
    }
}

/// A distribution that is required to be exponential. Serializable rand::distributions::Exp.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ExponentialDistribution(pub f64);

/// A distribution that is required to be normal. Serializable rand::distributions::Normal.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct NormalDistribution {
    /// The mean of the normal distribution.
    pub mean: f64,
    /// The standard deviation of the normal distribution.
    pub standard_deviation: f64,
}

/// A distribution that is required to be uniform. Serializable rand::distributions::Uniform.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct UniformDistribution<T> {
    /// The min value for the uniform distribution (always inclusive).
    pub min: T,
    /// The max value for the uniform distribution (may be inclusive or exclusive depending on
    /// context).
    pub max: T,
}
<commit_msg>use serde rename all for distribution snake case<commit_after>// Copyright 2018 Google LLC
//
// 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,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Contains serializable utility structs which are useful for other config structs.

/// Fully generic serializable vector. xsecurelock::engine::components::physics::Vector should be
/// used instead when possible.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Vector<T> {
    pub x: T,
    pub y: T,
}

/// A range over a generic group of elements. May be inclusive or exclusive depending on context.
/// Both parameters must be specified when this is specified explicitly.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Range<T> {
    pub min: T,
    pub max: T,
}

impl<T> Range<T> where T: PartialOrd + Clone {
    /// Clamps the value to be within this range, assuming the range is inclusive.
    pub fn clamp_inclusive(&self, val: T) -> T {
        assert!(self.min <= self.max, "min must be less than max");
        if val < self.min {
            self.min.clone()
        } else if val > self.max {
            self.max.clone()
        } else {
            val
        }
    }
}

/// A random distribution. This enum is used in places where the configuration should have a choice
/// of several different distribution types.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
pub enum Distribution {
    /// Use an exponential distribution.
    Exponential(ExponentialDistribution),
    /// Use a normal distribution.
    Normal(NormalDistribution),
    /// Use a uniform distribution.
    Uniform(UniformDistribution<f64>),
}

impl Distribution {
    /// Fix invalid to the given default, assuming inclusive uniform.
    pub fn fix_invalid_helper_iu(&mut self, path: &str, name: &str, default: fn() -> Self) {
        ::config::fix_invalid_helper(
            path, name,
            "Exponential must have lambda > 0, Normal must have standard_deviation >= 0, \
            or Uniform must have max >= min",
            self,
            |v| match v {
                Distribution::Exponential(ExponentialDistribution(lambda)) => *lambda > 0.,
                Distribution::Normal(NormalDistribution { standard_deviation, .. }) =>
                    *standard_deviation >= 0.,
                Distribution::Uniform(UniformDistribution { min, max }) => max >= min,
            },
            default,
        );
    }
}

/// A distribution that is required to be exponential. Serializable rand::distributions::Exp.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ExponentialDistribution(pub f64);

/// A distribution that is required to be normal. Serializable rand::distributions::Normal.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct NormalDistribution {
    /// The mean of the normal distribution.
    pub mean: f64,
    /// The standard deviation of the normal distribution.
    pub standard_deviation: f64,
}

/// A distribution that is required to be uniform. Serializable rand::distributions::Uniform.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct UniformDistribution<T> {
    /// The min value for the uniform distribution (always inclusive).
    pub min: T,
    /// The max value for the uniform distribution (may be inclusive or exclusive depending on
    /// context).
    pub max: T,
}
<|endoftext|>


<commit_before>use toml::Value;

use libimagerror::into::IntoError;

use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::result::Result;

use vcs::git::action::StoreAction;

pub fn commit_interactive(config: &Value) -> bool {
    unimplemented!()
}

pub fn commit_message(config: &Value, action: StoreAction) -> Option<String> {
    if commit_interactive(config) {
        unimplemented!()
    } else {
        unimplemented!()
    }
}

pub fn abort_on_repo_init_err(cfg: Option<&Value>) -> bool {
    cfg.map(|cfg| {
        match cfg.lookup("abort_on_repo_init_failure") {
            Some(&Value::Boolean(b)) => b,
            Some(_) => {
                warn!("Configuration error, 'abort_on_repo_init_failure' must be a Boolean (true|false).");
                warn!("Assuming 'true' now.");
                true
            },
            None => {
                debug!("No key `abort_on_repo_init_failure' - Assuming 'true'");
                true
            },
        }
    })
    .unwrap_or(false)
}

pub fn ensure_branch(cfg: Option<&Value>) -> Result<Option<String>> {
    match cfg {
        Some(cfg) => {
            match cfg.lookup("ensure_branch") {
                Some(&Value::String(ref s)) => Ok(Some(s.clone())),
                Some(_) => {
                    warn!("Configuration error, 'ensure_branch' must be a String.");
                    Err(GHEK::ConfigTypeError.into_error())
                        .map_err_into(GHEK::ConfigTypeError)
                },
                None => {
                    debug!("No key `ensure_branch'");
                    Ok(None)
                },
            }
        },
        None => Ok(None),
    }
}

<commit_msg>Add helper to check whether to try to checkout the ensure_branch branch<commit_after>use toml::Value;

use libimagerror::into::IntoError;

use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::result::Result;

use vcs::git::action::StoreAction;

pub fn commit_interactive(config: &Value) -> bool {
    unimplemented!()
}

pub fn commit_message(config: &Value, action: StoreAction) -> Option<String> {
    if commit_interactive(config) {
        unimplemented!()
    } else {
        unimplemented!()
    }
}

pub fn abort_on_repo_init_err(cfg: Option<&Value>) -> bool {
    cfg.map(|cfg| {
        match cfg.lookup("abort_on_repo_init_failure") {
            Some(&Value::Boolean(b)) => b,
            Some(_) => {
                warn!("Configuration error, 'abort_on_repo_init_failure' must be a Boolean (true|false).");
                warn!("Assuming 'true' now.");
                true
            },
            None => {
                debug!("No key `abort_on_repo_init_failure' - Assuming 'true'");
                true
            },
        }
    })
    .unwrap_or(false)
}

pub fn ensure_branch(cfg: Option<&Value>) -> Result<Option<String>> {
    match cfg {
        Some(cfg) => {
            match cfg.lookup("ensure_branch") {
                Some(&Value::String(ref s)) => Ok(Some(s.clone())),
                Some(_) => {
                    warn!("Configuration error, 'ensure_branch' must be a String.");
                    Err(GHEK::ConfigTypeError.into_error())
                        .map_err_into(GHEK::ConfigTypeError)
                },
                None => {
                    debug!("No key `ensure_branch'");
                    Ok(None)
                },
            }
        },
        None => Ok(None),
    }
}

pub fn do_checkout_ensure_branch(cfg: Option<&Value>) -> bool {
    cfg.map(|cfg| {
        match cfg.lookup("try_checkout_ensure_branch") {
            Some(&Value::Boolean(b)) => b,
            Some(_) => {
                warn!("Configuration error, 'try_checkout_ensure_branch' must be a Boolean (true|false).");
                warn!("Assuming 'true' now.");
                true
            },
            None => {
                debug!("No key `try_checkout_ensure_branch' - Assuming 'true'");
                true
            },
        }
    })
    .unwrap_or(false)
}

<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::path::Path;
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use toml::Value;

use libimagerror::into::IntoError;
use libimagerror::trace::trace_error;
use libimagstore::hook::Hook;
use libimagstore::hook::accessor::StoreIdAccessor;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::result::HookResult;
use libimagstore::storeid::StoreId;
use libimagutil::debug_result::*;

use vcs::git::error::GitHookError as GHE;
use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::error::MapIntoHookError;
use vcs::git::result::Result;
use vcs::git::runtime::Runtime as GRuntime;

pub struct UpdateHook {
    storepath: PathBuf,

    runtime: GRuntime,

    position: HookPosition,
}

impl UpdateHook {

    pub fn new(storepath: PathBuf, p: HookPosition) -> UpdateHook {
        UpdateHook {
            runtime: GRuntime::new(&storepath),
            storepath: storepath,
            position: p,
        }
    }

}

impl Debug for UpdateHook {
    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "UpdateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?})",
               self.storepath,
               (if self.runtime.has_repository() { "Some(_)" } else { "None" }),
               self.position,
               self.runtime.has_config())
    }
}

impl Hook for UpdateHook {

    fn name(&self) -> &'static str {
        "stdhook_git_update"
    }

    fn set_config(&mut self, config: &Value) {
        if let Err(e) = self.runtime.set_config(config) {
            trace_error(&e);
        }
    }

}

impl HookDataAccessorProvider for UpdateHook {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl StoreIdAccessor for UpdateHook {

    /// The implementation of the UpdateHook
    ///
    /// # Scope
    ///
    /// This hook takes the git index and commits it either interactively or with a default message,
    /// if there is no configuration for an interactive commit.
    ///
    fn access(&self, id: &StoreId) -> HookResult<()> {
        use vcs::git::action::StoreAction;
        use vcs::git::config::commit_message;
        use vcs::git::error::MapIntoHookError;
        use vcs::git::util::fetch_index;
        use git2::{Reference as GitReference, Repository, Error as Git2Error};
        use git2::{ADD_DEFAULT, STATUS_WT_NEW, STATUS_WT_MODIFIED, IndexMatchedPath};

        debug!("[GIT UPDATE HOOK]: {:?}", id);

        let action    = StoreAction::Update;
        let cfg       = try!(self.runtime.config_value_or_err(&action));
        let repo      = try!(self.runtime.repository(&action));
        let mut index = try!(fetch_index(repo, &action));

        let signature = try!(
            repo.signature()
                .map_err_into(GHEK::MkSignature)
                .map_dbg_err_str("Failed to fetch signature")
                .map_into_hook_error()
        );

        let head = try!(
            repo.head()
                .map_err_into(GHEK::HeadFetchError)
                .map_dbg_err_str("Failed to fetch HEAD")
                .map_into_hook_error()
        );

        let file_status = try!(
            repo
                .status_file(id.local())
                .map_dbg_err_str("Failed to fetch file status")
                .map_dbg_err(|e| format!("\t->  {:?}", e))
                .map_err_into(GHEK::RepositoryFileStatusError)
                .map_into_hook_error()
        );

        let cb = &mut |path: &Path, _matched_spec: &[u8]| -> i32 {
            if file_status.contains(STATUS_WT_NEW) || file_status.contains(STATUS_WT_MODIFIED) {
                debug!("[GIT CREATE HOOK]: File is modified/new: {}", path.display());
                0
            } else {
                debug!("[GIT CREATE HOOK]: Ignoring file: {}", path.display());
                1
            }
        };

        try!(
            index.add_all(&[id.local()], ADD_DEFAULT, Some(cb as &mut IndexMatchedPath))
                .map_err_into(GHEK::RepositoryPathAddingError)
                .map_dbg_err_str("Failed to add to index")
                .map_into_hook_error()
        );

        let tree_id = try!(
            index.write_tree()
                .map_err_into(GHEK::RepositoryIndexWritingError)
                .map_dbg_err_str("Failed to write tree")
                .map_into_hook_error()
        );

        let mut parents = Vec::new();
        {
            let commit = try!(
                repo.find_commit(head.target().unwrap())
                    .map_err_into(GHEK::RepositoryParentFetchingError)
                    .map_dbg_err_str("Failed to find commit HEAD")
                    .map_into_hook_error()
            );
            parents.push(commit);
        }

        // for converting from Vec<Commit> to Vec<&Commit>
        let parents = parents.iter().collect::<Vec<_>>();

        let tree = try!(
            repo.find_tree(tree_id)
                .map_err_into(GHEK::RepositoryParentFetchingError)
                .map_dbg_err_str("Failed to find tree")
                .map_into_hook_error()
        );

        let message = try!(commit_message(&repo, cfg, StoreAction::Update)
                .map_dbg_err_str("Failed to get commit message"));

        try!(repo.commit(Some("HEAD"), &signature, &signature, &message, &tree, &parents)
            .map_dbg_str("Committed")
            .map_dbg_err_str("Failed to commit")
            .map_err_into(GHEK::RepositoryCommittingError)
            .map_into_hook_error()
        );

        index.write()
            .map_err_into(GHEK::RepositoryIndexWritingError)
            .map_dbg_err_str("Failed to write tree")
            .map_into_hook_error()
            .map(|_| ())
    }

}

<commit_msg>Remove unused imports: Update hook<commit_after>use std::path::PathBuf;
use std::path::Path;
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use toml::Value;

use libimagerror::trace::trace_error;
use libimagstore::hook::Hook;
use libimagstore::hook::accessor::StoreIdAccessor;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::result::HookResult;
use libimagstore::storeid::StoreId;
use libimagutil::debug_result::*;

use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::runtime::Runtime as GRuntime;

pub struct UpdateHook {
    storepath: PathBuf,

    runtime: GRuntime,

    position: HookPosition,
}

impl UpdateHook {

    pub fn new(storepath: PathBuf, p: HookPosition) -> UpdateHook {
        UpdateHook {
            runtime: GRuntime::new(&storepath),
            storepath: storepath,
            position: p,
        }
    }

}

impl Debug for UpdateHook {
    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "UpdateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?})",
               self.storepath,
               (if self.runtime.has_repository() { "Some(_)" } else { "None" }),
               self.position,
               self.runtime.has_config())
    }
}

impl Hook for UpdateHook {

    fn name(&self) -> &'static str {
        "stdhook_git_update"
    }

    fn set_config(&mut self, config: &Value) {
        if let Err(e) = self.runtime.set_config(config) {
            trace_error(&e);
        }
    }

}

impl HookDataAccessorProvider for UpdateHook {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl StoreIdAccessor for UpdateHook {

    /// The implementation of the UpdateHook
    ///
    /// # Scope
    ///
    /// This hook takes the git index and commits it either interactively or with a default message,
    /// if there is no configuration for an interactive commit.
    ///
    fn access(&self, id: &StoreId) -> HookResult<()> {
        use vcs::git::action::StoreAction;
        use vcs::git::config::commit_message;
        use vcs::git::error::MapIntoHookError;
        use vcs::git::util::fetch_index;
        use git2::{ADD_DEFAULT, STATUS_WT_NEW, STATUS_WT_MODIFIED, IndexMatchedPath};

        debug!("[GIT UPDATE HOOK]: {:?}", id);

        let action    = StoreAction::Update;
        let cfg       = try!(self.runtime.config_value_or_err(&action));
        let repo      = try!(self.runtime.repository(&action));
        let mut index = try!(fetch_index(repo, &action));

        let signature = try!(
            repo.signature()
                .map_err_into(GHEK::MkSignature)
                .map_dbg_err_str("Failed to fetch signature")
                .map_into_hook_error()
        );

        let head = try!(
            repo.head()
                .map_err_into(GHEK::HeadFetchError)
                .map_dbg_err_str("Failed to fetch HEAD")
                .map_into_hook_error()
        );

        let file_status = try!(
            repo
                .status_file(id.local())
                .map_dbg_err_str("Failed to fetch file status")
                .map_dbg_err(|e| format!("\t->  {:?}", e))
                .map_err_into(GHEK::RepositoryFileStatusError)
                .map_into_hook_error()
        );

        let cb = &mut |path: &Path, _matched_spec: &[u8]| -> i32 {
            if file_status.contains(STATUS_WT_NEW) || file_status.contains(STATUS_WT_MODIFIED) {
                debug!("[GIT CREATE HOOK]: File is modified/new: {}", path.display());
                0
            } else {
                debug!("[GIT CREATE HOOK]: Ignoring file: {}", path.display());
                1
            }
        };

        try!(
            index.add_all(&[id.local()], ADD_DEFAULT, Some(cb as &mut IndexMatchedPath))
                .map_err_into(GHEK::RepositoryPathAddingError)
                .map_dbg_err_str("Failed to add to index")
                .map_into_hook_error()
        );

        let tree_id = try!(
            index.write_tree()
                .map_err_into(GHEK::RepositoryIndexWritingError)
                .map_dbg_err_str("Failed to write tree")
                .map_into_hook_error()
        );

        let mut parents = Vec::new();
        {
            let commit = try!(
                repo.find_commit(head.target().unwrap())
                    .map_err_into(GHEK::RepositoryParentFetchingError)
                    .map_dbg_err_str("Failed to find commit HEAD")
                    .map_into_hook_error()
            );
            parents.push(commit);
        }

        // for converting from Vec<Commit> to Vec<&Commit>
        let parents = parents.iter().collect::<Vec<_>>();

        let tree = try!(
            repo.find_tree(tree_id)
                .map_err_into(GHEK::RepositoryParentFetchingError)
                .map_dbg_err_str("Failed to find tree")
                .map_into_hook_error()
        );

        let message = try!(commit_message(&repo, cfg, StoreAction::Update)
                .map_dbg_err_str("Failed to get commit message"));

        try!(repo.commit(Some("HEAD"), &signature, &signature, &message, &tree, &parents)
            .map_dbg_str("Committed")
            .map_dbg_err_str("Failed to commit")
            .map_err_into(GHEK::RepositoryCommittingError)
            .map_into_hook_error()
        );

        index.write()
            .map_err_into(GHEK::RepositoryIndexWritingError)
            .map_dbg_err_str("Failed to write tree")
            .map_into_hook_error()
            .map(|_| ())
    }

}

<|endoftext|>


<commit_before>use crate::schema::*;
use diesel::prelude::*;

#[test]
fn selecting_basic_data() {
    let connection = &mut connection();
    diesel::sql_query("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
        .execute(connection)
        .unwrap();

    let expected_data = vec![
        ("Sean".to_string(), None::<String>),
        ("Tess".to_string(), None::<String>),
    ];

    let user_alias = alias!(users as user_alias);

    let actual_data = user_alias
        .select((
            user_alias.field(users::name),
            user_alias.field(users::hair_color),
        ))
        .load(connection)
        .unwrap();

    assert_eq!(expected_data, actual_data);
}

#[test]
fn select_multiple_from_join() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();

    diesel::sql_query(
        "INSERT INTO posts (id, user_id, title) VALUES
        (1, 1, 'Hello'),
        (2, 2, 'World')
    ",
    )
    .execute(connection)
    .unwrap();

    alias!(users as user_alias: UserAlias);
    let post_alias = alias!(posts as post_alias);

    // Having two different aliases in one query works
    post_alias
        .select(post_alias.fields((posts::id, posts::user_id, posts::title, posts::body)))
        .filter(
            post_alias.field(posts::user_id).eq_any(
                user_alias.select(user_alias.field(users::id)).filter(
                    user_alias
                        .field(users::id)
                        .eq_any(users::table.select(users::id)),
                ),
            ),
        )
        .load::<(i32, i32, String, Option<String>)>(connection)
        .unwrap();

    // using a subquery with an alias seems to work
    post_alias
        .select(
            posts::table
                .select(posts::id)
                .filter(post_alias.field(posts::id).eq(posts::id))
                .single_value(),
        )
        .load::<Option<i32>>(connection)
        .unwrap();

    // Joining with explicit on clause works
    post_alias
        .left_join(users::table)
        .inner_join(
            user_alias.on(post_alias
                .field(posts::user_id)
                .eq(user_alias.field(users::id))),
        )
        .select((
            post_alias.field(posts::id),
            users::id.nullable(),
            user_alias.field(users::id),
        ))
        .load::<(i32, Option<i32>, i32)>(connection)
        .unwrap();

    // having the alias on the right side seems to work
    // joining the table with an alias twice, also works
    posts::table
        .inner_join(user_alias)
        .inner_join(users::table)
        .select((user_alias.field(users::name), users::name))
        .load::<(String, String)>(connection)
        .unwrap();

    // Joining alias to alias works
    post_alias
        .inner_join(user_alias)
        .select((user_alias.field(users::name), post_alias.field(posts::id)))
        .load::<(String, i32)>(connection)
        .unwrap();

    // using mutiple aliases for the same table works if they are declared in the same alias call
    let (user1_alias, user2_alias, _post_alias) =
        alias!(users as user1, users as user2, posts as post1,);

    posts::table
        .inner_join(user1_alias)
        .inner_join(user2_alias)
        .select(posts::id)
        .load::<i32>(connection)
        .unwrap();

    // its also possible to do a self join, multiple times
    // (that should work as long as all aliases are declared in the same alias! call)
    users::table
        .inner_join(user1_alias.on(users::id.eq(user1_alias.field(users::id))))
        .inner_join(
            user2_alias.on(user2_alias
                .field(users::id)
                .eq(user1_alias.field(users::id))),
        )
        .select((
            users::id,
            user1_alias.field(users::id),
            user2_alias.field(users::id),
        ))
        .load::<(i32, i32, i32)>(connection)
        .unwrap();
}

#[test]
fn find_and_first() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let alias = alias!(users as users_alias);
    assert_eq!(
        alias
            .find(1)
            .select(alias.field(users::name))
            .first::<String>(connection),
        Ok("Sean".into()),
    )
}

#[test]
fn boxed() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();

    let (user1_alias, user2_alias, _post_alias) =
        alias!(users as user1, users as user2, posts as post1,);

    let q = posts::table
        .inner_join(user1_alias)
        .inner_join(user2_alias)
        .into_boxed();

    let res = q
        .select((posts::user_id, user1_alias.fields((users::id, users::id))))
        .load::<(i32, (i32, i32))>(connection)
        .unwrap();
    assert!(res.into_iter().all(|(a, (b, c))| a == b && a == c));
}

#[test]
fn visibility() {
    mod submodule {
        use super::*;
        alias! { users as user1: User1Alias }
    }
    let _user1 = submodule::user1;

    alias! {
        const USERS_ALIAS_2: Alias<UsersAlias2> = users as users_alias_2;
    }
}

// regression test for
// https://github.com/diesel-rs/diesel/issues/3319
#[test]
fn aliasing_with_group_by_and_primary_key() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let user_alias = alias!(users as user1);

    let res = user_alias
        .group_by(user_alias.field(users::id))
        .select(user_alias.field(users::name))
        .load::<String>(connection)
        .unwrap();
    assert!(res.len() == 2);
    assert_eq!(res[1], "Sean");
    assert_eq!(res[0], "Tess");
}
<commit_msg>Explicitly order results to fix the testcase<commit_after>use crate::schema::*;
use diesel::prelude::*;

#[test]
fn selecting_basic_data() {
    let connection = &mut connection();
    diesel::sql_query("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
        .execute(connection)
        .unwrap();

    let expected_data = vec![
        ("Sean".to_string(), None::<String>),
        ("Tess".to_string(), None::<String>),
    ];

    let user_alias = alias!(users as user_alias);

    let actual_data = user_alias
        .select((
            user_alias.field(users::name),
            user_alias.field(users::hair_color),
        ))
        .load(connection)
        .unwrap();

    assert_eq!(expected_data, actual_data);
}

#[test]
fn select_multiple_from_join() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();

    diesel::sql_query(
        "INSERT INTO posts (id, user_id, title) VALUES
        (1, 1, 'Hello'),
        (2, 2, 'World')
    ",
    )
    .execute(connection)
    .unwrap();

    alias!(users as user_alias: UserAlias);
    let post_alias = alias!(posts as post_alias);

    // Having two different aliases in one query works
    post_alias
        .select(post_alias.fields((posts::id, posts::user_id, posts::title, posts::body)))
        .filter(
            post_alias.field(posts::user_id).eq_any(
                user_alias.select(user_alias.field(users::id)).filter(
                    user_alias
                        .field(users::id)
                        .eq_any(users::table.select(users::id)),
                ),
            ),
        )
        .load::<(i32, i32, String, Option<String>)>(connection)
        .unwrap();

    // using a subquery with an alias seems to work
    post_alias
        .select(
            posts::table
                .select(posts::id)
                .filter(post_alias.field(posts::id).eq(posts::id))
                .single_value(),
        )
        .load::<Option<i32>>(connection)
        .unwrap();

    // Joining with explicit on clause works
    post_alias
        .left_join(users::table)
        .inner_join(
            user_alias.on(post_alias
                .field(posts::user_id)
                .eq(user_alias.field(users::id))),
        )
        .select((
            post_alias.field(posts::id),
            users::id.nullable(),
            user_alias.field(users::id),
        ))
        .load::<(i32, Option<i32>, i32)>(connection)
        .unwrap();

    // having the alias on the right side seems to work
    // joining the table with an alias twice, also works
    posts::table
        .inner_join(user_alias)
        .inner_join(users::table)
        .select((user_alias.field(users::name), users::name))
        .load::<(String, String)>(connection)
        .unwrap();

    // Joining alias to alias works
    post_alias
        .inner_join(user_alias)
        .select((user_alias.field(users::name), post_alias.field(posts::id)))
        .load::<(String, i32)>(connection)
        .unwrap();

    // using mutiple aliases for the same table works if they are declared in the same alias call
    let (user1_alias, user2_alias, _post_alias) =
        alias!(users as user1, users as user2, posts as post1,);

    posts::table
        .inner_join(user1_alias)
        .inner_join(user2_alias)
        .select(posts::id)
        .load::<i32>(connection)
        .unwrap();

    // its also possible to do a self join, multiple times
    // (that should work as long as all aliases are declared in the same alias! call)
    users::table
        .inner_join(user1_alias.on(users::id.eq(user1_alias.field(users::id))))
        .inner_join(
            user2_alias.on(user2_alias
                .field(users::id)
                .eq(user1_alias.field(users::id))),
        )
        .select((
            users::id,
            user1_alias.field(users::id),
            user2_alias.field(users::id),
        ))
        .load::<(i32, i32, i32)>(connection)
        .unwrap();
}

#[test]
fn find_and_first() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let alias = alias!(users as users_alias);
    assert_eq!(
        alias
            .find(1)
            .select(alias.field(users::name))
            .first::<String>(connection),
        Ok("Sean".into()),
    )
}

#[test]
fn boxed() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();

    let (user1_alias, user2_alias, _post_alias) =
        alias!(users as user1, users as user2, posts as post1,);

    let q = posts::table
        .inner_join(user1_alias)
        .inner_join(user2_alias)
        .into_boxed();

    let res = q
        .select((posts::user_id, user1_alias.fields((users::id, users::id))))
        .load::<(i32, (i32, i32))>(connection)
        .unwrap();
    assert!(res.into_iter().all(|(a, (b, c))| a == b && a == c));
}

#[test]
fn visibility() {
    mod submodule {
        use super::*;
        alias! { users as user1: User1Alias }
    }
    let _user1 = submodule::user1;

    alias! {
        const USERS_ALIAS_2: Alias<UsersAlias2> = users as users_alias_2;
    }
}

// regression test for
// https://github.com/diesel-rs/diesel/issues/3319
#[test]
fn aliasing_with_group_by_and_primary_key() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let user_alias = alias!(users as user1);

    let res = user_alias
        .group_by(user_alias.field(users::id))
        .select(user_alias.field(users::name))
        .order_by(user_alias.field(users::id))
        .load::<String>(connection)
        .unwrap();
    assert!(res.len() == 2);
    assert_eq!(res[0], "Sean");
    assert_eq!(res[1], "Tess");
}
<|endoftext|>