<commit_before>use std::borrow::Borrow;
use std::path::Path;
use std::sync::Arc;

#[cfg(target_os="linux")]
use std::process::{Command, Stdio};

use threadpool::ThreadPool;

use config::{Config, JiraConfig};
use git::Git;
use github;
use git_clone_manager::GitCloneManager;
use jira;
use worker;

pub fn comment_repo_version(version_script: &str,
                            jira_config: &JiraConfig,
                            jira: &jira::api::Session,
                            github: &github::api::Session,
                            clone_mgr: &GitCloneManager,
                            owner: &str,
                            repo: &str,
                            branch_name: &str,
                            commit_hash: &str,
                            commits: &Vec<github::PushCommit>) -> Result<(), String> {
    let held_clone_dir = try!(clone_mgr.clone(owner, repo));
    let clone_dir = held_clone_dir.dir();

    let git = Git::new(github.github_host(), github.github_token(), &clone_dir);

    // setup branch
    try!(git.checkout_branch(branch_name, commit_hash));

    let version = try!(run_script(version_script, clone_dir));

    let maybe_version = if version.len() > 0 {
        Some(version.as_str())
    } else {
        None
    };

    // resolve with version
    jira::workflow::resolve_issue(branch_name, maybe_version, commits, jira, jira_config);

    Ok(())
}

// Only run version scripts on Linux since firejail is only for Linux and it doesn't
// seem like a good idea to allow generic code execution without any containerization.
#[cfg(not(target_os="linux"))]
fn run_script(_: &str, _: &Path) -> Result<String, String> {
    return Err("Version scripts only supported when running Linux.".into());
}

#[cfg(target_os="linux")]
fn run_script(version_script: &str, clone_dir: &Path) -> Result<String, String> {
    debug!("Running version script: {}", version_script);
    let cmd = Command::new("firejail")
        .arg("--overlay-tmpfs")
        .arg("--quiet")
        .arg("--private=.")
        .arg("--private-etc=hostname alternatives")
        .arg("--net=none")
        .arg("--private-tmp")
        .arg("--private-dev")
        .arg("-c")
        .arg("bash")
        .arg("-c")
        .arg(version_script)
        .current_dir(clone_dir)
        .stdin(Stdio::null())
        .stderr(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn();

    let child = match cmd {
        Ok(c) => c,
        Err(e) => return Err(format!("Error starting version script (script: {}): {}", version_script, e)),
    };

    let result = match child.wait_with_output() {
        Ok(r) => r,
        Err(e) => return Err(format!("Error running version script (script: {}): {}", version_script, e)),
    };

    let mut output = String::new();
    if result.stdout.len() > 0 {
        output += String::from_utf8_lossy(&result.stdout).as_ref();
        // skip over firejail output (even with --quiet)
        if output.starts_with("OverlayFS") {
            let new_lines: Vec<String> =
                output.lines().skip(1)
                              .skip_while(|s| s.trim().len() == 0)
                              .map(|s| s.into())
                              .collect();
            output = new_lines.join("\n");
        }

    }

    if !result.status.success() {
        if result.stderr.len() > 0 {
            output += String::from_utf8_lossy(&result.stderr).as_ref();
        }
        Err(format!("Error running version script (exit code {}; script: {}):\n{}",
                    result.status.code().unwrap_or(-1),
                    version_script,
                    output))
    } else {

        Ok(output.trim().to_string())
    }
}

#[derive(Debug)]
pub struct RepoVersionRequest {
    pub repo: github::Repo,
    pub branch: String,
    pub commit_hash: String,
    pub commits: Vec<github::PushCommit>,
}

struct Runner {
    config: Arc<Config>,
    github_session: Arc<github::api::Session>,
    jira_session: Option<Arc<jira::api::Session>>,
    clone_mgr: Arc<GitCloneManager>,
    thread_pool: ThreadPool,
}

pub fn req(repo: &github::Repo, branch: &str, commit_hash: &str, commits: &Vec<github::PushCommit>) -> RepoVersionRequest {
    RepoVersionRequest {
        repo: repo.clone(),
        branch: branch.to_string(),
        commit_hash: commit_hash.to_string(),
        commits: commits.clone(),
    }
}

pub fn new_worker(max_concurrency: usize,
                  config: Arc<Config>,
                  github_session: Arc<github::api::Session>,
                  jira_session: Option<Arc<jira::api::Session>>,
                  clone_mgr: Arc<GitCloneManager>)
                   -> worker::Worker<RepoVersionRequest> {
    worker::Worker::new(Runner {
        config: config,
        github_session: github_session,
        jira_session: jira_session,
        clone_mgr: clone_mgr,
        thread_pool: ThreadPool::new(max_concurrency),
    })
}

impl worker::Runner<RepoVersionRequest> for Runner {
    fn handle(&self, req: RepoVersionRequest) {
        let github_session = self.github_session.clone();
        let jira_session = self.jira_session.clone();
        let clone_mgr = self.clone_mgr.clone();
        let config = self.config.clone();

        // launch another thread to do the version calculation
        self.thread_pool.execute(move || {
            let version_script;
            {
                let repos_lock = config.repos();
                version_script = repos_lock.version_script(&req.repo);
            }

            if let Some(version_script) = version_script {
                if let Some(ref jira_session) = jira_session {
                    if let Some(ref jira_config) = config.jira {
                        let jira = jira_session.borrow();
                        if let Err(e) = comment_repo_version(&version_script,
                                                             jira_config,
                                                             jira,
                                                             github_session.borrow(),
                                                             &clone_mgr,
                                                             &req.repo.owner.login(),
                                                             &req.repo.name,
                                                             &req.branch,
                                                             &req.commit_hash,
                                                             &req.commits) {
                            error!("Error running version script: {}", e);
                            // resolve the issue with no version
                            jira::workflow::resolve_issue(&req.branch, None, &req.commits, jira, jira_config);
                        }
                    }
                }
            }
        });
    }
}

#[cfg(target_os="linux")]
#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;
    use std::io::Write;

    extern crate tempdir;
    use self::tempdir::TempDir;

    #[test]
    fn test_run_script() {
        let dir = TempDir::new("repo_version.rs").expect("create temp dir for repo_version.rs test");

        let sub_dir = dir.path().join("subdir");
        fs::create_dir(&sub_dir).expect("create subdir");

        let script_file = sub_dir.join("version.sh");
        {
            let mut file = fs::File::create(&script_file).expect("create file");
            file.write_all(b"echo 1.2.3.4").expect("write file");
        }

        assert_eq!(Ok("1.2.3.4".into()), run_script("bash version.sh", &sub_dir));
    }

    #[test]
    fn test_run_script_isolation() {
        let dir = TempDir::new("repo_version.rs").expect("create temp dir for repo_version.rs test");

        let parent_file = dir.path().join("private.txt");
        {
            let mut file = fs::File::create(&parent_file).expect("create file");
            file.write_all(b"I am a file").expect("write file");
        }

        let sub_dir = dir.path().join("subdir");
        fs::create_dir(&sub_dir).expect("create subdir");

        let script_file = sub_dir.join("version.sh");
        {
            let mut file = fs::File::create(&script_file).expect("create file");
            file.write_all(br#"
            # no `set -e` on purpose: try to do them all!
            rm ../private.txt
            rm version.sh
            touch ../muahaha.txt
            touch muahaha.txt

            echo 1.2.3.4
            "#).expect("write file");
        }

        assert_eq!(Ok("1.2.3.4".into()), run_script("bash version.sh", &sub_dir));

        assert!(parent_file.exists(), "version scripts should not be able to delete files outside its directory");
        assert!(script_file.exists(), "version scripts should not be able to delete files inside its directory");
        assert!(!dir.path().join("muahaha.txt").exists(), "version scripts should not be able to create files outside its directory");
        assert!(!sub_dir.join("muahaha.txt").exists(), "version scripts should not be able to create files inside its directory");
    }
}
<commit_msg>Add better version script logging (#83)<commit_after>use std::borrow::Borrow;
use std::path::Path;
use std::sync::Arc;

#[cfg(target_os="linux")]
use std::process::{Command, Stdio};

use threadpool::ThreadPool;

use config::{Config, JiraConfig};
use git::Git;
use github;
use git_clone_manager::GitCloneManager;
use jira;
use worker;

pub fn comment_repo_version(version_script: &str,
                            jira_config: &JiraConfig,
                            jira: &jira::api::Session,
                            github: &github::api::Session,
                            clone_mgr: &GitCloneManager,
                            owner: &str,
                            repo: &str,
                            branch_name: &str,
                            commit_hash: &str,
                            commits: &Vec<github::PushCommit>) -> Result<(), String> {
    let held_clone_dir = try!(clone_mgr.clone(owner, repo));
    let clone_dir = held_clone_dir.dir();

    let git = Git::new(github.github_host(), github.github_token(), &clone_dir);

    // setup branch
    try!(git.checkout_branch(branch_name, commit_hash));

    let version = try!(run_script(version_script, clone_dir));

    let maybe_version = if version.len() > 0 {
        Some(version.as_str())
    } else {
        None
    };

    // resolve with version
    jira::workflow::resolve_issue(branch_name, maybe_version, commits, jira, jira_config);

    Ok(())
}

// Only run version scripts on Linux since firejail is only for Linux and it doesn't
// seem like a good idea to allow generic code execution without any containerization.
#[cfg(not(target_os="linux"))]
fn run_script(_: &str, _: &Path) -> Result<String, String> {
    return Err("Version scripts only supported when running Linux.".into());
}

#[cfg(target_os="linux")]
fn run_script(version_script: &str, clone_dir: &Path) -> Result<String, String> {
    debug!("Running version script: {}", version_script);
    let cmd = Command::new("firejail")
        .arg("--overlay-tmpfs")
        .arg("--quiet")
        .arg("--private=.")
        .arg("--private-etc=hostname alternatives")
        .arg("--net=none")
        .arg("--private-tmp")
        .arg("--private-dev")
        .arg("-c")
        .arg("bash")
        .arg("-c")
        .arg(version_script)
        .current_dir(clone_dir)
        .stdin(Stdio::null())
        .stderr(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn();

    let child = match cmd {
        Ok(c) => c,
        Err(e) => return Err(format!("Error starting version script (script: {}): {}", version_script, e)),
    };

    let result = match child.wait_with_output() {
        Ok(r) => r,
        Err(e) => return Err(format!("Error running version script (script: {}): {}", version_script, e)),
    };

    let mut output = String::new();
    if result.stdout.len() > 0 {
        let stdout = String::from_utf8_lossy(&result.stdout).into_owned();
        debug!("Version script stdout: \n---\n{}\n---", stdout);
        output += &stdout;
        // skip over firejail output (even with --quiet)
        if output.starts_with("OverlayFS") {
            let new_lines: Vec<String> =
                output.lines().skip(1)
                              .skip_while(|s| s.trim().len() == 0)
                              .map(|s| s.into())
                              .collect();
            output = new_lines.join("\n");
        }
    }

    let mut stderr = String::new();
    if result.stderr.len() > 0 {
        stderr = String::from_utf8_lossy(&result.stderr).into_owned();
        debug!("Version script stderr: \n---\n{}\n---", stderr);
    }

    if !result.status.success() {
        output += &stderr;
        Err(format!("Error running version script (exit code {}; script: {}):\n{}",
                    result.status.code().unwrap_or(-1),
                    version_script,
                    output))
    } else {

        Ok(output.trim().to_string())
    }
}

#[derive(Debug)]
pub struct RepoVersionRequest {
    pub repo: github::Repo,
    pub branch: String,
    pub commit_hash: String,
    pub commits: Vec<github::PushCommit>,
}

struct Runner {
    config: Arc<Config>,
    github_session: Arc<github::api::Session>,
    jira_session: Option<Arc<jira::api::Session>>,
    clone_mgr: Arc<GitCloneManager>,
    thread_pool: ThreadPool,
}

pub fn req(repo: &github::Repo, branch: &str, commit_hash: &str, commits: &Vec<github::PushCommit>) -> RepoVersionRequest {
    RepoVersionRequest {
        repo: repo.clone(),
        branch: branch.to_string(),
        commit_hash: commit_hash.to_string(),
        commits: commits.clone(),
    }
}

pub fn new_worker(max_concurrency: usize,
                  config: Arc<Config>,
                  github_session: Arc<github::api::Session>,
                  jira_session: Option<Arc<jira::api::Session>>,
                  clone_mgr: Arc<GitCloneManager>)
                   -> worker::Worker<RepoVersionRequest> {
    worker::Worker::new(Runner {
        config: config,
        github_session: github_session,
        jira_session: jira_session,
        clone_mgr: clone_mgr,
        thread_pool: ThreadPool::new(max_concurrency),
    })
}

impl worker::Runner<RepoVersionRequest> for Runner {
    fn handle(&self, req: RepoVersionRequest) {
        let github_session = self.github_session.clone();
        let jira_session = self.jira_session.clone();
        let clone_mgr = self.clone_mgr.clone();
        let config = self.config.clone();

        // launch another thread to do the version calculation
        self.thread_pool.execute(move || {
            let version_script;
            {
                let repos_lock = config.repos();
                version_script = repos_lock.version_script(&req.repo);
            }

            if let Some(version_script) = version_script {
                if let Some(ref jira_session) = jira_session {
                    if let Some(ref jira_config) = config.jira {
                        let jira = jira_session.borrow();
                        if let Err(e) = comment_repo_version(&version_script,
                                                             jira_config,
                                                             jira,
                                                             github_session.borrow(),
                                                             &clone_mgr,
                                                             &req.repo.owner.login(),
                                                             &req.repo.name,
                                                             &req.branch,
                                                             &req.commit_hash,
                                                             &req.commits) {
                            error!("Error running version script: {}", e);
                            // resolve the issue with no version
                            jira::workflow::resolve_issue(&req.branch, None, &req.commits, jira, jira_config);
                        }
                    }
                }
            }
        });
    }
}

#[cfg(target_os="linux")]
#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;
    use std::io::Write;

    extern crate tempdir;
    use self::tempdir::TempDir;

    #[test]
    fn test_run_script() {
        let dir = TempDir::new("repo_version.rs").expect("create temp dir for repo_version.rs test");

        let sub_dir = dir.path().join("subdir");
        fs::create_dir(&sub_dir).expect("create subdir");

        let script_file = sub_dir.join("version.sh");
        {
            let mut file = fs::File::create(&script_file).expect("create file");
            file.write_all(b"echo 1.2.3.4").expect("write file");
        }

        assert_eq!(Ok("1.2.3.4".into()), run_script("bash version.sh", &sub_dir));
    }

    #[test]
    fn test_run_script_isolation() {
        let dir = TempDir::new("repo_version.rs").expect("create temp dir for repo_version.rs test");

        let parent_file = dir.path().join("private.txt");
        {
            let mut file = fs::File::create(&parent_file).expect("create file");
            file.write_all(b"I am a file").expect("write file");
        }

        let sub_dir = dir.path().join("subdir");
        fs::create_dir(&sub_dir).expect("create subdir");

        let script_file = sub_dir.join("version.sh");
        {
            let mut file = fs::File::create(&script_file).expect("create file");
            file.write_all(br#"
            # no `set -e` on purpose: try to do them all!
            rm ../private.txt
            rm version.sh
            touch ../muahaha.txt
            touch muahaha.txt

            echo 1.2.3.4
            "#).expect("write file");
        }

        assert_eq!(Ok("1.2.3.4".into()), run_script("bash version.sh", &sub_dir));

        assert!(parent_file.exists(), "version scripts should not be able to delete files outside its directory");
        assert!(script_file.exists(), "version scripts should not be able to delete files inside its directory");
        assert!(!dir.path().join("muahaha.txt").exists(), "version scripts should not be able to create files outside its directory");
        assert!(!sub_dir.join("muahaha.txt").exists(), "version scripts should not be able to create files inside its directory");
    }
}
<|endoftext|>


<commit_before>use std::cast;
use rect::Rect;
use get_error;
use std::ptr;
use libc::c_int;
use pixels;
use rwops;

#[allow(non_camel_case_types)]
pub mod ll {
    use pixels::ll::SDL_PixelFormat;
    use pixels::ll::SDL_Palette;
    use render::ll::SDL_BlendMode;
    use rwops::ll::SDL_RWops;
    use rect::Rect;
    use libc::{c_int, c_void, uint32_t, uint8_t};
    pub type SDL_Rect = Rect;
    pub type SDL_bool = c_int;

    pub type SDL_SurfaceFlag = c_int;

    pub static SDL_SWSURFACE: SDL_SurfaceFlag = 0;
    pub static SDL_PREALLOC: SDL_SurfaceFlag = 0x00000001;
    pub static SDL_RLEACCEL: SDL_SurfaceFlag = 0x00000002;
    pub static SDL_DONTFREE: SDL_SurfaceFlag = 0x00000004;

    //SDL_surface.h
    pub struct SDL_BlitMap;

    pub struct SDL_Surface {
        pub flags: uint32_t,
        pub format: *SDL_PixelFormat,
        pub w: c_int,
        pub h: c_int,
        pub pitch: c_int,
        pub pixels: *c_void,
        pub userdata: *c_void,
        pub locked: c_int,
        pub lock_data: *c_void,
        pub clip_rect: SDL_Rect,
        pub map: *SDL_BlitMap,
        pub refcount: c_int
    }

    extern "C" {
        pub fn SDL_CreateRGBSurface(flags: uint32_t, width: c_int, height: c_int, depth: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *SDL_Surface;
        pub fn SDL_CreateRGBSurfaceFrom(pixels: *c_void, width: c_int, height: c_int, depth: c_int, pitch: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *SDL_Surface;
        pub fn SDL_FreeSurface(surface: *SDL_Surface);
        pub fn SDL_SetSurfacePalette(surface: *SDL_Surface, palette: *SDL_Palette) -> c_int;
        pub fn SDL_LockSurface(surface: *SDL_Surface) -> c_int;
        pub fn SDL_UnlockSurface(surface: *SDL_Surface);
        pub fn SDL_LoadBMP_RW(src: *SDL_RWops, freesrc: c_int) ->  *SDL_Surface;
        pub fn SDL_SaveBMP_RW(surface: *SDL_Surface, dst: *SDL_RWops, freedst: c_int) -> c_int;
        pub fn SDL_SetSurfaceRLE(surface: *SDL_Surface, flag: c_int) -> c_int;
        pub fn SDL_SetColorKey(surface: *SDL_Surface, flag: c_int, key: uint32_t) -> c_int;
        pub fn SDL_GetColorKey(surface: *SDL_Surface, key: *uint32_t) -> c_int;
        pub fn SDL_SetSurfaceColorMod(surface: *SDL_Surface, r: uint8_t, g: uint8_t, b: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceColorMod(surface: *SDL_Surface, r: *uint8_t, g: *uint8_t, b: *uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceAlphaMod(surface: *SDL_Surface, alpha: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceAlphaMod(surface: *SDL_Surface, alpha: *uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceBlendMode(surface: *SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
        pub fn SDL_GetSurfaceBlendMode(surface: *SDL_Surface, blendMode: *SDL_BlendMode) -> c_int;
        pub fn SDL_SetClipRect(surface: *SDL_Surface, rect: *SDL_Rect) ->  SDL_bool;
        pub fn SDL_GetClipRect(surface: *SDL_Surface, rect: *SDL_Rect);
        pub fn SDL_ConvertSurface(src: *SDL_Surface, fmt: *SDL_PixelFormat, flags: uint32_t) ->  *SDL_Surface;
        pub fn SDL_ConvertSurfaceFormat(src: *SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *SDL_Surface;
        pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *c_void, src_pitch: c_int, dst_format: uint32_t, dst: *c_void, dst_pitch: c_int) -> c_int;
        pub fn SDL_FillRect(dst: *SDL_Surface, rect: *SDL_Rect, color: uint32_t) -> c_int;
        pub fn SDL_FillRects(dst: *SDL_Surface, rects: *SDL_Rect, count: c_int, color: uint32_t) -> c_int;
        pub fn SDL_UpperBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_LowerBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_SoftStretch(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_UpperBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_LowerBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    }
}

flag_type!(SurfaceFlag {
    SWSurface = ll::SDL_SWSURFACE,
    PreAlloc = ll::SDL_PREALLOC,
    RLEAccel = ll::SDL_RLEACCEL,
    DontFree = ll::SDL_DONTFREE
})

#[deriving(Eq)] #[allow(raw_pointer_deriving)]
pub struct Surface {
    pub raw: *ll::SDL_Surface,
    pub owned: bool
}

impl Drop for Surface {
    fn drop(&mut self) {
        if self.owned {
            unsafe {
                ll::SDL_FreeSurface(self.raw);
            }
        }
    }
}

impl Surface {
    pub fn new(surface_flags: SurfaceFlag, width: int, height: int, bpp: int,
               rmask: u32, gmask: u32, bmask: u32, amask: u32) -> Result<Surface, ~str> {
        unsafe {
            let raw = ll::SDL_CreateRGBSurface(surface_flags.get(), width as c_int, height as c_int, bpp as c_int,
                                               rmask, gmask, bmask, amask);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Surface { raw: raw, owned: true })
            }
        }
    }

    //TODO: From Data
    pub fn get_width(&self) -> u16 {
        unsafe { (*self.raw).w as u16 }
    }

    pub fn get_height(&self) -> u16 {
        unsafe { (*self.raw).h as u16 }
    }

    pub fn get_size(&self) -> (u16, u16) {
        (self.get_width(), self.get_height())
    }

    pub fn get_rect(&self) -> Rect {
        Rect {
            x: 0,
            y: 0,
            w: self.get_width() as i32,
            h: self.get_height() as i32
        }
    }

    pub fn get_pixel_format(&self) -> pixels::PixelFormat {
        pixels::PixelFormat {
            raw: unsafe { (*self.raw).format }
        }
    }

    pub fn lock(&self) -> bool {
        unsafe { ll::SDL_LockSurface(self.raw) == 0 }
    }

    /// Locks a surface so that the pixels can be directly accessed safely.
    pub fn with_lock<R>(&self, f: |pixels: &mut [u8]| -> R) -> R {
        unsafe {
            if ll::SDL_LockSurface(self.raw) != 0 { fail!("could not lock surface"); }
            let len = (*self.raw).pitch as uint * ((*self.raw).h as uint);
            let pixels: &mut [u8] = cast::transmute(((*self.raw).pixels, len));
            let rv = f(pixels);
            ll::SDL_UnlockSurface(self.raw);
            rv
        }
    }

    pub fn unlock(&self) {
        unsafe { ll::SDL_UnlockSurface(self.raw); }
    }

    pub fn from_bmp(path: &Path) -> Result<Surface, ~str> {
        let raw = unsafe {
            ll::SDL_LoadBMP_RW(try!(rwops::RWops::from_file(path, "rb")).raw, 0)
        };

        if raw.is_null() { Err(get_error()) }
        else { Ok(Surface{raw: raw, owned: true}) }
    }

    pub fn save_bmp(&self, path: &Path) -> Result<(), ~str> {
	let ret = unsafe {
            ll::SDL_SaveBMP_RW(self.raw, try!(rwops::RWops::from_file(path, "rb")).raw, 0)
	};
        if ret == 0 { Ok(()) }
        else { Err(get_error()) }
    }

    pub fn set_palette(&self, palette: &pixels::Palette) -> bool {
        unsafe {
            ll::SDL_SetSurfacePalette(self.raw, palette.raw) == 0
        }
    }

    pub fn enable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 1) == 0
        }
    }

    pub fn disable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 0) == 0
        }
    }

    pub fn set_color_key(&self, enable: bool, color: pixels::Color) -> Result<(), ~str> {
        let key = color.to_u32(&self.get_pixel_format());
        let result = unsafe {
            ll::SDL_SetColorKey(self.raw, ::std::bool::to_bit(enable), key)
        };
        if result == 0 {
            Ok(())
        } else {
            Err(get_error())
        }
    }

    pub fn get_color_key(&self) -> Result<pixels::Color, ~str> {
        let key: u32 = 0;
        let result = unsafe {
            ll::SDL_GetColorKey(self.raw, &key)
        };

        if result == 0 {
            Ok(pixels::Color::from_u32(&self.get_pixel_format(), key))
        } else {
            Err(get_error())
        }
    }

    pub fn set_color_mod(&self, color: pixels::Color) -> bool {
        let (r, g, b) = match color {
            pixels::RGB(r, g, b) => (r, g, b),
            pixels::RGBA(r, g, b, _) => (r, g, b)
        };

        unsafe {
            ll::SDL_SetSurfaceColorMod(self.raw, r, g, b) == 0
        }
    }

    pub fn get_color_mod(&self) -> Result<pixels::Color, ~str> {
        let r: u8 = 0;
        let g: u8 = 0;
        let b: u8 = 0;

        let result = unsafe {
            ll::SDL_GetSurfaceColorMod(self.raw, &r, &g, &b) == 0
        };

        if result {
            Ok(pixels::RGB(r,g,b))
        } else {
            Err(get_error())
        }
    }
    /*
    pub fn SDL_SetSurfaceAlphaMod(surface: *SDL_Surface, alpha: uint8_t) -> c_int;
    pub fn SDL_GetSurfaceAlphaMod(surface: *SDL_Surface, alpha: *uint8_t ) -> c_int;
    pub fn SDL_SetSurfaceBlendMode(surface: *SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
    pub fn SDL_GetSurfaceBlendMode(surface: *SDL_Surface, blendMode: *SDL_BlendMode) -> c_int;
    pub fn SDL_SetClipRect(surface: *SDL_Surface, rect: *SDL_Rect) ->  SDL_bool;
    pub fn SDL_GetClipRect(surface: *SDL_Surface, rect: *SDL_Rect);
    pub fn SDL_ConvertSurface(src: *SDL_Surface, fmt: *SDL_PixelFormat, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertSurfaceFormat(src: *SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *c_void, src_pitch: c_int, dst_format: uint32_t, dst: *c_void, dst_pitch: c_int) -> c_int;
    pub fn SDL_FillRect(dst: *SDL_Surface, rect: *SDL_Rect, color: uint32_t) -> c_int;
    pub fn SDL_FillRects(dst: *SDL_Surface, rects: *SDL_Rect, count: c_int, color: uint32_t) -> c_int;
    pub fn SDL_UpperBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_LowerBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_SoftStretch(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_UpperBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_LowerBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int)*/
}
<commit_msg>Implement SDL_UpperBlit as upper_blit<commit_after>use std::cast;
use rect::Rect;
use get_error;
use std::ptr;
use libc::c_int;
use pixels;
use rwops;

#[allow(non_camel_case_types)]
pub mod ll {
    use pixels::ll::SDL_PixelFormat;
    use pixels::ll::SDL_Palette;
    use render::ll::SDL_BlendMode;
    use rwops::ll::SDL_RWops;
    use rect::Rect;
    use libc::{c_int, c_void, uint32_t, uint8_t};
    pub type SDL_Rect = Rect;
    pub type SDL_bool = c_int;

    pub type SDL_SurfaceFlag = c_int;

    pub static SDL_SWSURFACE: SDL_SurfaceFlag = 0;
    pub static SDL_PREALLOC: SDL_SurfaceFlag = 0x00000001;
    pub static SDL_RLEACCEL: SDL_SurfaceFlag = 0x00000002;
    pub static SDL_DONTFREE: SDL_SurfaceFlag = 0x00000004;

    //SDL_surface.h
    pub struct SDL_BlitMap;

    pub struct SDL_Surface {
        pub flags: uint32_t,
        pub format: *SDL_PixelFormat,
        pub w: c_int,
        pub h: c_int,
        pub pitch: c_int,
        pub pixels: *c_void,
        pub userdata: *c_void,
        pub locked: c_int,
        pub lock_data: *c_void,
        pub clip_rect: SDL_Rect,
        pub map: *SDL_BlitMap,
        pub refcount: c_int
    }

    extern "C" {
        pub fn SDL_CreateRGBSurface(flags: uint32_t, width: c_int, height: c_int, depth: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *SDL_Surface;
        pub fn SDL_CreateRGBSurfaceFrom(pixels: *c_void, width: c_int, height: c_int, depth: c_int, pitch: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *SDL_Surface;
        pub fn SDL_FreeSurface(surface: *SDL_Surface);
        pub fn SDL_SetSurfacePalette(surface: *SDL_Surface, palette: *SDL_Palette) -> c_int;
        pub fn SDL_LockSurface(surface: *SDL_Surface) -> c_int;
        pub fn SDL_UnlockSurface(surface: *SDL_Surface);
        pub fn SDL_LoadBMP_RW(src: *SDL_RWops, freesrc: c_int) ->  *SDL_Surface;
        pub fn SDL_SaveBMP_RW(surface: *SDL_Surface, dst: *SDL_RWops, freedst: c_int) -> c_int;
        pub fn SDL_SetSurfaceRLE(surface: *SDL_Surface, flag: c_int) -> c_int;
        pub fn SDL_SetColorKey(surface: *SDL_Surface, flag: c_int, key: uint32_t) -> c_int;
        pub fn SDL_GetColorKey(surface: *SDL_Surface, key: *uint32_t) -> c_int;
        pub fn SDL_SetSurfaceColorMod(surface: *SDL_Surface, r: uint8_t, g: uint8_t, b: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceColorMod(surface: *SDL_Surface, r: *uint8_t, g: *uint8_t, b: *uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceAlphaMod(surface: *SDL_Surface, alpha: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceAlphaMod(surface: *SDL_Surface, alpha: *uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceBlendMode(surface: *SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
        pub fn SDL_GetSurfaceBlendMode(surface: *SDL_Surface, blendMode: *SDL_BlendMode) -> c_int;
        pub fn SDL_SetClipRect(surface: *SDL_Surface, rect: *SDL_Rect) ->  SDL_bool;
        pub fn SDL_GetClipRect(surface: *SDL_Surface, rect: *SDL_Rect);
        pub fn SDL_ConvertSurface(src: *SDL_Surface, fmt: *SDL_PixelFormat, flags: uint32_t) ->  *SDL_Surface;
        pub fn SDL_ConvertSurfaceFormat(src: *SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *SDL_Surface;
        pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *c_void, src_pitch: c_int, dst_format: uint32_t, dst: *c_void, dst_pitch: c_int) -> c_int;
        pub fn SDL_FillRect(dst: *SDL_Surface, rect: *SDL_Rect, color: uint32_t) -> c_int;
        pub fn SDL_FillRects(dst: *SDL_Surface, rects: *SDL_Rect, count: c_int, color: uint32_t) -> c_int;
        pub fn SDL_UpperBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_LowerBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_SoftStretch(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_UpperBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_LowerBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    }
}

flag_type!(SurfaceFlag {
    SWSurface = ll::SDL_SWSURFACE,
    PreAlloc = ll::SDL_PREALLOC,
    RLEAccel = ll::SDL_RLEACCEL,
    DontFree = ll::SDL_DONTFREE
})

#[deriving(Eq)] #[allow(raw_pointer_deriving)]
pub struct Surface {
    pub raw: *ll::SDL_Surface,
    pub owned: bool
}

impl Drop for Surface {
    fn drop(&mut self) {
        if self.owned {
            unsafe {
                ll::SDL_FreeSurface(self.raw);
            }
        }
    }
}

impl Surface {
    pub fn new(surface_flags: SurfaceFlag, width: int, height: int, bpp: int,
               rmask: u32, gmask: u32, bmask: u32, amask: u32) -> Result<Surface, ~str> {
        unsafe {
            let raw = ll::SDL_CreateRGBSurface(surface_flags.get(), width as c_int, height as c_int, bpp as c_int,
                                               rmask, gmask, bmask, amask);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Surface { raw: raw, owned: true })
            }
        }
    }

    //TODO: From Data
    pub fn get_width(&self) -> u16 {
        unsafe { (*self.raw).w as u16 }
    }

    pub fn get_height(&self) -> u16 {
        unsafe { (*self.raw).h as u16 }
    }

    pub fn get_size(&self) -> (u16, u16) {
        (self.get_width(), self.get_height())
    }

    pub fn get_rect(&self) -> Rect {
        Rect {
            x: 0,
            y: 0,
            w: self.get_width() as i32,
            h: self.get_height() as i32
        }
    }

    pub fn get_pixel_format(&self) -> pixels::PixelFormat {
        pixels::PixelFormat {
            raw: unsafe { (*self.raw).format }
        }
    }

    pub fn lock(&self) -> bool {
        unsafe { ll::SDL_LockSurface(self.raw) == 0 }
    }

    /// Locks a surface so that the pixels can be directly accessed safely.
    pub fn with_lock<R>(&self, f: |pixels: &mut [u8]| -> R) -> R {
        unsafe {
            if ll::SDL_LockSurface(self.raw) != 0 { fail!("could not lock surface"); }
            let len = (*self.raw).pitch as uint * ((*self.raw).h as uint);
            let pixels: &mut [u8] = cast::transmute(((*self.raw).pixels, len));
            let rv = f(pixels);
            ll::SDL_UnlockSurface(self.raw);
            rv
        }
    }

    pub fn unlock(&self) {
        unsafe { ll::SDL_UnlockSurface(self.raw); }
    }

    pub fn from_bmp(path: &Path) -> Result<Surface, ~str> {
        let raw = unsafe {
            ll::SDL_LoadBMP_RW(try!(rwops::RWops::from_file(path, "rb")).raw, 0)
        };

        if raw.is_null() { Err(get_error()) }
        else { Ok(Surface{raw: raw, owned: true}) }
    }

    pub fn save_bmp(&self, path: &Path) -> Result<(), ~str> {
	let ret = unsafe {
            ll::SDL_SaveBMP_RW(self.raw, try!(rwops::RWops::from_file(path, "rb")).raw, 0)
	};
        if ret == 0 { Ok(()) }
        else { Err(get_error()) }
    }

    pub fn set_palette(&self, palette: &pixels::Palette) -> bool {
        unsafe {
            ll::SDL_SetSurfacePalette(self.raw, palette.raw) == 0
        }
    }

    pub fn enable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 1) == 0
        }
    }

    pub fn disable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 0) == 0
        }
    }

    pub fn set_color_key(&self, enable: bool, color: pixels::Color) -> Result<(), ~str> {
        let key = color.to_u32(&self.get_pixel_format());
        let result = unsafe {
            ll::SDL_SetColorKey(self.raw, ::std::bool::to_bit(enable), key)
        };
        if result == 0 {
            Ok(())
        } else {
            Err(get_error())
        }
    }

    pub fn get_color_key(&self) -> Result<pixels::Color, ~str> {
        let key: u32 = 0;
        let result = unsafe {
            ll::SDL_GetColorKey(self.raw, &key)
        };

        if result == 0 {
            Ok(pixels::Color::from_u32(&self.get_pixel_format(), key))
        } else {
            Err(get_error())
        }
    }

    pub fn set_color_mod(&self, color: pixels::Color) -> bool {
        let (r, g, b) = match color {
            pixels::RGB(r, g, b) => (r, g, b),
            pixels::RGBA(r, g, b, _) => (r, g, b)
        };

        unsafe {
            ll::SDL_SetSurfaceColorMod(self.raw, r, g, b) == 0
        }
    }

    pub fn get_color_mod(&self) -> Result<pixels::Color, ~str> {
        let r: u8 = 0;
        let g: u8 = 0;
        let b: u8 = 0;

        let result = unsafe {
            ll::SDL_GetSurfaceColorMod(self.raw, &r, &g, &b) == 0
        };

        if result {
            Ok(pixels::RGB(r,g,b))
        } else {
            Err(get_error())
        }
    }

    pub fn upper_blit( &self, src: &Surface, dstrect: Option<Rect>, srcrect: Option<Rect> ) -> bool {
        unsafe {
            match( srcrect, dstrect ) {
                (Some( srcrect ), Some( dstrect )) =>
                    ll::SDL_UpperBlit( src.raw, &srcrect, self.raw, &dstrect ) == 0,
                (Some( srcrect ), None) =>
                    ll::SDL_UpperBlit( src.raw, &srcrect, self.raw, ptr::null() ) == 0,
                (None, Some( dstrect )) =>
                    ll::SDL_UpperBlit( src.raw, ptr::null(), self.raw, &dstrect ) == 0,
                (None, None) =>
                    ll::SDL_UpperBlit( src.raw, ptr::null(), self.raw, ptr::null() ) == 0
            }
        }
    }

    /*
    pub fn SDL_SetSurfaceAlphaMod(surface: *SDL_Surface, alpha: uint8_t) -> c_int;
    pub fn SDL_GetSurfaceAlphaMod(surface: *SDL_Surface, alpha: *uint8_t ) -> c_int;
    pub fn SDL_SetSurfaceBlendMode(surface: *SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
    pub fn SDL_GetSurfaceBlendMode(surface: *SDL_Surface, blendMode: *SDL_BlendMode) -> c_int;
    pub fn SDL_SetClipRect(surface: *SDL_Surface, rect: *SDL_Rect) ->  SDL_bool;
    pub fn SDL_GetClipRect(surface: *SDL_Surface, rect: *SDL_Rect);
    pub fn SDL_ConvertSurface(src: *SDL_Surface, fmt: *SDL_PixelFormat, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertSurfaceFormat(src: *SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *c_void, src_pitch: c_int, dst_format: uint32_t, dst: *c_void, dst_pitch: c_int) -> c_int;
    pub fn SDL_FillRect(dst: *SDL_Surface, rect: *SDL_Rect, color: uint32_t) -> c_int;
    pub fn SDL_FillRects(dst: *SDL_Surface, rects: *SDL_Rect, count: c_int, color: uint32_t) -> c_int;
    pub fn SDL_LowerBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_SoftStretch(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_UpperBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_LowerBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int)*/
}
<|endoftext|>


<commit_before>#![no_std]
#![allow(ctypes)]
#![feature(lang_items)]

extern crate core;

use core::iter;
use core::str::StrExt;

use core::kinds::Copy;

impl Copy for Color {}

enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

enum Option<T> {
    None,
    Some(T)
}

struct IntRange {
    cur: int,
    max: int
}

impl IntRange {
    fn next(&mut self) -> Option<int> {
        if self.cur < self.max {
            self.cur += 1;
            Option::Some(self.cur - 1)
        } else {
            Option::None
        }
    }
}

fn range(lo: int, hi: int) -> IntRange {
    IntRange { cur: lo, max: hi }
}

fn clear_screen(background: Color) {
    let mut r = range(0, 80 * 25);
    loop {
        match r.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
                }
            },
            Option::None =>{break}
        }
    }
}

fn print_string(string: &str) {
        unsafe {
            let character = 'A' as u8;
            *((0xb8000) as *mut u8) = character;
            *((0xb8000+1) as *mut u8) = 0x0f;
        }
    let bytes = string.chars();
        unsafe {
            let character = 'B' as u8;
            *((0xb8000) as *mut u8) = character;
            *((0xb8000+1) as *mut u8) = 0x0f;
        }
}

#[no_mangle]
#[no_split_stack]
pub fn main() {
    clear_screen(Color::LightRed);
    print_string("A");
}
<commit_msg>Print garbled Hello world string.<commit_after>#![no_std]
#![allow(ctypes)]

extern crate core;

use core::iter::Iterator;
use core::str::StrExt;
use core::option::Option;

use core::kinds::Copy;

impl Copy for Color {}

enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

struct IntRange {
    cur: int,
    max: int
}

impl IntRange {
    fn next(&mut self) -> Option<int> {
        if self.cur < self.max {
            self.cur += 1;
            Option::Some(self.cur - 1)
        } else {
            Option::None
        }
    }
}

fn range(lo: int, hi: int) -> IntRange {
    IntRange { cur: lo, max: hi }
}

fn clear_screen(background: Color) {
    let mut r = range(0, 80 * 25);
    loop {
        match r.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
                }
            },
            Option::None =>{break}
        }
    }
}

fn print_string(string: &str) {
    let mut bytes = string.bytes();
    let mut count = 0;
    loop {
        match bytes.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + count) as *mut u8) = x as u8;
                    *((0xb8000 + count + 1) as *mut u8) = 0x0f;
                }
                count = count + 1;
            },
            Option::None =>{break}
        }
    }
}

#[no_mangle]
#[no_split_stack]
pub fn main() {
    clear_screen(Color::LightRed);
    print_string("Hello world");
}
<|endoftext|>


<commit_before>fn encode<T: Clone+Eq>(list: &[T]) -> ~[(uint, T)] {
    let mut it = list.iter();
    let mut result = ~[];
    let mut l = 1;
    loop {
        match it.nth(l - 1) {
            Some(e) => {
                l = it.take_while(|&a| *a == *e).len() + 1;
                result.push((l, e.clone()))
            },
            None    => break
        }
    }
    result
}

fn main() {
    let list =
        ~['a', 'a', 'a', 'a', 'b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e', 'e'];

    println!("{:?}", encode(list));
}
<commit_msg>Cleanup Problem 13<commit_after>// The author of this work hereby waives all claim of copyright (economic and
// moral) in this work and immediately places it in the public domain; it may
// be used, distorted or destroyed in any manner whatsoever without further
// attribution or notice to the creator.

//! Problem 13: Vectors: encode_ter
//!
//! Implement the so-called run-length encoding data compression method
//! directly. I.e. don't explicitly create the sublists containing the
//! duplicates, as in problem "Pack consecutive duplicates of list elements
//! into sublists", but only count them. As in problem "Modified run-length
//! encoding", simplify the result list by replacing the singleton lists
//! (1 X) by X.
//!
//! Your function could have this signature:
//! `fn encode_ter<T>(vec: ~[T]) -> ~[Node<T>]`

#[deriving(Eq)]
#[deriving(Show)]
enum Node<T> {
    One(T),
    Many(uint, T)
}

fn encode_ter<T: Eq>(vec: ~[T]) -> ~[Node<T>] {
    let mut input = vec.move_iter().peekable();
    let mut n = 1;
    let mut result = ~[];

    while !input.peek().is_none() {
        match (input.next(), input.peek()) {
            (Some(a), Some(b)) =>
                if a != *b {
                    if n == 1 {
                        result.push(One(a));
                    } else {
                        result.push(Many(n, a));
                        n = 1;
                    }
                } else {
                    n += 1
                },
            (Some(a), None) => {result.push(Many(n, a)); n = 1},
            (None, _) => unreachable!()
        }
    }
    result
}

#[test]
fn encode_ter_test() {
    let vec = ~['a', 'a', 'a', 'a',
                'b',
                'c', 'c',
                'a', 'a',
                'd',
                'e', 'e', 'e', 'e'];

    assert_eq!(encode_ter(vec), ~[  Many(4, 'a'),
                                    One('b'),
                                    Many(2, 'c'),
                                    Many(2, 'a'),
                                    One('d'),
                                    Many(4, 'e')])
}
<|endoftext|>


<commit_before>use nix::sys::uio::*;
use nix::unistd::*;
use rand::{thread_rng, Rng};
use std::{cmp, iter};
use std::fs::{OpenOptions};
use std::os::unix::io::AsRawFd;

use tempdir::TempDir;
use tempfile::tempfile;

#[test]
fn test_writev() {
    let mut to_write = Vec::with_capacity(16 * 128);
    for _ in 0..16 {
        let s: String = thread_rng().gen_ascii_chars().take(128).collect();
        let b = s.as_bytes();
        to_write.extend(b.iter().map(|x| x.clone()));
    }
    // Allocate and fill iovecs
    let mut iovecs = Vec::new();
    let mut consumed = 0;
    while consumed < to_write.len() {
        let left = to_write.len() - consumed;
        let slice_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
        let b = &to_write[consumed..consumed+slice_len];
        iovecs.push(IoVec::from_slice(b));
        consumed += slice_len;
    }
    let pipe_res = pipe();
    assert!(pipe_res.is_ok());
    let (reader, writer) = pipe_res.ok().unwrap();
    // FileDesc will close its filedesc (reader).
    let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
    // Blocking io, should write all data.
    let write_res = writev(writer, &iovecs);
    // Successful write
    assert!(write_res.is_ok());
    let written = write_res.ok().unwrap();
    // Check whether we written all data
    assert_eq!(to_write.len(), written);
    let read_res = read(reader, &mut read_buf[..]);
    // Successful read
    assert!(read_res.is_ok());
    let read = read_res.ok().unwrap() as usize;
    // Check we have read as much as we written
    assert_eq!(read, written);
    // Check equality of written and read data
    assert_eq!(&to_write, &read_buf);
    let close_res = close(writer);
    assert!(close_res.is_ok());
    let close_res = close(reader);
    assert!(close_res.is_ok());
}

#[test]
fn test_readv() {
    let s:String = thread_rng().gen_ascii_chars().take(128).collect();
    let to_write = s.as_bytes().to_vec();
    let mut storage = Vec::new();
    let mut allocated = 0;
    while allocated < to_write.len() {
        let left = to_write.len() - allocated;
        let vec_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
        let v: Vec<u8> = iter::repeat(0u8).take(vec_len).collect();
        storage.push(v);
        allocated += vec_len;
    }
    let mut iovecs = Vec::with_capacity(storage.len());
    for v in storage.iter_mut() {
        iovecs.push(IoVec::from_mut_slice(&mut v[..]));
    }
    let pipe_res = pipe();
    assert!(pipe_res.is_ok());
    let (reader, writer) = pipe_res.ok().unwrap();
    // Blocking io, should write all data.
    let write_res = write(writer, &to_write);
    // Successful write
    assert!(write_res.is_ok());
    let read_res = readv(reader, &mut iovecs[..]);
    assert!(read_res.is_ok());
    let read = read_res.ok().unwrap();
    // Check whether we've read all data
    assert_eq!(to_write.len(), read);
    // Cccumulate data from iovecs
    let mut read_buf = Vec::with_capacity(to_write.len());
    for iovec in iovecs.iter() {
        read_buf.extend(iovec.as_slice().iter().map(|x| x.clone()));
    }
    // Check whether iovecs contain all written data
    assert_eq!(read_buf.len(), to_write.len());
    // Check equality of written and read data
    assert_eq!(&read_buf, &to_write);
    let close_res = close(reader);
    assert!(close_res.is_ok());
    let close_res = close(writer);
    assert!(close_res.is_ok());
}

#[test]
fn test_pwrite() {
    use std::io::Read;

    let mut file = tempfile().unwrap();
    let buf = [1u8;8];
    assert_eq!(Ok(8), pwrite(file.as_raw_fd(), &buf, 8));
    let mut file_content = Vec::new();
    file.read_to_end(&mut file_content).unwrap();
    let mut expected = vec![0u8;8];
    expected.extend(vec![1;8]);
    assert_eq!(file_content, expected);
}

#[test]
fn test_pread() {
    use std::io::Write;

    let tempdir = TempDir::new("nix-test_pread").unwrap();

    let path = tempdir.path().join("pread_test_file");
    let mut file = OpenOptions::new().write(true).read(true).create(true)
                                    .truncate(true).open(path).unwrap();
    let file_content: Vec<u8> = (0..64).collect();
    file.write_all(&file_content).unwrap();

    let mut buf = [0u8;16];
    assert_eq!(Ok(16), pread(file.as_raw_fd(), &mut buf, 16));
    let expected: Vec<_> = (16..32).collect();
    assert_eq!(&buf[..], &expected[..]);
}

#[test]
#[cfg(target_os = "linux")]
fn test_pwritev() {
    use std::io::Read;

    let to_write: Vec<u8> = (0..128).collect();
    let expected: Vec<u8> = [vec![0;100], to_write.clone()].concat();

    let iovecs = [
        IoVec::from_slice(&to_write[0..17]),
        IoVec::from_slice(&to_write[17..64]),
        IoVec::from_slice(&to_write[64..128]),
    ];

    let tempdir = TempDir::new("nix-test_pwritev").unwrap();

    // pwritev them into a temporary file
    let path = tempdir.path().join("pwritev_test_file");
    let mut file = OpenOptions::new().write(true).read(true).create(true)
                                    .truncate(true).open(path).unwrap();

    let written = pwritev(file.as_raw_fd(), &iovecs, 100).ok().unwrap();
    assert_eq!(written, to_write.len());

    // Read the data back and make sure it matches
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(contents, expected);
}

#[test]
#[cfg(target_os = "linux")]
fn test_preadv() {
    use std::io::Write;

    let to_write: Vec<u8> = (0..200).collect();
    let expected: Vec<u8> = (100..200).collect();

    let tempdir = TempDir::new("nix-test_preadv").unwrap();

    let path = tempdir.path().join("preadv_test_file");

    let mut file = OpenOptions::new().read(true).write(true).create(true)
                                    .truncate(true).open(path).unwrap();
    file.write_all(&to_write).unwrap();

    let mut buffers: Vec<Vec<u8>> = vec![
        vec![0; 24],
        vec![0; 1],
        vec![0; 75],
    ];

    {
        // Borrow the buffers into IoVecs and preadv into them
        let mut iovecs: Vec<_> = buffers.iter_mut().map(
            |buf| IoVec::from_mut_slice(&mut buf[..])).collect();
        assert_eq!(Ok(100), preadv(file.as_raw_fd(), &mut iovecs, 100));
    }

    let all = buffers.concat();
    assert_eq!(all, expected);
}

#[test]
#[cfg(target_os = "linux")]
// FIXME: qemu-user doesn't implement process_vm_readv/writev on most arches
#[cfg_attr(not(any(target_arch = "x86", target_arch = "x86_64")), ignore)]
fn test_process_vm_readv() {
    use nix::unistd::ForkResult::*;
    use nix::sys::signal::*;
    use nix::sys::wait::*;

    #[allow(unused_variables)]
    let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");

    // Pre-allocate memory in the child, since allocation isn't safe
    // post-fork (~= async-signal-safe)
    let mut vector = vec![1u8, 2, 3, 4, 5];

    let (r, w) = pipe().unwrap();
    match fork() {
        Ok(Parent { child }) => {
            close(w).unwrap();
            // wait for child
            read(r, &mut vec![0u8]).unwrap();
            close(r).unwrap();

            let ptr = vector.as_ptr() as usize;
            let remote_iov = RemoteIoVec { base: ptr, len: 5 };
            let mut buf = vec![0u8; 5];

            let ret = process_vm_readv(child,
                                       &[IoVec::from_mut_slice(&mut buf)],
                                       &[remote_iov]);

            kill(child, SIGTERM).unwrap();
            waitpid(child, None).unwrap();

            assert_eq!(Ok(5), ret);
            assert_eq!(20u8, buf.iter().sum());
        },
        Ok(Child) => {
            let _ = close(r);
            for i in vector.iter_mut() {
                *i += 1;
            }
            let _ = write(w, b"\0");
            let _ = close(w);
            loop { let _ = pause(); }
        },
        Err(_) => panic!("fork failed")
    }
}
<commit_msg>Remove useless vec![]<commit_after>use nix::sys::uio::*;
use nix::unistd::*;
use rand::{thread_rng, Rng};
use std::{cmp, iter};
use std::fs::{OpenOptions};
use std::os::unix::io::AsRawFd;

use tempdir::TempDir;
use tempfile::tempfile;

#[test]
fn test_writev() {
    let mut to_write = Vec::with_capacity(16 * 128);
    for _ in 0..16 {
        let s: String = thread_rng().gen_ascii_chars().take(128).collect();
        let b = s.as_bytes();
        to_write.extend(b.iter().map(|x| x.clone()));
    }
    // Allocate and fill iovecs
    let mut iovecs = Vec::new();
    let mut consumed = 0;
    while consumed < to_write.len() {
        let left = to_write.len() - consumed;
        let slice_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
        let b = &to_write[consumed..consumed+slice_len];
        iovecs.push(IoVec::from_slice(b));
        consumed += slice_len;
    }
    let pipe_res = pipe();
    assert!(pipe_res.is_ok());
    let (reader, writer) = pipe_res.ok().unwrap();
    // FileDesc will close its filedesc (reader).
    let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
    // Blocking io, should write all data.
    let write_res = writev(writer, &iovecs);
    // Successful write
    assert!(write_res.is_ok());
    let written = write_res.ok().unwrap();
    // Check whether we written all data
    assert_eq!(to_write.len(), written);
    let read_res = read(reader, &mut read_buf[..]);
    // Successful read
    assert!(read_res.is_ok());
    let read = read_res.ok().unwrap() as usize;
    // Check we have read as much as we written
    assert_eq!(read, written);
    // Check equality of written and read data
    assert_eq!(&to_write, &read_buf);
    let close_res = close(writer);
    assert!(close_res.is_ok());
    let close_res = close(reader);
    assert!(close_res.is_ok());
}

#[test]
fn test_readv() {
    let s:String = thread_rng().gen_ascii_chars().take(128).collect();
    let to_write = s.as_bytes().to_vec();
    let mut storage = Vec::new();
    let mut allocated = 0;
    while allocated < to_write.len() {
        let left = to_write.len() - allocated;
        let vec_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
        let v: Vec<u8> = iter::repeat(0u8).take(vec_len).collect();
        storage.push(v);
        allocated += vec_len;
    }
    let mut iovecs = Vec::with_capacity(storage.len());
    for v in storage.iter_mut() {
        iovecs.push(IoVec::from_mut_slice(&mut v[..]));
    }
    let pipe_res = pipe();
    assert!(pipe_res.is_ok());
    let (reader, writer) = pipe_res.ok().unwrap();
    // Blocking io, should write all data.
    let write_res = write(writer, &to_write);
    // Successful write
    assert!(write_res.is_ok());
    let read_res = readv(reader, &mut iovecs[..]);
    assert!(read_res.is_ok());
    let read = read_res.ok().unwrap();
    // Check whether we've read all data
    assert_eq!(to_write.len(), read);
    // Cccumulate data from iovecs
    let mut read_buf = Vec::with_capacity(to_write.len());
    for iovec in iovecs.iter() {
        read_buf.extend(iovec.as_slice().iter().map(|x| x.clone()));
    }
    // Check whether iovecs contain all written data
    assert_eq!(read_buf.len(), to_write.len());
    // Check equality of written and read data
    assert_eq!(&read_buf, &to_write);
    let close_res = close(reader);
    assert!(close_res.is_ok());
    let close_res = close(writer);
    assert!(close_res.is_ok());
}

#[test]
fn test_pwrite() {
    use std::io::Read;

    let mut file = tempfile().unwrap();
    let buf = [1u8;8];
    assert_eq!(Ok(8), pwrite(file.as_raw_fd(), &buf, 8));
    let mut file_content = Vec::new();
    file.read_to_end(&mut file_content).unwrap();
    let mut expected = vec![0u8;8];
    expected.extend(vec![1;8]);
    assert_eq!(file_content, expected);
}

#[test]
fn test_pread() {
    use std::io::Write;

    let tempdir = TempDir::new("nix-test_pread").unwrap();

    let path = tempdir.path().join("pread_test_file");
    let mut file = OpenOptions::new().write(true).read(true).create(true)
                                    .truncate(true).open(path).unwrap();
    let file_content: Vec<u8> = (0..64).collect();
    file.write_all(&file_content).unwrap();

    let mut buf = [0u8;16];
    assert_eq!(Ok(16), pread(file.as_raw_fd(), &mut buf, 16));
    let expected: Vec<_> = (16..32).collect();
    assert_eq!(&buf[..], &expected[..]);
}

#[test]
#[cfg(target_os = "linux")]
fn test_pwritev() {
    use std::io::Read;

    let to_write: Vec<u8> = (0..128).collect();
    let expected: Vec<u8> = [vec![0;100], to_write.clone()].concat();

    let iovecs = [
        IoVec::from_slice(&to_write[0..17]),
        IoVec::from_slice(&to_write[17..64]),
        IoVec::from_slice(&to_write[64..128]),
    ];

    let tempdir = TempDir::new("nix-test_pwritev").unwrap();

    // pwritev them into a temporary file
    let path = tempdir.path().join("pwritev_test_file");
    let mut file = OpenOptions::new().write(true).read(true).create(true)
                                    .truncate(true).open(path).unwrap();

    let written = pwritev(file.as_raw_fd(), &iovecs, 100).ok().unwrap();
    assert_eq!(written, to_write.len());

    // Read the data back and make sure it matches
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(contents, expected);
}

#[test]
#[cfg(target_os = "linux")]
fn test_preadv() {
    use std::io::Write;

    let to_write: Vec<u8> = (0..200).collect();
    let expected: Vec<u8> = (100..200).collect();

    let tempdir = TempDir::new("nix-test_preadv").unwrap();

    let path = tempdir.path().join("preadv_test_file");

    let mut file = OpenOptions::new().read(true).write(true).create(true)
                                    .truncate(true).open(path).unwrap();
    file.write_all(&to_write).unwrap();

    let mut buffers: Vec<Vec<u8>> = vec![
        vec![0; 24],
        vec![0; 1],
        vec![0; 75],
    ];

    {
        // Borrow the buffers into IoVecs and preadv into them
        let mut iovecs: Vec<_> = buffers.iter_mut().map(
            |buf| IoVec::from_mut_slice(&mut buf[..])).collect();
        assert_eq!(Ok(100), preadv(file.as_raw_fd(), &mut iovecs, 100));
    }

    let all = buffers.concat();
    assert_eq!(all, expected);
}

#[test]
#[cfg(target_os = "linux")]
// FIXME: qemu-user doesn't implement process_vm_readv/writev on most arches
#[cfg_attr(not(any(target_arch = "x86", target_arch = "x86_64")), ignore)]
fn test_process_vm_readv() {
    use nix::unistd::ForkResult::*;
    use nix::sys::signal::*;
    use nix::sys::wait::*;

    #[allow(unused_variables)]
    let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");

    // Pre-allocate memory in the child, since allocation isn't safe
    // post-fork (~= async-signal-safe)
    let mut vector = vec![1u8, 2, 3, 4, 5];

    let (r, w) = pipe().unwrap();
    match fork() {
        Ok(Parent { child }) => {
            close(w).unwrap();
            // wait for child
            read(r, &mut [0u8]).unwrap();
            close(r).unwrap();

            let ptr = vector.as_ptr() as usize;
            let remote_iov = RemoteIoVec { base: ptr, len: 5 };
            let mut buf = vec![0u8; 5];

            let ret = process_vm_readv(child,
                                       &[IoVec::from_mut_slice(&mut buf)],
                                       &[remote_iov]);

            kill(child, SIGTERM).unwrap();
            waitpid(child, None).unwrap();

            assert_eq!(Ok(5), ret);
            assert_eq!(20u8, buf.iter().sum());
        },
        Ok(Child) => {
            let _ = close(r);
            for i in vector.iter_mut() {
                *i += 1;
            }
            let _ = write(w, b"\0");
            let _ = close(w);
            loop { let _ = pause(); }
        },
        Err(_) => panic!("fork failed")
    }
}
<|endoftext|>


<commit_before>#![feature(globs)]
extern crate rdb;
use rdb::*;
use std::io::MemReader;

#[test]
fn test_read_length() {
    assert_eq!(
        LengthEncoded::LE(0, false),
        read_length_with_encoding(&mut MemReader::new(vec!(0x0)))
        );

    assert_eq!(
        LengthEncoded::LE(16383, false),
        read_length_with_encoding(&mut MemReader::new(vec!(0x7f, 0xff)))
        );

    assert_eq!(
        LengthEncoded::LE(4294967295, false),
        read_length_with_encoding(&mut MemReader::new(
                vec!(0x80, 0xff, 0xff, 0xff, 0xff)))
        );

    assert_eq!(
        LengthEncoded::LE(0, true),
        read_length_with_encoding(&mut MemReader::new(vec!(0xC0))));
}

#[test]
fn test_read_blob() {
    assert_eq!(
        vec!(0x61, 0x62, 0x63, 0x64),
        read_blob(&mut MemReader::new(vec!(4, 0x61, 0x62, 0x63, 0x64))));
}

#[test]
fn test_verify_version() {
    assert_eq!(
        true,
        verify_version(&mut MemReader::new(vec!(0x30, 0x30, 0x30, 0x33))));

    assert_eq!(
        false,
        verify_version(&mut MemReader::new(vec!(0x30, 0x30, 0x30, 0x3a))));
}

#[test]
fn test_verify_magic() {
    assert_eq!(
        true,
        verify_magic(&mut MemReader::new(vec!(0x52, 0x45, 0x44, 0x49, 0x53))));

    assert_eq!(
        false,
        verify_magic(&mut MemReader::new(vec!(0x51, 0x0, 0x0, 0x0, 0x0))));
}
<commit_msg>Length encoding is now just a tuple<commit_after>#![feature(globs)]
extern crate rdb;
use rdb::*;
use std::io::MemReader;

#[test]
fn test_read_length() {
    assert_eq!(
        (0, false),
        read_length_with_encoding(&mut MemReader::new(vec!(0x0)))
        );

    assert_eq!(
        (16383, false),
        read_length_with_encoding(&mut MemReader::new(vec!(0x7f, 0xff)))
        );

    assert_eq!(
        (4294967295, false),
        read_length_with_encoding(&mut MemReader::new(
                vec!(0x80, 0xff, 0xff, 0xff, 0xff)))
        );

    assert_eq!(
        (0, true),
        read_length_with_encoding(&mut MemReader::new(vec!(0xC0))));
}

#[test]
fn test_read_blob() {
    assert_eq!(
        vec!(0x61, 0x62, 0x63, 0x64),
        read_blob(&mut MemReader::new(vec!(4, 0x61, 0x62, 0x63, 0x64))));
}

#[test]
fn test_verify_version() {
    assert_eq!(
        true,
        verify_version(&mut MemReader::new(vec!(0x30, 0x30, 0x30, 0x33))));

    assert_eq!(
        false,
        verify_version(&mut MemReader::new(vec!(0x30, 0x30, 0x30, 0x3a))));
}

#[test]
fn test_verify_magic() {
    assert_eq!(
        true,
        verify_magic(&mut MemReader::new(vec!(0x52, 0x45, 0x44, 0x49, 0x53))));

    assert_eq!(
        false,
        verify_magic(&mut MemReader::new(vec!(0x51, 0x0, 0x0, 0x0, 0x0))));
}
<|endoftext|>


<commit_before>// TODO: COPYRIGHT, USE & AUTHORS
// TODO: RUST DOCS!

extern crate rust_monster;
#[macro_use]
extern crate log;
extern crate env_logger;
#[cfg(test)]
mod tests
{
    use rust_monster::ga::ga_core::{GeneticAlgorithm, GASolution, GAFactory, DEBUG_FLAG};
    use rust_monster::ga::ga_population::{GAPopulation, GAPopulationSortOrder, GAPopulationSortBasis};
    use rust_monster::ga::ga_simple::{SimpleGeneticAlgorithm, SimpleGeneticAlgorithmCfg};
    use rust_monster::ga::ga_selectors::*;
    use rust_monster::ga::ga_random::GARandomCtx;

    use env_logger;

    const VAL: f32 = 3.14159;

    struct TestSolution
    {
        fitness: f32
    }
    impl GASolution for TestSolution
    {
        fn new() -> TestSolution
        {
            TestSolution{ fitness: VAL }
        }

        fn clone(&self) -> Self { TestSolution::new() }
        fn evaluate(&mut self) -> f32 { self.fitness }
    #[allow(unused_variables)]
        fn crossover(&self, other : &Self) -> Self { TestSolution::new() }
    #[allow(unused_variables)]
        fn mutate(&mut self, pm : f32) {}
        fn fitness(&self) -> f32 { (1.0 / self.fitness) }
        fn score(&self) -> f32 { self.fitness }
    }

    #[allow(dead_code)]
    struct TestFactory
    {
        starting_fitness: f32
    }
    impl GAFactory<TestSolution> for TestFactory
    {
        fn initial_population(&mut self) -> GAPopulation<TestSolution> {
            GAPopulation::new(vec![TestSolution { fitness: self.starting_fitness }], GAPopulationSortOrder::HighIsBest)
        }
    }

////////////////////////////////////////
// Utility functions

    fn ga_test_setup(test_name: &str)
    {
        let _ =  env_logger::init();
        debug!("{:?}", test_name);
    }

    fn simple_ga_validation(sga:&mut SimpleGeneticAlgorithm<TestSolution>)
    {
        sga.initialize();
        assert_eq!(sga.step(), 1);
        assert_eq!(sga.done(), false);
        assert_eq!(sga.population().size(), 1);
        assert_eq!(sga.population().best().score(), VAL);
    }

////////////////////////////////////////
// Tests

    #[test]
    fn init_test_with_initial_population()
    {
        ga_test_setup("init_test_with_initial_population");
        let initial_population = GAPopulation::new(vec![TestSolution { fitness: VAL}], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : [1; 4],
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(initial_population)
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    fn init_test_with_factory()
    {
        ga_test_setup("init_test_with_factory");
        let mut factory = TestFactory { starting_fitness: VAL };
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : [1; 4],
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 Some(&mut factory as &mut GAFactory<TestSolution>),
                                                 None
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    #[should_panic]
    #[allow(unused_variables)]
    fn init_test_missing_args()
    {
        ga_test_setup("init_test_missing_args");
        let ga : SimpleGeneticAlgorithm<TestSolution> =
                 SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                               d_seed : [1; 4],
                                               flags : DEBUG_FLAG,
                                               max_generations: 100,
                                               ..Default::default()
                                             },
                                             None,
                                             None
                                             );
        // Not reached
    }

    #[test]
    #[should_panic]
    fn init_test_empty_initial_pop()
    {
        ga_test_setup("init_test_empty_initial_pop");
        let empty_initial_population : GAPopulation<TestSolution> = GAPopulation::new(vec![], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : [1; 4],
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(empty_initial_population)
                                                 );
        ga.initialize()
        //Not reached
    }

    // This test should live in the ga_population file directly,
    // but since it requires GASolution objects it is here for now.
    // Maybe we could use a Mocking library.
    // TODO: This doesn't go here.
    #[test]
    fn test_sort_population()
    {
        ga_test_setup("test_sort_population");
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population = GAPopulation::new(vec![TestSolution { fitness: f }, TestSolution { fitness: f_m }], GAPopulationSortOrder::HighIsBest);
        population.sort();

        //TestSolution's Fitness is the inverse of the Score (F = 1/S)
        assert_eq!(population.individual(0, GAPopulationSortBasis::Raw).score(), f);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Raw).score(), f_m);
        assert_eq!(population.individual(0, GAPopulationSortBasis::Scaled).fitness(), i_f_m);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Scaled).fitness(), i_f);
    }

    #[test]
    #[allow(unused_variables)]
    fn test_rank_selector()
    {
        ga_test_setup("test_rank_selector");
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population
          = GAPopulation::new(vec![TestSolution { fitness: f },
                                   TestSolution { fitness: f_m }],
                              GAPopulationSortOrder::HighIsBest);

        {
            let raw_score_selection = GARawScoreBasedSelection;
            let mut raw_rank_selector = GARankSelector::new(&mut population, &raw_score_selection);

            raw_rank_selector.update();

            // Best Raw score is that of 1st solution.
            assert_eq!(raw_rank_selector.select(&mut GARandomCtx::new_unseeded(String::from("test_rank_selector_rng"))).score(), f);
        }

        {
            let scaled_score_selection = GAScaledScoreBasedSelection;
            let mut scaled_rank_selector = GARankSelector::new(&mut population, &scaled_score_selection);

            scaled_rank_selector.update();

            // Best Scaled score is that of 2nd solution (because fitness is inverse of score). Weird. In this case, LowIsBest.
            assert_eq!(scaled_rank_selector.select(&mut GARandomCtx::new_unseeded(String::from("test_rank_selector_rng"))).fitness(), i_f_m);
        }
    }

    #[test]
    fn test_uniform_selector()
    {
        ga_test_setup("test_uniform_selector");
        let f = VAL;
        let f_m = VAL - 1.0;

        let mut population
          = GAPopulation::new(vec![TestSolution { fitness: f },
                                   TestSolution { fitness: f_m }],
                              GAPopulationSortOrder::HighIsBest);

        let mut uniform_selector = GAUniformSelector::new(&mut population);

        uniform_selector.update();

        let selected_individual = uniform_selector.select(&mut GARandomCtx::new_unseeded(String::from("test_rank_selector_rng")));
        assert!(selected_individual.score() == f || selected_individual.score() == f_m);
    }

    #[test]
    #[allow(unused_variables)]
    fn test_roulette_wheel_selector()
    {
        ga_test_setup("test_roulette_wheel_selector");
        // Just exercise the code.
        // TODO: How to test when there is randomness?

        let mut individuals = vec![];
        let mut rng_ctx = GARandomCtx::new_unseeded(String::from("test_roulette_wheel_selector_rng"));

        for i in 1 .. 20
        {
            individuals.push(TestSolution { fitness: rng_ctx.gen::<f32>() });
        }

        let mut population
          = GAPopulation::new(individuals, GAPopulationSortOrder::LowIsBest);

        {
            let raw_score_selection = GARawScoreBasedSelection;

            let mut raw_roulette_wheel_selector
              = GARouletteWheelSelector::new(&mut population, &raw_score_selection);

            raw_roulette_wheel_selector.update();

            raw_roulette_wheel_selector.select(&mut rng_ctx);
        }

        {
            let scaled_score_selection = GAScaledScoreBasedSelection;

            let mut scaled_roulette_wheel_selector
              = GARouletteWheelSelector::new(&mut population, &scaled_score_selection);

            scaled_roulette_wheel_selector.update();

            scaled_roulette_wheel_selector.select(&mut rng_ctx);
        }
    }

    #[test]
    #[allow(unused_variables)]
    fn test_tournament_selector()
    {
        // Just exercise the code.
        // TODO: How to test when there is randomness?

        ga_test_setup("test_tournament_selector");
        let mut individuals = vec![];
        let mut rng_ctx = GARandomCtx::new_unseeded(String::from("test_tournament_selector_rng"));

        for i in 1 .. 20
        {
            individuals.push(TestSolution { fitness: rng_ctx.gen::<f32>() });
        }

        let mut population
          = GAPopulation::new(individuals, GAPopulationSortOrder::LowIsBest);

        {
            let raw_score_selection = GARawScoreBasedSelection;

            let mut raw_tournament_selector
              = GARouletteWheelSelector::new(&mut population, &raw_score_selection);

            raw_tournament_selector.update();

            raw_tournament_selector.select(&mut rng_ctx);
        }

        {
            let scaled_score_selection = GAScaledScoreBasedSelection;

            let mut scaled_tournament_selector
              = GARouletteWheelSelector::new(&mut population, &scaled_score_selection);

            scaled_tournament_selector.update();

            scaled_tournament_selector.select(&mut rng_ctx);
        }
    }

}
<commit_msg>Update select(), new() and update() selector calls with new parameter lists.<commit_after>// TODO: COPYRIGHT, USE & AUTHORS
// TODO: RUST DOCS!

extern crate rust_monster;
#[macro_use]
extern crate log;
extern crate env_logger;
#[cfg(test)]
mod tests
{
    use rust_monster::ga::ga_core::{GeneticAlgorithm, GASolution, GAFactory, DEBUG_FLAG};
    use rust_monster::ga::ga_population::{GAPopulation, GAPopulationSortOrder, GAPopulationSortBasis};
    use rust_monster::ga::ga_simple::{SimpleGeneticAlgorithm, SimpleGeneticAlgorithmCfg};
    use rust_monster::ga::ga_selectors::*;
    use rust_monster::ga::ga_random::GARandomCtx;

    use env_logger;

    const VAL: f32 = 3.14159;

    struct TestSolution
    {
        fitness: f32
    }
    impl GASolution for TestSolution
    {
        fn new() -> TestSolution
        {
            TestSolution{ fitness: VAL }
        }

        fn clone(&self) -> Self { TestSolution::new() }
        fn evaluate(&mut self) -> f32 { self.fitness }
    #[allow(unused_variables)]
        fn crossover(&self, other : &Self) -> Self { TestSolution::new() }
    #[allow(unused_variables)]
        fn mutate(&mut self, pm : f32) {}
        fn fitness(&self) -> f32 { (1.0 / self.fitness) }
        fn score(&self) -> f32 { self.fitness }
    }

    #[allow(dead_code)]
    struct TestFactory
    {
        starting_fitness: f32
    }
    impl GAFactory<TestSolution> for TestFactory
    {
        fn initial_population(&mut self) -> GAPopulation<TestSolution> {
            GAPopulation::new(vec![TestSolution { fitness: self.starting_fitness }], GAPopulationSortOrder::HighIsBest)
        }
    }

////////////////////////////////////////
// Utility functions

    fn ga_test_setup(test_name: &str)
    {
        let _ =  env_logger::init();
        debug!("{:?}", test_name);
    }

    fn simple_ga_validation(sga:&mut SimpleGeneticAlgorithm<TestSolution>)
    {
        sga.initialize();
        assert_eq!(sga.step(), 1);
        assert_eq!(sga.done(), false);
        assert_eq!(sga.population().size(), 1);
        assert_eq!(sga.population().best().score(), VAL);
    }

////////////////////////////////////////
// Tests

    #[test]
    fn init_test_with_initial_population()
    {
        ga_test_setup("init_test_with_initial_population");
        let initial_population = GAPopulation::new(vec![TestSolution { fitness: VAL}], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : [1; 4],
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(initial_population)
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    fn init_test_with_factory()
    {
        ga_test_setup("init_test_with_factory");
        let mut factory = TestFactory { starting_fitness: VAL };
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : [1; 4],
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 Some(&mut factory as &mut GAFactory<TestSolution>),
                                                 None
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    #[should_panic]
    #[allow(unused_variables)]
    fn init_test_missing_args()
    {
        ga_test_setup("init_test_missing_args");
        let ga : SimpleGeneticAlgorithm<TestSolution> =
                 SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                               d_seed : [1; 4],
                                               flags : DEBUG_FLAG,
                                               max_generations: 100,
                                               ..Default::default()
                                             },
                                             None,
                                             None
                                             );
        // Not reached
    }

    #[test]
    #[should_panic]
    fn init_test_empty_initial_pop()
    {
        ga_test_setup("init_test_empty_initial_pop");
        let empty_initial_population : GAPopulation<TestSolution> = GAPopulation::new(vec![], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : [1; 4],
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(empty_initial_population)
                                                 );
        ga.initialize()
        //Not reached
    }

    // This test should live in the ga_population file directly,
    // but since it requires GASolution objects it is here for now.
    // Maybe we could use a Mocking library.
    // TODO: This doesn't go here.
    #[test]
    fn test_sort_population()
    {
        ga_test_setup("test_sort_population");
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population = GAPopulation::new(vec![TestSolution { fitness: f }, TestSolution { fitness: f_m }], GAPopulationSortOrder::HighIsBest);
        population.sort();

        //TestSolution's Fitness is the inverse of the Score (F = 1/S)
        assert_eq!(population.individual(0, GAPopulationSortBasis::Raw).score(), f);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Raw).score(), f_m);
        assert_eq!(population.individual(0, GAPopulationSortBasis::Scaled).fitness(), i_f_m);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Scaled).fitness(), i_f);
    }

    #[test]
    #[allow(unused_variables)]
    fn test_rank_selector()
    {
        ga_test_setup("test_rank_selector");
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population
          = GAPopulation::new(vec![TestSolution { fitness: f },
                                   TestSolution { fitness: f_m }],
                              GAPopulationSortOrder::HighIsBest);

        {
            let raw_score_selection = GARawScoreBasedSelection;
            let mut raw_rank_selector = GARankSelector::new(&raw_score_selection);

            raw_rank_selector.update(&mut population);

            // Best Raw score is that of 1st solution.
            assert_eq!(raw_rank_selector.select(&population, &mut GARandomCtx::new_unseeded(String::from("test_rank_selector_rng"))).score(), f);
        }

        {
            let scaled_score_selection = GAScaledScoreBasedSelection;
            let mut scaled_rank_selector = GARankSelector::new(&scaled_score_selection);

            scaled_rank_selector.update(&mut population);

            // Best Scaled score is that of 2nd solution (because fitness is inverse of score). Weird. In this case, LowIsBest.
            assert_eq!(scaled_rank_selector.select(&population, &mut GARandomCtx::new_unseeded(String::from("test_rank_selector_rng"))).fitness(), i_f_m);
        }
    }

    #[test]
    fn test_uniform_selector()
    {
        ga_test_setup("test_uniform_selector");
        let f = VAL;
        let f_m = VAL - 1.0;

        let mut population
          = GAPopulation::new(vec![TestSolution { fitness: f },
                                   TestSolution { fitness: f_m }],
                              GAPopulationSortOrder::HighIsBest);

        let mut uniform_selector = GAUniformSelector::new();

        uniform_selector.update(&mut population);

        let selected_individual = uniform_selector.select(&population, &mut GARandomCtx::new_unseeded(String::from("test_rank_selector_rng")));
        assert!(selected_individual.score() == f || selected_individual.score() == f_m);
    }

    #[test]
    #[allow(unused_variables)]
    fn test_roulette_wheel_selector()
    {
        ga_test_setup("test_roulette_wheel_selector");
        // Just exercise the code.
        // TODO: How to test when there is randomness?

        let mut individuals = vec![];
        let mut rng_ctx = GARandomCtx::new_unseeded(String::from("test_roulette_wheel_selector_rng"));

        for i in 1 .. 20
        {
            individuals.push(TestSolution { fitness: rng_ctx.gen::<f32>() });
        }

        let mut population
          = GAPopulation::new(individuals, GAPopulationSortOrder::LowIsBest);

        {
            let raw_score_selection = GARawScoreBasedSelection;

            let mut raw_roulette_wheel_selector
              = GARouletteWheelSelector::new(&raw_score_selection, population.size());

            raw_roulette_wheel_selector.update(&mut population);

            raw_roulette_wheel_selector.select(&population, &mut rng_ctx);
        }

        {
            let scaled_score_selection = GAScaledScoreBasedSelection;

            let mut scaled_roulette_wheel_selector
              = GARouletteWheelSelector::new(&scaled_score_selection, population.size());

            scaled_roulette_wheel_selector.update(&mut population);

            scaled_roulette_wheel_selector.select(&population, &mut rng_ctx);
        }
    }

    #[test]
    #[allow(unused_variables)]
    fn test_tournament_selector()
    {
        // Just exercise the code.
        // TODO: How to test when there is randomness?

        ga_test_setup("test_tournament_selector");
        let mut individuals = vec![];
        let mut rng_ctx = GARandomCtx::new_unseeded(String::from("test_tournament_selector_rng"));

        for i in 1 .. 20
        {
            individuals.push(TestSolution { fitness: rng_ctx.gen::<f32>() });
        }

        let mut population
          = GAPopulation::new(individuals, GAPopulationSortOrder::LowIsBest);

        {
            let raw_score_selection = GARawScoreBasedSelection;

            let mut raw_tournament_selector
              = GARouletteWheelSelector::new(&raw_score_selection, population.size());

            raw_tournament_selector.update(&mut population);

            raw_tournament_selector.select(&population, &mut rng_ctx);
        }

        {
            let scaled_score_selection = GAScaledScoreBasedSelection;

            let mut scaled_tournament_selector
              = GARouletteWheelSelector::new(&scaled_score_selection, population.size());

            scaled_tournament_selector.update(&mut population);

            scaled_tournament_selector.select(&population, &mut rng_ctx);
        }
    }

}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_variables)]

extern crate rebind;
extern crate input;

use rebind::{Action, ButtonTuple, InputTranslator, RebindBuilder, InputRebind, Translated};
use input::Input;
use input::Button::Keyboard;
use input::keyboard::Key;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
enum TestAction {
    Action1, Action2, Action3, Action4, Action5,
    Action6, Action7, Action8, Action9, Action10
}

impl Action for TestAction { }

type TestBuilder = RebindBuilder<TestAction>;
type TestTranslator = InputTranslator<TestAction>;
type TestRebind = InputRebind<TestAction>;

fn create_prepopulated_builder() -> TestBuilder {
    RebindBuilder::default()
        .with_action_mapping(Keyboard(Key::Up),    TestAction::Action1)
        .with_action_mapping(Keyboard(Key::W),     TestAction::Action1)
        .with_action_mapping(Keyboard(Key::Down),  TestAction::Action2)
        .with_action_mapping(Keyboard(Key::S),     TestAction::Action2)
        .with_action_mapping(Keyboard(Key::Left),  TestAction::Action3)
        .with_action_mapping(Keyboard(Key::A),     TestAction::Action3)
        .with_action_mapping(Keyboard(Key::Right), TestAction::Action4)
        .with_action_mapping(Keyboard(Key::D),     TestAction::Action4)
}

#[test]
fn test_translator_get_action_from_buttonpress() {
    let translator = create_prepopulated_builder().build_translator();

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::Down))).unwrap(),
               Translated::Press(TestAction::Action2));

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::D))).unwrap(),
               Translated::Press(TestAction::Action4));

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::Left))).unwrap(),
               Translated::Press(TestAction::Action3));

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::W))).unwrap(),
               Translated::Press(TestAction::Action1));
}

#[test]
fn test_conversion_from_rebind_to_translator() {
    let translator = create_prepopulated_builder().build_translator();

    let translator_clone = translator.clone();
    let converted_translator = Into::<TestTranslator>::into(
            Into::<TestRebind>::into(translator));

    assert_eq!(translator_clone, converted_translator);
}

#[test]
fn test_add_button_to_translator_using_rebind() {
    use input::Button;
    const Q_KEY: Button = Keyboard(Key::Q);
    const E_KEY: Button = Keyboard(Key::E);

    let translator = create_prepopulated_builder().build_translator();
    let mut rebind = translator.into_rebind();
    rebind.insert_action_with_buttons(TestAction::Action5, ButtonTuple(Some(Q_KEY), Some(E_KEY), None));

    let translator = rebind.into_translator();

    assert_eq!(translator.translate(&Input::Press(Q_KEY)), Some(Translated::Press(TestAction::Action5)));
    assert_eq!(translator.translate(&Input::Press(E_KEY)), Some(Translated::Press(TestAction::Action5)));
}

#[test]
fn test_get_button_iter_len() {
    let bt = ButtonTuple(Some(Keyboard(Key::B)), None, None);
    let mut bti = bt.iter();
    assert_eq!(bti.len(), 3);
    let _ = bti.next();
    assert_eq!(bti.len(), 2);
    let _ = bti.next();
    assert_eq!(bti.len(), 1);
    let _ = bti.next();
    assert_eq!(bti.len(), 0);
    let _ = bti.next();
    assert_eq!(bti.len(), 0);
}<commit_msg>Add test to check whether `ButtonTuple::num_buttons_set` works correctly<commit_after>#![allow(dead_code, unused_variables)]

extern crate rebind;
extern crate input;

use rebind::{Action, ButtonTuple, InputTranslator, RebindBuilder, InputRebind, Translated};
use input::Input;
use input::Button::Keyboard;
use input::keyboard::Key;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
enum TestAction {
    Action1, Action2, Action3, Action4, Action5,
    Action6, Action7, Action8, Action9, Action10
}

impl Action for TestAction { }

type TestBuilder = RebindBuilder<TestAction>;
type TestTranslator = InputTranslator<TestAction>;
type TestRebind = InputRebind<TestAction>;

fn create_prepopulated_builder() -> TestBuilder {
    RebindBuilder::default()
        .with_action_mapping(Keyboard(Key::Up),    TestAction::Action1)
        .with_action_mapping(Keyboard(Key::W),     TestAction::Action1)
        .with_action_mapping(Keyboard(Key::Down),  TestAction::Action2)
        .with_action_mapping(Keyboard(Key::S),     TestAction::Action2)
        .with_action_mapping(Keyboard(Key::Left),  TestAction::Action3)
        .with_action_mapping(Keyboard(Key::A),     TestAction::Action3)
        .with_action_mapping(Keyboard(Key::Right), TestAction::Action4)
        .with_action_mapping(Keyboard(Key::D),     TestAction::Action4)
}

#[test]
fn test_translator_get_action_from_buttonpress() {
    let translator = create_prepopulated_builder().build_translator();

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::Down))).unwrap(),
               Translated::Press(TestAction::Action2));

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::D))).unwrap(),
               Translated::Press(TestAction::Action4));

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::Left))).unwrap(),
               Translated::Press(TestAction::Action3));

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::W))).unwrap(),
               Translated::Press(TestAction::Action1));
}

#[test]
fn test_conversion_from_rebind_to_translator() {
    let translator = create_prepopulated_builder().build_translator();

    let translator_clone = translator.clone();
    let converted_translator = Into::<TestTranslator>::into(
            Into::<TestRebind>::into(translator));

    assert_eq!(translator_clone, converted_translator);
}

#[test]
fn test_add_button_to_translator_using_rebind() {
    use input::Button;
    const Q_KEY: Button = Keyboard(Key::Q);
    const E_KEY: Button = Keyboard(Key::E);

    let translator = create_prepopulated_builder().build_translator();
    let mut rebind = translator.into_rebind();
    rebind.insert_action_with_buttons(TestAction::Action5, ButtonTuple(Some(Q_KEY), Some(E_KEY), None));

    let translator = rebind.into_translator();

    assert_eq!(translator.translate(&Input::Press(Q_KEY)), Some(Translated::Press(TestAction::Action5)));
    assert_eq!(translator.translate(&Input::Press(E_KEY)), Some(Translated::Press(TestAction::Action5)));
}

#[test]
fn test_get_num_buttons_set() {
    let mut bt = ButtonTuple::new();
    assert_eq!(bt.num_buttons_set(), 0);

    bt.0 = Some(Keyboard(Key::Z));
    assert_eq!(bt.num_buttons_set(), 1);

    bt.1 = Some(Keyboard(Key::Q));
    assert_eq!(bt.num_buttons_set(), 2);

    bt.2 = Some(Keyboard(Key::D0));
    assert_eq!(bt.num_buttons_set(), 3);
}

#[test]
fn test_get_button_iter_len() {
    let bt = ButtonTuple(Some(Keyboard(Key::B)), None, None);
    let mut bti = bt.iter();
    assert_eq!(bti.len(), 3);
    let _ = bti.next();
    assert_eq!(bti.len(), 2);
    let _ = bti.next();
    assert_eq!(bti.len(), 1);
    let _ = bti.next();
    assert_eq!(bti.len(), 0);
    let _ = bti.next();
    assert_eq!(bti.len(), 0);
}<|endoftext|>