<commit_before>use crate::common::util::*;
use rust_users::*;
use std::os::unix::fs::PermissionsExt;

#[test]
fn test_install_help() {
    let (_, mut ucmd) = at_and_ucmd!();

    assert!(ucmd
        .arg("--help")
        .succeeds()
        .no_stderr()
        .stdout
        .contains("FLAGS:"));
}

#[test]
fn test_install_basic() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_install_target_dir_dir_a";
    let file1 = "test_install_target_dir_file_a1";
    let file2 = "test_install_target_dir_file_a2";

    at.touch(file1);
    at.touch(file2);
    at.mkdir(dir);
    ucmd.arg(file1).arg(file2).arg(dir).succeeds().no_stderr();

    assert!(at.file_exists(file1));
    assert!(at.file_exists(file2));
    assert!(at.file_exists(&format!("{}/{}", dir, file1)));
    assert!(at.file_exists(&format!("{}/{}", dir, file2)));
}

#[test]
fn test_install_twice_dir() {
    let dir = "test_install_target_dir_dir_a";
    let scene = TestScenario::new(util_name!());

    scene.ucmd().arg("-d").arg(dir).succeeds();
    scene.ucmd().arg("-d").arg(dir).succeeds();
    let at = &scene.fixtures;

    assert!(at.dir_exists(dir));
}

#[test]
fn test_install_failing_not_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "test_install_target_dir_file_a1";
    let file2 = "test_install_target_dir_file_a2";
    let file3 = "test_install_target_dir_file_a3";

    at.touch(file1);
    at.touch(file2);
    at.touch(file3);
    assert!(ucmd
        .arg(file1)
        .arg(file2)
        .arg(file3)
        .fails()
        .stderr
        .contains("not a directory"));
}

#[test]
fn test_install_unimplemented_arg() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_install_target_dir_dir_b";
    let file = "test_install_target_dir_file_b";
    let context_arg = "--context";

    at.touch(file);
    at.mkdir(dir);
    assert!(ucmd
        .arg(context_arg)
        .arg(file)
        .arg(dir)
        .fails()
        .stderr
        .contains("Unimplemented"));

    assert!(!at.file_exists(&format!("{}/{}", dir, file)));
}

#[test]
fn test_install_component_directories() {
    let (at, mut ucmd) = at_and_ucmd!();
    let component1 = "test_install_target_dir_component_c1";
    let component2 = "test_install_target_dir_component_c2";
    let component3 = "test_install_target_dir_component_c3";
    let directories_arg = "-d";

    ucmd.args(&[directories_arg, component1, component2, component3])
        .succeeds()
        .no_stderr();

    assert!(at.dir_exists(component1));
    assert!(at.dir_exists(component2));
    assert!(at.dir_exists(component3));
}

#[test]
fn test_install_mode_numeric() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    let dir = "test_install_target_dir_dir_e";
    let dir2 = "test_install_target_dir_dir_e2";

    let file = "test_install_target_dir_file_e";
    let mode_arg = "--mode=333";

    at.touch(file);
    at.mkdir(dir);
    scene
        .ucmd()
        .arg(file)
        .arg(dir)
        .arg(mode_arg)
        .succeeds()
        .no_stderr();

    let dest_file = &format!("{}/{}", dir, file);
    assert!(at.file_exists(file));
    assert!(at.file_exists(dest_file));
    let permissions = at.metadata(dest_file).permissions();
    assert_eq!(0o100333 as u32, PermissionsExt::mode(&permissions));

    let mode_arg = "-m 0333";
    at.mkdir(dir2);

    let result = scene.ucmd().arg(mode_arg).arg(file).arg(dir2).run();

    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);

    assert!(result.success);
    let dest_file = &format!("{}/{}", dir2, file);
    assert!(at.file_exists(file));
    assert!(at.file_exists(dest_file));
    let permissions = at.metadata(dest_file).permissions();
    assert_eq!(0o100333 as u32, PermissionsExt::mode(&permissions));
}

#[test]
fn test_install_mode_symbolic() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_install_target_dir_dir_f";
    let file = "test_install_target_dir_file_f";
    let mode_arg = "--mode=o+wx";

    at.touch(file);
    at.mkdir(dir);
    ucmd.arg(file).arg(dir).arg(mode_arg).succeeds().no_stderr();

    let dest_file = &format!("{}/{}", dir, file);
    assert!(at.file_exists(file));
    assert!(at.file_exists(dest_file));
    let permissions = at.metadata(dest_file).permissions();
    assert_eq!(0o100003 as u32, PermissionsExt::mode(&permissions));
}

#[test]
fn test_install_mode_failing() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_install_target_dir_dir_g";
    let file = "test_install_target_dir_file_g";
    let mode_arg = "--mode=999";

    at.touch(file);
    at.mkdir(dir);
    assert!(ucmd
        .arg(file)
        .arg(dir)
        .arg(mode_arg)
        .fails()
        .stderr
        .contains("Invalid mode string: invalid digit found in string"));

    let dest_file = &format!("{}/{}", dir, file);
    assert!(at.file_exists(file));
    assert!(!at.file_exists(dest_file));
}

#[test]
fn test_install_mode_directories() {
    let (at, mut ucmd) = at_and_ucmd!();
    let component = "test_install_target_dir_component_h";
    let directories_arg = "-d";
    let mode_arg = "--mode=333";

    ucmd.arg(directories_arg)
        .arg(component)
        .arg(mode_arg)
        .succeeds()
        .no_stderr();

    assert!(at.dir_exists(component));
    let permissions = at.metadata(component).permissions();
    assert_eq!(0o040333 as u32, PermissionsExt::mode(&permissions));
}

#[test]
fn test_install_target_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "test_install_target_file_file_i1";
    let file2 = "test_install_target_file_file_i2";

    at.touch(file1);
    at.touch(file2);
    ucmd.arg(file1).arg(file2).succeeds().no_stderr();

    assert!(at.file_exists(file1));
    assert!(at.file_exists(file2));
}

#[test]
fn test_install_target_new_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_install_target_new_filer_file_j";
    let dir = "test_install_target_new_file_dir_j";

    at.touch(file);
    at.mkdir(dir);
    ucmd.arg(file)
        .arg(format!("{}/{}", dir, file))
        .succeeds()
        .no_stderr();

    assert!(at.file_exists(file));
    assert!(at.file_exists(&format!("{}/{}", dir, file)));
}

#[test]
fn test_install_target_new_file_with_group() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_install_target_new_filer_file_j";
    let dir = "test_install_target_new_file_dir_j";
    let gid = get_effective_gid();

    at.touch(file);
    at.mkdir(dir);
    let result = ucmd
        .arg(file)
        .arg("--group")
        .arg(gid.to_string())
        .arg(format!("{}/{}", dir, file))
        .run();

    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);

    if is_ci() && result.stderr.contains("error: no such group:") {
        // In the CI, some server are failing to return the group.
        // As seems to be a configuration issue, ignoring it
        return;
    }

    assert!(result.success);
    assert!(at.file_exists(file));
    assert!(at.file_exists(&format!("{}/{}", dir, file)));
}

#[test]
fn test_install_target_new_file_with_owner() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_install_target_new_filer_file_j";
    let dir = "test_install_target_new_file_dir_j";
    let uid = get_effective_uid();

    at.touch(file);
    at.mkdir(dir);
    let result = ucmd
        .arg(file)
        .arg("--owner")
        .arg(uid.to_string())
        .arg(format!("{}/{}", dir, file))
        .run();

    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);

    if is_ci() && result.stderr.contains("error: no such user:") {
        // In the CI, some server are failing to return the user id.
        // As seems to be a configuration issue, ignoring it
        return;
    }

    assert!(result.success);
    assert!(at.file_exists(file));
    assert!(at.file_exists(&format!("{}/{}", dir, file)));
}

#[test]
fn test_install_target_new_file_failing_nonexistent_parent() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "test_install_target_new_file_failing_file_k1";
    let file2 = "test_install_target_new_file_failing_file_k2";
    let dir = "test_install_target_new_file_failing_dir_k";

    at.touch(file1);

    let err = ucmd
        .arg(file1)
        .arg(format!("{}/{}", dir, file2))
        .fails()
        .stderr;

    assert!(err.contains("not a directory"))
}

#[test]
fn test_install_preserve_timestamps() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "test_install_target_dir_file_a1";
    let file2 = "test_install_target_dir_file_a2";
    at.touch(file1);

    ucmd.arg(file1).arg(file2).arg("-p").succeeds().no_stderr();

    assert!(at.file_exists(file1));
    assert!(at.file_exists(file2));

    let file1_metadata = at.metadata(file1);
    let file2_metadata = at.metadata(file2);

    assert_eq!(
        file1_metadata.accessed().ok(),
        file2_metadata.accessed().ok()
    );
    assert_eq!(
        file1_metadata.modified().ok(),
        file2_metadata.modified().ok()
    );
}

// These two tests are failing but should work
#[test]
fn test_install_copy_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "test_install_target_dir_file_a1";
    let file2 = "test_install_target_dir_file_a2";

    at.touch(file1);
    ucmd.arg(file1).arg(file2).succeeds().no_stderr();

    assert!(at.file_exists(file1));
    assert!(at.file_exists(file2));
}

#[test]
#[cfg(target_os = "linux")]
fn test_install_target_file_dev_null() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "/dev/null";
    let file2 = "test_install_target_file_file_i2";

    ucmd.arg(file1).arg(file2).succeeds().no_stderr();
    assert!(at.file_exists(file2));
}

#[test]
fn test_install_copy_file_leading_dot() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir1 = "test_install_target_new_file_dir_l";
    let dir2 = "test_install_target_new_file_dir_m";
    let file1 = "test_install_target_file_file_l1";

    at.mkdir(dir1);
    at.mkdir(dir2);
    at.touch(&format!("{}/{}", dir1, file1));

    ucmd.arg(format!("{}/{}", dir1, file1))
        .arg(dir2)
        .succeeds()
        .no_stderr();
    assert!(at.file_exists(&format!("{}/{}", dir2, file1)));
}
<commit_msg>install: added additional tests<commit_after>use crate::common::util::*;
use rust_users::*;
use std::os::unix::fs::PermissionsExt;

#[test]
fn test_install_help() {
    let (_, mut ucmd) = at_and_ucmd!();

    assert!(ucmd
        .arg("--help")
        .succeeds()
        .no_stderr()
        .stdout
        .contains("FLAGS:"));
}

#[test]
fn test_install_basic() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_install_target_dir_dir_a";
    let file1 = "test_install_target_dir_file_a1";
    let file2 = "test_install_target_dir_file_a2";

    at.touch(file1);
    at.touch(file2);
    at.mkdir(dir);
    ucmd.arg(file1).arg(file2).arg(dir).succeeds().no_stderr();

    assert!(at.file_exists(file1));
    assert!(at.file_exists(file2));
    assert!(at.file_exists(&format!("{}/{}", dir, file1)));
    assert!(at.file_exists(&format!("{}/{}", dir, file2)));
}

#[test]
fn test_install_twice_dir() {
    let dir = "test_install_target_dir_dir_a";
    let scene = TestScenario::new(util_name!());

    scene.ucmd().arg("-d").arg(dir).succeeds();
    scene.ucmd().arg("-d").arg(dir).succeeds();
    let at = &scene.fixtures;

    assert!(at.dir_exists(dir));
}

#[test]
fn test_install_failing_not_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "test_install_target_dir_file_a1";
    let file2 = "test_install_target_dir_file_a2";
    let file3 = "test_install_target_dir_file_a3";

    at.touch(file1);
    at.touch(file2);
    at.touch(file3);
    assert!(ucmd
        .arg(file1)
        .arg(file2)
        .arg(file3)
        .fails()
        .stderr
        .contains("not a directory"));
}

#[test]
fn test_install_unimplemented_arg() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_install_target_dir_dir_b";
    let file = "test_install_target_dir_file_b";
    let context_arg = "--context";

    at.touch(file);
    at.mkdir(dir);
    assert!(ucmd
        .arg(context_arg)
        .arg(file)
        .arg(dir)
        .fails()
        .stderr
        .contains("Unimplemented"));

    assert!(!at.file_exists(&format!("{}/{}", dir, file)));
}

#[test]
fn test_install_component_directories() {
    let (at, mut ucmd) = at_and_ucmd!();
    let component1 = "test_install_target_dir_component_c1";
    let component2 = "test_install_target_dir_component_c2";
    let component3 = "test_install_target_dir_component_c3";
    let directories_arg = "-d";

    ucmd.args(&[directories_arg, component1, component2, component3])
        .succeeds()
        .no_stderr();

    assert!(at.dir_exists(component1));
    assert!(at.dir_exists(component2));
    assert!(at.dir_exists(component3));
}

#[test]
fn test_install_mode_numeric() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    let dir = "test_install_target_dir_dir_e";
    let dir2 = "test_install_target_dir_dir_e2";

    let file = "test_install_target_dir_file_e";
    let mode_arg = "--mode=333";

    at.touch(file);
    at.mkdir(dir);
    scene
        .ucmd()
        .arg(file)
        .arg(dir)
        .arg(mode_arg)
        .succeeds()
        .no_stderr();

    let dest_file = &format!("{}/{}", dir, file);
    assert!(at.file_exists(file));
    assert!(at.file_exists(dest_file));
    let permissions = at.metadata(dest_file).permissions();
    assert_eq!(0o100333 as u32, PermissionsExt::mode(&permissions));

    let mode_arg = "-m 0333";
    at.mkdir(dir2);

    let result = scene.ucmd().arg(mode_arg).arg(file).arg(dir2).run();

    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);

    assert!(result.success);
    let dest_file = &format!("{}/{}", dir2, file);
    assert!(at.file_exists(file));
    assert!(at.file_exists(dest_file));
    let permissions = at.metadata(dest_file).permissions();
    assert_eq!(0o100333 as u32, PermissionsExt::mode(&permissions));
}

#[test]
fn test_install_mode_symbolic() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_install_target_dir_dir_f";
    let file = "test_install_target_dir_file_f";
    let mode_arg = "--mode=o+wx";

    at.touch(file);
    at.mkdir(dir);
    ucmd.arg(file).arg(dir).arg(mode_arg).succeeds().no_stderr();

    let dest_file = &format!("{}/{}", dir, file);
    assert!(at.file_exists(file));
    assert!(at.file_exists(dest_file));
    let permissions = at.metadata(dest_file).permissions();
    assert_eq!(0o100003 as u32, PermissionsExt::mode(&permissions));
}

#[test]
fn test_install_mode_failing() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_install_target_dir_dir_g";
    let file = "test_install_target_dir_file_g";
    let mode_arg = "--mode=999";

    at.touch(file);
    at.mkdir(dir);
    assert!(ucmd
        .arg(file)
        .arg(dir)
        .arg(mode_arg)
        .fails()
        .stderr
        .contains("Invalid mode string: invalid digit found in string"));

    let dest_file = &format!("{}/{}", dir, file);
    assert!(at.file_exists(file));
    assert!(!at.file_exists(dest_file));
}

#[test]
fn test_install_mode_directories() {
    let (at, mut ucmd) = at_and_ucmd!();
    let component = "test_install_target_dir_component_h";
    let directories_arg = "-d";
    let mode_arg = "--mode=333";

    ucmd.arg(directories_arg)
        .arg(component)
        .arg(mode_arg)
        .succeeds()
        .no_stderr();

    assert!(at.dir_exists(component));
    let permissions = at.metadata(component).permissions();
    assert_eq!(0o040333 as u32, PermissionsExt::mode(&permissions));
}

#[test]
fn test_install_target_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "test_install_target_file_file_i1";
    let file2 = "test_install_target_file_file_i2";

    at.touch(file1);
    at.touch(file2);
    ucmd.arg(file1).arg(file2).succeeds().no_stderr();

    assert!(at.file_exists(file1));
    assert!(at.file_exists(file2));
}

#[test]
fn test_install_target_new_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_install_target_new_filer_file_j";
    let dir = "test_install_target_new_file_dir_j";

    at.touch(file);
    at.mkdir(dir);
    ucmd.arg(file)
        .arg(format!("{}/{}", dir, file))
        .succeeds()
        .no_stderr();

    assert!(at.file_exists(file));
    assert!(at.file_exists(&format!("{}/{}", dir, file)));
}

#[test]
fn test_install_target_new_file_with_group() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_install_target_new_filer_file_j";
    let dir = "test_install_target_new_file_dir_j";
    let gid = get_effective_gid();

    at.touch(file);
    at.mkdir(dir);
    let result = ucmd
        .arg(file)
        .arg("--group")
        .arg(gid.to_string())
        .arg(format!("{}/{}", dir, file))
        .run();

    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);

    if is_ci() && result.stderr.contains("error: no such group:") {
        // In the CI, some server are failing to return the group.
        // As seems to be a configuration issue, ignoring it
        return;
    }

    assert!(result.success);
    assert!(at.file_exists(file));
    assert!(at.file_exists(&format!("{}/{}", dir, file)));
}

#[test]
fn test_install_target_new_file_with_owner() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_install_target_new_filer_file_j";
    let dir = "test_install_target_new_file_dir_j";
    let uid = get_effective_uid();

    at.touch(file);
    at.mkdir(dir);
    let result = ucmd
        .arg(file)
        .arg("--owner")
        .arg(uid.to_string())
        .arg(format!("{}/{}", dir, file))
        .run();

    println!("stderr = {:?}", result.stderr);
    println!("stdout = {:?}", result.stdout);

    if is_ci() && result.stderr.contains("error: no such user:") {
        // In the CI, some server are failing to return the user id.
        // As seems to be a configuration issue, ignoring it
        return;
    }

    assert!(result.success);
    assert!(at.file_exists(file));
    assert!(at.file_exists(&format!("{}/{}", dir, file)));
}

#[test]
fn test_install_target_new_file_failing_nonexistent_parent() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "test_install_target_new_file_failing_file_k1";
    let file2 = "test_install_target_new_file_failing_file_k2";
    let dir = "test_install_target_new_file_failing_dir_k";

    at.touch(file1);

    let err = ucmd
        .arg(file1)
        .arg(format!("{}/{}", dir, file2))
        .fails()
        .stderr;

    assert!(err.contains("not a directory"))
}

#[test]
fn test_install_preserve_timestamps() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "test_install_target_dir_file_a1";
    let file2 = "test_install_target_dir_file_a2";
    at.touch(file1);

    ucmd.arg(file1).arg(file2).arg("-p").succeeds().no_stderr();

    assert!(at.file_exists(file1));
    assert!(at.file_exists(file2));

    let file1_metadata = at.metadata(file1);
    let file2_metadata = at.metadata(file2);

    assert_eq!(
        file1_metadata.accessed().ok(),
        file2_metadata.accessed().ok()
    );
    assert_eq!(
        file1_metadata.modified().ok(),
        file2_metadata.modified().ok()
    );
}

// These two tests are failing but should work
#[test]
fn test_install_copy_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "test_install_target_dir_file_a1";
    let file2 = "test_install_target_dir_file_a2";

    at.touch(file1);
    ucmd.arg(file1).arg(file2).succeeds().no_stderr();

    assert!(at.file_exists(file1));
    assert!(at.file_exists(file2));
}

#[test]
#[cfg(target_os = "linux")]
fn test_install_target_file_dev_null() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "/dev/null";
    let file2 = "test_install_target_file_file_i2";

    ucmd.arg(file1).arg(file2).succeeds().no_stderr();
    assert!(at.file_exists(file2));
}

#[test]
fn test_install_nested_paths_copy_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir1 = "test_install_target_new_file_dir_l";
    let dir2 = "test_install_target_new_file_dir_m";
    let file1 = "test_install_target_file_file_l1";

    at.mkdir(dir1);
    at.mkdir(dir2);
    at.touch(&format!("{}/{}", dir1, file1));

    ucmd.arg(format!("{}/{}", dir1, file1))
        .arg(dir2)
        .succeeds()
        .no_stderr();
    assert!(at.file_exists(&format!("{}/{}", dir2, file1)));
}

#[test]
fn test_install_failing_omitting_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir1 = "source_dir";
    let file1 = "source_file";
    let dir2 = "target_dir";

    at.mkdir(dir1);
    at.mkdir(dir2);
    at.touch(file1);

    let r = ucmd.arg(dir1).arg(file1).arg(dir2).run();
    assert!(r.code == Some(1));
    assert!(r.stderr.contains("omitting directory"));
}

#[test]
fn test_install_failing_no_such_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file1 = "source_file";
    let file2 = "inexistent_file";
    let dir1 = "target_dir";

    at.mkdir(dir1);
    at.touch(file1);

    let r = ucmd.arg(file1).arg(file2).arg(dir1).run();
    assert!(r.code == Some(1));
    assert!(r.stderr.contains("No such file or directory"));
}
<|endoftext|>


<commit_before>extern crate curl;
extern crate flate2;
extern crate pkg_config;
extern crate semver;
extern crate tar;

use std::error::Error;
use std::fs::File;
use std::io::BufWriter;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process;
use std::process::Command;
use std::{env, fs};

use curl::easy::Easy;
use flate2::read::GzDecoder;
use semver::Version;
use tar::Archive;

const FRAMEWORK_LIBRARY: &'static str = "tensorflow_framework";
const LIBRARY: &'static str = "tensorflow";
const REPOSITORY: &'static str = "https://github.com/tensorflow/tensorflow.git";
const FRAMEWORK_TARGET: &'static str = "tensorflow:libtensorflow_framework.so";
const TARGET: &'static str = "tensorflow:libtensorflow.so";
// `VERSION` and `TAG` are separate because the tag is not always `'v' + VERSION`.
const VERSION: &'static str = "1.13.1";
const TAG: &'static str = "v1.13.1";
const MIN_BAZEL: &'static str = "0.5.4";

macro_rules! get(($name:expr) => (ok!(env::var($name))));
macro_rules! ok(($expression:expr) => ($expression.unwrap()));
macro_rules! log {
    ($fmt:expr) => (println!(concat!("libtensorflow-sys/build.rs:{}: ", $fmt), line!()));
    ($fmt:expr, $($arg:tt)*) => (println!(concat!("libtensorflow-sys/build.rs:{}: ", $fmt),
    line!(), $($arg)*));
}
macro_rules! log_var(($var:ident) => (log!(concat!(stringify!($var), " = {:?}"), $var)));

fn main() {
    if check_windows_lib() {
        log!("Returning early because {} was already found", LIBRARY);
        return;
    }

    if pkg_config::find_library(LIBRARY).is_ok() {
        log!("Returning early because {} was already found", LIBRARY);
        return;
    }

    let force_src = match env::var("TF_RUST_BUILD_FROM_SRC") {
        Ok(s) => s == "true",
        Err(_) => false,
    };

    if !force_src
        && env::consts::ARCH == "x86_64"
        && (env::consts::OS == "linux" || env::consts::OS == "macos")
    {
        install_prebuilt();
    } else {
        build_from_src();
    }
}

#[cfg(not(target_env = "msvc"))]
fn check_windows_lib() -> bool {
    false
}

#[cfg(target_env = "msvc")]
fn check_windows_lib() -> bool {
    let windows_lib: &str = &format!("{}.lib", LIBRARY);
    if let Ok(path) = env::var("PATH") {
        for p in path.split(";") {
            let path = Path::new(p).join(windows_lib);
            if path.exists() {
                println!("cargo:rustc-link-lib=dylib={}", LIBRARY);
                println!("cargo:rustc-link-search=native={}", p);
                return true;
            }
        }
    }
    false
}

fn remove_suffix(value: &mut String, suffix: &str) {
    if value.ends_with(suffix) {
        let n = value.len();
        value.truncate(n - suffix.len());
    }
}

fn extract<P: AsRef<Path>, P2: AsRef<Path>>(archive_path: P, extract_to: P2) {
    let file = File::open(archive_path).unwrap();
    let unzipped = GzDecoder::new(file);
    let mut a = Archive::new(unzipped);
    a.unpack(extract_to).unwrap();
}

// Downloads and unpacks a prebuilt binary. Only works for certain platforms.
fn install_prebuilt() {
    // Figure out the file names.
    let os = match env::consts::OS {
        "macos" => "darwin",
        x => x,
    };
    let proc_type = if cfg!(feature = "tensorflow_gpu") {
        "gpu"
    } else {
        "cpu"
    };
    let binary_url =
        format!(
        "https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-{}-{}-{}-{}.tar.gz",
        proc_type, os, env::consts::ARCH, VERSION);
    log_var!(binary_url);
    let short_file_name = binary_url.split("/").last().unwrap();
    let mut base_name = short_file_name.to_string();
    remove_suffix(&mut base_name, ".tar.gz");
    log_var!(base_name);
    let download_dir = match env::var("TF_RUST_DOWNLOAD_DIR") {
        Ok(s) => PathBuf::from(s),
        Err(_) => PathBuf::from(&get!("CARGO_MANIFEST_DIR")).join("target"),
    };
    if !download_dir.exists() {
        fs::create_dir(&download_dir).unwrap();
    }
    let file_name = download_dir.join(short_file_name);
    log_var!(file_name);

    // Download the tarball.
    if !file_name.exists() {
        let f = File::create(&file_name).unwrap();
        let mut writer = BufWriter::new(f);
        let mut easy = Easy::new();
        easy.url(&binary_url).unwrap();
        easy.write_function(move |data| Ok(writer.write(data).unwrap()))
            .unwrap();
        easy.perform().unwrap();

        let response_code = easy.response_code().unwrap();
        if response_code != 200 {
            panic!(
                "Unexpected response code {} for {}",
                response_code, binary_url
            );
        }
    }

    // Extract the tarball.
    let unpacked_dir = download_dir.join(base_name);
    let lib_dir = unpacked_dir.join("lib");
    let framework_library_file = format!("lib{}.so", FRAMEWORK_LIBRARY);
    let library_file = format!("lib{}.so", LIBRARY);
    let framework_library_full_path = lib_dir.join(&framework_library_file);
    let library_full_path = lib_dir.join(&library_file);
    if !framework_library_full_path.exists() || !library_full_path.exists() {
        extract(file_name, &unpacked_dir);
    }

    println!("cargo:rustc-link-lib=dylib={}", FRAMEWORK_LIBRARY);
    println!("cargo:rustc-link-lib=dylib={}", LIBRARY);
    let output = PathBuf::from(&get!("OUT_DIR"));
    let new_framework_library_full_path = output.join(&framework_library_file);
    if new_framework_library_full_path.exists() {
        log!(
            "File {} already exists, deleting.",
            new_framework_library_full_path.display()
        );
        std::fs::remove_file(&new_framework_library_full_path).unwrap();
    }
    let new_library_full_path = output.join(&library_file);
    if new_library_full_path.exists() {
        log!(
            "File {} already exists, deleting.",
            new_library_full_path.display()
        );
        std::fs::remove_file(&new_library_full_path).unwrap();
    }

    log!(
        "Copying {} to {}...",
        library_full_path.display(),
        new_library_full_path.display()
    );
    std::fs::copy(&library_full_path, &new_library_full_path).unwrap();
    log!(
        "Copying {} to {}...",
        framework_library_full_path.display(),
        new_framework_library_full_path.display()
    );
    std::fs::copy(
        &framework_library_full_path,
        &new_framework_library_full_path,
    )
    .unwrap();
    println!("cargo:rustc-link-search={}", output.display());
}

fn build_from_src() {
    let output = PathBuf::from(&get!("OUT_DIR"));
    log_var!(output);
    let source = PathBuf::from(&get!("CARGO_MANIFEST_DIR")).join(format!("target/source-{}", TAG));
    log_var!(source);
    let lib_dir = output.join(format!("lib-{}", TAG));
    log_var!(lib_dir);
    if lib_dir.exists() {
        log!("Directory {:?} already exists", lib_dir);
    } else {
        log!("Creating directory {:?}", lib_dir);
        fs::create_dir(lib_dir.clone()).unwrap();
    }
    let framework_library_path = lib_dir.join(format!("lib{}.so", FRAMEWORK_LIBRARY));
    log_var!(framework_library_path);
    let library_path = lib_dir.join(format!("lib{}.so", LIBRARY));
    log_var!(library_path);
    if library_path.exists() && framework_library_path.exists() {
        log!(
            "{:?} and {:?} already exist, not building",
            library_path,
            framework_library_path
        );
    } else {
        if let Err(e) = check_bazel() {
            println!(
                "cargo:error=Bazel must be installed at version {} or greater. (Error: {})",
                MIN_BAZEL, e
            );
            process::exit(1);
        }
        let framework_target_path = &FRAMEWORK_TARGET.replace(":", "/");
        log_var!(framework_target_path);
        let target_path = &TARGET.replace(":", "/");
        log_var!(target_path);
        if !Path::new(&source.join(".git")).exists() {
            run("git", |command| {
                command
                    .arg("clone")
                    .arg(format!("--branch={}", TAG))
                    .arg("--recursive")
                    .arg(REPOSITORY)
                    .arg(&source)
            });
        }
        // Only configure if not previously configured.  Configuring runs a
        // `bazel clean`, which we don't want, because we want to be able to
        // continue from a cancelled build.
        let configure_hint_file_pb = source.join(".rust-configured");
        let configure_hint_file = Path::new(&configure_hint_file_pb);
        if !configure_hint_file.exists() {
            run("bash", |command| {
                command
                    .current_dir(&source)
                    .env(
                        "TF_NEED_CUDA",
                        if cfg!(feature = "tensorflow_gpu") {
                            "1"
                        } else {
                            "0"
                        },
                    )
                    .arg("-c")
                    .arg("yes ''|./configure")
            });
            File::create(configure_hint_file).unwrap();
        }
        // Allows us to pass in --incompatible_load_argument_is_label=false
        // to work around https://github.com/tensorflow/tensorflow/issues/15492
        let bazel_args_string = if let Ok(args) = env::var("TF_RUST_BAZEL_OPTS") {
            args
        } else {
            "".to_string()
        };
        run("bazel", |command| {
            command
                .current_dir(&source)
                .arg("build")
                .arg(format!("--jobs={}", get!("NUM_JOBS")))
                .arg("--compilation_mode=opt")
                .arg("--copt=-march=native")
                .args(bazel_args_string.split_whitespace())
                .arg(TARGET)
        });
        let framework_target_bazel_bin = source.join("bazel-bin").join(framework_target_path);
        log!(
            "Copying {:?} to {:?}",
            framework_target_bazel_bin,
            framework_library_path
        );
        fs::copy(framework_target_bazel_bin, framework_library_path).unwrap();
        let target_bazel_bin = source.join("bazel-bin").join(target_path);
        log!("Copying {:?} to {:?}", target_bazel_bin, library_path);
        fs::copy(target_bazel_bin, library_path).unwrap();
    }

    println!("cargo:rustc-link-lib=dylib={}", FRAMEWORK_LIBRARY);
    println!("cargo:rustc-link-lib=dylib={}", LIBRARY);
    println!("cargo:rustc-link-search={}", lib_dir.display());
}

fn run<F>(name: &str, mut configure: F)
where
    F: FnMut(&mut Command) -> &mut Command,
{
    let mut command = Command::new(name);
    let configured = configure(&mut command);
    log!("Executing {:?}", configured);
    if !ok!(configured.status()).success() {
        panic!("failed to execute {:?}", configured);
    }
    log!("Command {:?} finished successfully", configured);
}

// Building TF 0.11.0rc1 with Bazel 0.3.0 gives this error when running `configure`:
//   expected ConfigurationTransition or NoneType for 'cfg' while calling label_list but got
// string instead:     data.
//       ERROR: com.google.devtools.build.lib.packages.BuildFileContainsErrorsException: error
// loading package '': Extension file 'tensorflow/tensorflow.bzl' has errors.
// And the simple solution is to require Bazel 0.3.1 or higher.
fn check_bazel() -> Result<(), Box<Error>> {
    let mut command = Command::new("bazel");
    command.arg("version");
    log!("Executing {:?}", command);
    let out = command.output()?;
    log!("Command {:?} finished successfully", command);
    let stdout = String::from_utf8(out.stdout)?;
    let mut found_version = false;
    for line in stdout.lines() {
        if line.starts_with("Build label:") {
            found_version = true;
            let mut version_str = line
                .split(":")
                .nth(1)
                .unwrap()
                .split(" ")
                .nth(1)
                .unwrap()
                .trim();
            if version_str.ends_with('-') {
                // hyphen is 1 byte long, so it's safe
                version_str = &version_str[..version_str.len() - 1];
            }
            let version = Version::parse(version_str)?;
            let want = Version::parse(MIN_BAZEL)?;
            if version < want {
                return Err(format!(
                    "Installed version {} is less than required version {}",
                    version_str, MIN_BAZEL
                )
                .into());
            }
        }
    }
    if !found_version {
        return Err("Did not find version number in `bazel version` output.".into());
    }
    Ok(())
}
<commit_msg>set rustc-link-lib/search for tensorflow lib found via pkg_config<commit_after>extern crate curl;
extern crate flate2;
extern crate pkg_config;
extern crate semver;
extern crate tar;

use std::error::Error;
use std::fs::File;
use std::io::BufWriter;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process;
use std::process::Command;
use std::{env, fs};

use curl::easy::Easy;
use flate2::read::GzDecoder;
use semver::Version;
use tar::Archive;

const FRAMEWORK_LIBRARY: &'static str = "tensorflow_framework";
const LIBRARY: &'static str = "tensorflow";
const REPOSITORY: &'static str = "https://github.com/tensorflow/tensorflow.git";
const FRAMEWORK_TARGET: &'static str = "tensorflow:libtensorflow_framework.so";
const TARGET: &'static str = "tensorflow:libtensorflow.so";
// `VERSION` and `TAG` are separate because the tag is not always `'v' + VERSION`.
const VERSION: &'static str = "1.13.1";
const TAG: &'static str = "v1.13.1";
const MIN_BAZEL: &'static str = "0.5.4";

macro_rules! get(($name:expr) => (ok!(env::var($name))));
macro_rules! ok(($expression:expr) => ($expression.unwrap()));
macro_rules! log {
    ($fmt:expr) => (println!(concat!("libtensorflow-sys/build.rs:{}: ", $fmt), line!()));
    ($fmt:expr, $($arg:tt)*) => (println!(concat!("libtensorflow-sys/build.rs:{}: ", $fmt),
    line!(), $($arg)*));
}
macro_rules! log_var(($var:ident) => (log!(concat!(stringify!($var), " = {:?}"), $var)));

fn main() {
    if check_windows_lib() {
        log!("Returning early because {} was already found", LIBRARY);
        return;
    }

    if let Ok(library) = pkg_config::find_library(LIBRARY) {
        for lib in &library.libs {
            println!("cargo:rustc-link-lib=dylib={}", lib);
        }
        for path in &library.link_paths {
            println!("cargo:rustc-link-search=native={}", path.display());
        }
        log!("Returning early because {} was already found", LIBRARY);
        return;
    }

    let force_src = match env::var("TF_RUST_BUILD_FROM_SRC") {
        Ok(s) => s == "true",
        Err(_) => false,
    };

    if !force_src
        && env::consts::ARCH == "x86_64"
        && (env::consts::OS == "linux" || env::consts::OS == "macos")
    {
        install_prebuilt();
    } else {
        build_from_src();
    }
}

#[cfg(not(target_env = "msvc"))]
fn check_windows_lib() -> bool {
    false
}

#[cfg(target_env = "msvc")]
fn check_windows_lib() -> bool {
    let windows_lib: &str = &format!("{}.lib", LIBRARY);
    if let Ok(path) = env::var("PATH") {
        for p in path.split(";") {
            let path = Path::new(p).join(windows_lib);
            if path.exists() {
                println!("cargo:rustc-link-lib=dylib={}", LIBRARY);
                println!("cargo:rustc-link-search=native={}", p);
                return true;
            }
        }
    }
    false
}

fn remove_suffix(value: &mut String, suffix: &str) {
    if value.ends_with(suffix) {
        let n = value.len();
        value.truncate(n - suffix.len());
    }
}

fn extract<P: AsRef<Path>, P2: AsRef<Path>>(archive_path: P, extract_to: P2) {
    let file = File::open(archive_path).unwrap();
    let unzipped = GzDecoder::new(file);
    let mut a = Archive::new(unzipped);
    a.unpack(extract_to).unwrap();
}

// Downloads and unpacks a prebuilt binary. Only works for certain platforms.
fn install_prebuilt() {
    // Figure out the file names.
    let os = match env::consts::OS {
        "macos" => "darwin",
        x => x,
    };
    let proc_type = if cfg!(feature = "tensorflow_gpu") {
        "gpu"
    } else {
        "cpu"
    };
    let binary_url =
        format!(
        "https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-{}-{}-{}-{}.tar.gz",
        proc_type, os, env::consts::ARCH, VERSION);
    log_var!(binary_url);
    let short_file_name = binary_url.split("/").last().unwrap();
    let mut base_name = short_file_name.to_string();
    remove_suffix(&mut base_name, ".tar.gz");
    log_var!(base_name);
    let download_dir = match env::var("TF_RUST_DOWNLOAD_DIR") {
        Ok(s) => PathBuf::from(s),
        Err(_) => PathBuf::from(&get!("CARGO_MANIFEST_DIR")).join("target"),
    };
    if !download_dir.exists() {
        fs::create_dir(&download_dir).unwrap();
    }
    let file_name = download_dir.join(short_file_name);
    log_var!(file_name);

    // Download the tarball.
    if !file_name.exists() {
        let f = File::create(&file_name).unwrap();
        let mut writer = BufWriter::new(f);
        let mut easy = Easy::new();
        easy.url(&binary_url).unwrap();
        easy.write_function(move |data| Ok(writer.write(data).unwrap()))
            .unwrap();
        easy.perform().unwrap();

        let response_code = easy.response_code().unwrap();
        if response_code != 200 {
            panic!(
                "Unexpected response code {} for {}",
                response_code, binary_url
            );
        }
    }

    // Extract the tarball.
    let unpacked_dir = download_dir.join(base_name);
    let lib_dir = unpacked_dir.join("lib");
    let framework_library_file = format!("lib{}.so", FRAMEWORK_LIBRARY);
    let library_file = format!("lib{}.so", LIBRARY);
    let framework_library_full_path = lib_dir.join(&framework_library_file);
    let library_full_path = lib_dir.join(&library_file);
    if !framework_library_full_path.exists() || !library_full_path.exists() {
        extract(file_name, &unpacked_dir);
    }

    println!("cargo:rustc-link-lib=dylib={}", FRAMEWORK_LIBRARY);
    println!("cargo:rustc-link-lib=dylib={}", LIBRARY);
    let output = PathBuf::from(&get!("OUT_DIR"));
    let new_framework_library_full_path = output.join(&framework_library_file);
    if new_framework_library_full_path.exists() {
        log!(
            "File {} already exists, deleting.",
            new_framework_library_full_path.display()
        );
        std::fs::remove_file(&new_framework_library_full_path).unwrap();
    }
    let new_library_full_path = output.join(&library_file);
    if new_library_full_path.exists() {
        log!(
            "File {} already exists, deleting.",
            new_library_full_path.display()
        );
        std::fs::remove_file(&new_library_full_path).unwrap();
    }

    log!(
        "Copying {} to {}...",
        library_full_path.display(),
        new_library_full_path.display()
    );
    std::fs::copy(&library_full_path, &new_library_full_path).unwrap();
    log!(
        "Copying {} to {}...",
        framework_library_full_path.display(),
        new_framework_library_full_path.display()
    );
    std::fs::copy(
        &framework_library_full_path,
        &new_framework_library_full_path,
    )
    .unwrap();
    println!("cargo:rustc-link-search={}", output.display());
}

fn build_from_src() {
    let output = PathBuf::from(&get!("OUT_DIR"));
    log_var!(output);
    let source = PathBuf::from(&get!("CARGO_MANIFEST_DIR")).join(format!("target/source-{}", TAG));
    log_var!(source);
    let lib_dir = output.join(format!("lib-{}", TAG));
    log_var!(lib_dir);
    if lib_dir.exists() {
        log!("Directory {:?} already exists", lib_dir);
    } else {
        log!("Creating directory {:?}", lib_dir);
        fs::create_dir(lib_dir.clone()).unwrap();
    }
    let framework_library_path = lib_dir.join(format!("lib{}.so", FRAMEWORK_LIBRARY));
    log_var!(framework_library_path);
    let library_path = lib_dir.join(format!("lib{}.so", LIBRARY));
    log_var!(library_path);
    if library_path.exists() && framework_library_path.exists() {
        log!(
            "{:?} and {:?} already exist, not building",
            library_path,
            framework_library_path
        );
    } else {
        if let Err(e) = check_bazel() {
            println!(
                "cargo:error=Bazel must be installed at version {} or greater. (Error: {})",
                MIN_BAZEL, e
            );
            process::exit(1);
        }
        let framework_target_path = &FRAMEWORK_TARGET.replace(":", "/");
        log_var!(framework_target_path);
        let target_path = &TARGET.replace(":", "/");
        log_var!(target_path);
        if !Path::new(&source.join(".git")).exists() {
            run("git", |command| {
                command
                    .arg("clone")
                    .arg(format!("--branch={}", TAG))
                    .arg("--recursive")
                    .arg(REPOSITORY)
                    .arg(&source)
            });
        }
        // Only configure if not previously configured.  Configuring runs a
        // `bazel clean`, which we don't want, because we want to be able to
        // continue from a cancelled build.
        let configure_hint_file_pb = source.join(".rust-configured");
        let configure_hint_file = Path::new(&configure_hint_file_pb);
        if !configure_hint_file.exists() {
            run("bash", |command| {
                command
                    .current_dir(&source)
                    .env(
                        "TF_NEED_CUDA",
                        if cfg!(feature = "tensorflow_gpu") {
                            "1"
                        } else {
                            "0"
                        },
                    )
                    .arg("-c")
                    .arg("yes ''|./configure")
            });
            File::create(configure_hint_file).unwrap();
        }
        // Allows us to pass in --incompatible_load_argument_is_label=false
        // to work around https://github.com/tensorflow/tensorflow/issues/15492
        let bazel_args_string = if let Ok(args) = env::var("TF_RUST_BAZEL_OPTS") {
            args
        } else {
            "".to_string()
        };
        run("bazel", |command| {
            command
                .current_dir(&source)
                .arg("build")
                .arg(format!("--jobs={}", get!("NUM_JOBS")))
                .arg("--compilation_mode=opt")
                .arg("--copt=-march=native")
                .args(bazel_args_string.split_whitespace())
                .arg(TARGET)
        });
        let framework_target_bazel_bin = source.join("bazel-bin").join(framework_target_path);
        log!(
            "Copying {:?} to {:?}",
            framework_target_bazel_bin,
            framework_library_path
        );
        fs::copy(framework_target_bazel_bin, framework_library_path).unwrap();
        let target_bazel_bin = source.join("bazel-bin").join(target_path);
        log!("Copying {:?} to {:?}", target_bazel_bin, library_path);
        fs::copy(target_bazel_bin, library_path).unwrap();
    }

    println!("cargo:rustc-link-lib=dylib={}", FRAMEWORK_LIBRARY);
    println!("cargo:rustc-link-lib=dylib={}", LIBRARY);
    println!("cargo:rustc-link-search={}", lib_dir.display());
}

fn run<F>(name: &str, mut configure: F)
where
    F: FnMut(&mut Command) -> &mut Command,
{
    let mut command = Command::new(name);
    let configured = configure(&mut command);
    log!("Executing {:?}", configured);
    if !ok!(configured.status()).success() {
        panic!("failed to execute {:?}", configured);
    }
    log!("Command {:?} finished successfully", configured);
}

// Building TF 0.11.0rc1 with Bazel 0.3.0 gives this error when running `configure`:
//   expected ConfigurationTransition or NoneType for 'cfg' while calling label_list but got
// string instead:     data.
//       ERROR: com.google.devtools.build.lib.packages.BuildFileContainsErrorsException: error
// loading package '': Extension file 'tensorflow/tensorflow.bzl' has errors.
// And the simple solution is to require Bazel 0.3.1 or higher.
fn check_bazel() -> Result<(), Box<Error>> {
    let mut command = Command::new("bazel");
    command.arg("version");
    log!("Executing {:?}", command);
    let out = command.output()?;
    log!("Command {:?} finished successfully", command);
    let stdout = String::from_utf8(out.stdout)?;
    let mut found_version = false;
    for line in stdout.lines() {
        if line.starts_with("Build label:") {
            found_version = true;
            let mut version_str = line
                .split(":")
                .nth(1)
                .unwrap()
                .split(" ")
                .nth(1)
                .unwrap()
                .trim();
            if version_str.ends_with('-') {
                // hyphen is 1 byte long, so it's safe
                version_str = &version_str[..version_str.len() - 1];
            }
            let version = Version::parse(version_str)?;
            let want = Version::parse(MIN_BAZEL)?;
            if version < want {
                return Err(format!(
                    "Installed version {} is less than required version {}",
                    version_str, MIN_BAZEL
                )
                .into());
            }
        }
    }
    if !found_version {
        return Err("Did not find version number in `bazel version` output.".into());
    }
    Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
extern crate rocksdb;
mod util;

use rocksdb::{Options, DB};
use util::DBPath;

#[test]
fn test_set_num_levels() {
    let n = DBPath::new("_rust_rocksdb_test_set_num_levels");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_num_levels(2);
        let _db = DB::open(&opts, &n).unwrap();
    }
}
<commit_msg>Confirm calling Options.increase_parallelism works on all platforms...<commit_after>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
extern crate rocksdb;
mod util;

use rocksdb::{Options, DB};
use util::DBPath;

#[test]
fn test_set_num_levels() {
    let n = DBPath::new("_rust_rocksdb_test_set_num_levels");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_num_levels(2);
        let _db = DB::open(&opts, &n).unwrap();
    }
}

#[test]
fn test_increase_parallelism() {
    let n = DBPath::new("_rust_rocksdb_test_increase_parallelism");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.increase_parallelism(4);
        let _db = DB::open(&opts, &n).unwrap();
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate abomonation_derive;
extern crate abomonation;
extern crate timely;
extern crate timely_sort;
extern crate differential_dataflow;
#[macro_use]
extern crate serde_derive;
extern crate serde;

use std::rc::Rc;
use std::hash::Hash;
use std::ops::Mul;

use timely::dataflow::Scope;
use timely::progress::Timestamp;
use timely::dataflow::operators::Partition;
use timely::dataflow::operators::Concatenate;

use differential_dataflow::{ExchangeData, Collection, AsCollection};
use differential_dataflow::operators::Threshold;
use differential_dataflow::difference::Monoid;
use differential_dataflow::lattice::Lattice;
use differential_dataflow::operators::arrange::TraceAgent;
use differential_dataflow::operators::arrange::{ArrangeBySelf, ArrangeByKey};
use differential_dataflow::trace::implementations::spine_fueled::Spine;
use differential_dataflow::trace::implementations::ord::{OrdValBatch, OrdKeyBatch};

pub mod altneu;

pub mod operators;

/// A type capable of extending a stream of prefixes.
///
/**
    Implementors of `PrefixExtension` provide types and methods for extending a differential dataflow collection,
    via the three methods `count`, `propose`, and `validate`.
**/
pub trait PrefixExtender<G: Scope, R: Monoid+Mul<Output = R>> {
    /// The required type of prefix to extend.
    type Prefix;
    /// The type to be produced as extension.
    type Extension;
    /// Annotates prefixes with the number of extensions the relation would propose.
    fn count(&mut self, &Collection<G, (Self::Prefix, usize, usize), R>, usize) -> Collection<G, (Self::Prefix, usize, usize), R>;
    /// Extends each prefix with corresponding extensions.
    fn propose(&mut self, &Collection<G, Self::Prefix, R>) -> Collection<G, (Self::Prefix, Self::Extension), R>;
    /// Restricts proposed extensions by those the extender would have proposed.
    fn validate(&mut self, &Collection<G, (Self::Prefix, Self::Extension), R>) -> Collection<G, (Self::Prefix, Self::Extension), R>;
}

pub trait ProposeExtensionMethod<G: Scope, P: ExchangeData+Ord, R: Monoid+Mul<Output = R>> {
    fn propose_using<PE: PrefixExtender<G, R, Prefix=P>>(&self, extender: &mut PE) -> Collection<G, (P, PE::Extension), R>;
    fn extend<E: ExchangeData+Ord>(&self, extenders: &mut [&mut PrefixExtender<G,R,Prefix=P,Extension=E>]) -> Collection<G, (P, E), R>;
}

impl<G, P, R> ProposeExtensionMethod<G, P, R> for Collection<G, P, R>
where
    G: Scope,
    P: ExchangeData+Ord,
    R: Monoid+Mul<Output = R>,
{
    fn propose_using<PE>(&self, extender: &mut PE) -> Collection<G, (P, PE::Extension), R>
    where
        PE: PrefixExtender<G, R, Prefix=P>
    {
        extender.propose(self)
    }
    fn extend<E>(&self, extenders: &mut [&mut PrefixExtender<G,R,Prefix=P,Extension=E>]) -> Collection<G, (P, E), R>
    where
        E: ExchangeData+Ord
    {

        if extenders.len() == 1 {
            extenders[0].propose(&self.clone())
        }
        else {
            let mut counts = self.map(|p| (p, 1 << 31, 0));
            for (index,extender) in extenders.iter_mut().enumerate() {
                counts = extender.count(&counts, index);
            }

            let parts = counts.inner.partition(extenders.len() as u64, |((p, _, i),t,d)| (i as u64, (p,t,d)));

            let mut results = Vec::new();
            for (index, nominations) in parts.into_iter().enumerate() {
                let mut extensions = extenders[index].propose(&nominations.as_collection());
                for other in (0..extenders.len()).filter(|&x| x != index) {
                    extensions = extenders[other].validate(&extensions);
                }

                results.push(extensions.inner);    // save extensions
            }

            self.scope().concatenate(results).as_collection()
        }
    }
}

pub trait ValidateExtensionMethod<G: Scope, R: Monoid+Mul<Output = R>, P, E> {
    fn validate_using<PE: PrefixExtender<G, R, Prefix=P, Extension=E>>(&self, extender: &mut PE) -> Collection<G, (P, E), R>;
}

impl<G: Scope, R: Monoid+Mul<Output = R>, P, E> ValidateExtensionMethod<G, R, P, E> for Collection<G, (P, E), R> {
    fn validate_using<PE: PrefixExtender<G, R, Prefix=P, Extension=E>>(&self, extender: &mut PE) -> Collection<G, (P, E), R> {
        extender.validate(self)
    }
}

// These are all defined here so that users can be assured a common layout.
type TraceValSpine<K,V,T,R> = Spine<K, V, T, R, Rc<OrdValBatch<K,V,T,R>>>;
type TraceValHandle<K,V,T,R> = TraceAgent<TraceValSpine<K,V,T,R>>;
type TraceKeySpine<K,T,R> = Spine<K, (), T, R, Rc<OrdKeyBatch<K,T,R>>>;
type TraceKeyHandle<K,T,R> = TraceAgent<TraceKeySpine<K,T,R>>;

pub struct CollectionIndex<K, V, T, R>
where
    K: ExchangeData,
    V: ExchangeData,
    T: Lattice+ExchangeData,
    R: Monoid+Mul<Output = R>+ExchangeData,
{
    /// A trace of type (K, ()), used to count extensions for each prefix.
    count_trace: TraceKeyHandle<K, T, isize>,

    /// A trace of type (K, V), used to propose extensions for each prefix.
    propose_trace: TraceValHandle<K, V, T, R>,

    /// A trace of type ((K, V), ()), used to validate proposed extensions.
    validate_trace: TraceKeyHandle<(K, V), T, R>,
}

impl<K, V, T, R> Clone for CollectionIndex<K, V, T, R>
where
    K: ExchangeData+Hash,
    V: ExchangeData+Hash,
    T: Lattice+ExchangeData+Timestamp,
    R: Monoid+Mul<Output = R>+ExchangeData,
{
    fn clone(&self) -> Self {
        CollectionIndex {
            count_trace: self.count_trace.clone(),
            propose_trace: self.propose_trace.clone(),
            validate_trace: self.validate_trace.clone(),
        }
    }
}

impl<K, V, T, R> CollectionIndex<K, V, T, R>
where
    K: ExchangeData+Hash,
    V: ExchangeData+Hash,
    T: Lattice+ExchangeData+Timestamp,
    R: Monoid+Mul<Output = R>+ExchangeData,
{

    pub fn index<G: Scope<Timestamp = T>>(collection: &Collection<G, (K, V), R>) -> Self {
        // We need to count the number of (k, v) pairs and not rely on the given Monoid R and its binary addition operation.
        // counts and validate can share the base arrangement
        let arranged = collection.arrange_by_self();
        let counts = arranged
            .distinct()
            .map(|(k, _v)| k)
            .arrange_by_self()
            .trace;
        let propose = collection.arrange_by_key().trace;
        let validate = arranged.trace;

        CollectionIndex {
            count_trace: counts,
            propose_trace: propose,
            validate_trace: validate,
        }
    }
    pub fn extend_using<P, F: Fn(&P)->K>(&self, logic: F) -> CollectionExtender<K, V, T, R, P, F> {
        CollectionExtender {
            phantom: std::marker::PhantomData,
            indices: self.clone(),
            key_selector: Rc::new(logic),
        }
    }
}

pub struct CollectionExtender<K, V, T, R, P, F>
where
    K: ExchangeData,
    V: ExchangeData,
    T: Lattice+ExchangeData,
    R: Monoid+Mul<Output = R>+ExchangeData,
    F: Fn(&P)->K,
{
    phantom: std::marker::PhantomData<P>,
    indices: CollectionIndex<K, V, T, R>,
    key_selector: Rc<F>,
}

impl<G, K, V, R, P, F> PrefixExtender<G, R> for CollectionExtender<K, V, G::Timestamp, R, P, F>
where
    G: Scope,
    K: ExchangeData+Hash,
    V: ExchangeData+Hash,
    P: ExchangeData,
    G::Timestamp: Lattice+ExchangeData,
    R: Monoid+Mul<Output = R>+ExchangeData,
    F: Fn(&P)->K+'static,
{
    type Prefix = P;
    type Extension = V;

    fn count(&mut self, prefixes: &Collection<G, (P, usize, usize), R>, index: usize) -> Collection<G, (P, usize, usize), R> {
        let counts = self.indices.count_trace.import(&prefixes.scope());
        operators::count::count(prefixes, counts, self.key_selector.clone(), index)
    }

    fn propose(&mut self, prefixes: &Collection<G, P, R>) -> Collection<G, (P, V), R> {
        let propose = self.indices.propose_trace.import(&prefixes.scope());
        operators::propose::propose(prefixes, propose, self.key_selector.clone())
    }

    fn validate(&mut self, extensions: &Collection<G, (P, V), R>) -> Collection<G, (P, V), R> {
        let validate = self.indices.validate_trace.import(&extensions.scope());
        operators::validate::validate(extensions, validate, self.key_selector.clone())
    }
}<commit_msg>add Default constraint<commit_after>#[macro_use]
extern crate abomonation_derive;
extern crate abomonation;
extern crate timely;
extern crate timely_sort;
extern crate differential_dataflow;
#[macro_use]
extern crate serde_derive;
extern crate serde;

use std::rc::Rc;
use std::hash::Hash;
use std::ops::Mul;

use timely::dataflow::Scope;
use timely::progress::Timestamp;
use timely::dataflow::operators::Partition;
use timely::dataflow::operators::Concatenate;

use differential_dataflow::{ExchangeData, Collection, AsCollection};
use differential_dataflow::operators::Threshold;
use differential_dataflow::difference::Monoid;
use differential_dataflow::lattice::Lattice;
use differential_dataflow::operators::arrange::TraceAgent;
use differential_dataflow::operators::arrange::{ArrangeBySelf, ArrangeByKey};
use differential_dataflow::trace::implementations::spine_fueled::Spine;
use differential_dataflow::trace::implementations::ord::{OrdValBatch, OrdKeyBatch};

pub mod altneu;

pub mod operators;

/// A type capable of extending a stream of prefixes.
///
/**
    Implementors of `PrefixExtension` provide types and methods for extending a differential dataflow collection,
    via the three methods `count`, `propose`, and `validate`.
**/
pub trait PrefixExtender<G: Scope, R: Monoid+Mul<Output = R>> {
    /// The required type of prefix to extend.
    type Prefix;
    /// The type to be produced as extension.
    type Extension;
    /// Annotates prefixes with the number of extensions the relation would propose.
    fn count(&mut self, &Collection<G, (Self::Prefix, usize, usize), R>, usize) -> Collection<G, (Self::Prefix, usize, usize), R>;
    /// Extends each prefix with corresponding extensions.
    fn propose(&mut self, &Collection<G, Self::Prefix, R>) -> Collection<G, (Self::Prefix, Self::Extension), R>;
    /// Restricts proposed extensions by those the extender would have proposed.
    fn validate(&mut self, &Collection<G, (Self::Prefix, Self::Extension), R>) -> Collection<G, (Self::Prefix, Self::Extension), R>;
}

pub trait ProposeExtensionMethod<G: Scope, P: ExchangeData+Ord, R: Monoid+Mul<Output = R>> {
    fn propose_using<PE: PrefixExtender<G, R, Prefix=P>>(&self, extender: &mut PE) -> Collection<G, (P, PE::Extension), R>;
    fn extend<E: ExchangeData+Ord>(&self, extenders: &mut [&mut PrefixExtender<G,R,Prefix=P,Extension=E>]) -> Collection<G, (P, E), R>;
}

impl<G, P, R> ProposeExtensionMethod<G, P, R> for Collection<G, P, R>
where
    G: Scope,
    P: ExchangeData+Ord,
    R: Monoid+Mul<Output = R>,
{
    fn propose_using<PE>(&self, extender: &mut PE) -> Collection<G, (P, PE::Extension), R>
    where
        PE: PrefixExtender<G, R, Prefix=P>
    {
        extender.propose(self)
    }
    fn extend<E>(&self, extenders: &mut [&mut PrefixExtender<G,R,Prefix=P,Extension=E>]) -> Collection<G, (P, E), R>
    where
        E: ExchangeData+Ord
    {

        if extenders.len() == 1 {
            extenders[0].propose(&self.clone())
        }
        else {
            let mut counts = self.map(|p| (p, 1 << 31, 0));
            for (index,extender) in extenders.iter_mut().enumerate() {
                counts = extender.count(&counts, index);
            }

            let parts = counts.inner.partition(extenders.len() as u64, |((p, _, i),t,d)| (i as u64, (p,t,d)));

            let mut results = Vec::new();
            for (index, nominations) in parts.into_iter().enumerate() {
                let mut extensions = extenders[index].propose(&nominations.as_collection());
                for other in (0..extenders.len()).filter(|&x| x != index) {
                    extensions = extenders[other].validate(&extensions);
                }

                results.push(extensions.inner);    // save extensions
            }

            self.scope().concatenate(results).as_collection()
        }
    }
}

pub trait ValidateExtensionMethod<G: Scope, R: Monoid+Mul<Output = R>, P, E> {
    fn validate_using<PE: PrefixExtender<G, R, Prefix=P, Extension=E>>(&self, extender: &mut PE) -> Collection<G, (P, E), R>;
}

impl<G: Scope, R: Monoid+Mul<Output = R>, P, E> ValidateExtensionMethod<G, R, P, E> for Collection<G, (P, E), R> {
    fn validate_using<PE: PrefixExtender<G, R, Prefix=P, Extension=E>>(&self, extender: &mut PE) -> Collection<G, (P, E), R> {
        extender.validate(self)
    }
}

// These are all defined here so that users can be assured a common layout.
type TraceValSpine<K,V,T,R> = Spine<K, V, T, R, Rc<OrdValBatch<K,V,T,R>>>;
type TraceValHandle<K,V,T,R> = TraceAgent<TraceValSpine<K,V,T,R>>;
type TraceKeySpine<K,T,R> = Spine<K, (), T, R, Rc<OrdKeyBatch<K,T,R>>>;
type TraceKeyHandle<K,T,R> = TraceAgent<TraceKeySpine<K,T,R>>;

pub struct CollectionIndex<K, V, T, R>
where
    K: ExchangeData,
    V: ExchangeData,
    T: Lattice+ExchangeData+Default,
    R: Monoid+Mul<Output = R>+ExchangeData,
{
    /// A trace of type (K, ()), used to count extensions for each prefix.
    count_trace: TraceKeyHandle<K, T, isize>,

    /// A trace of type (K, V), used to propose extensions for each prefix.
    propose_trace: TraceValHandle<K, V, T, R>,

    /// A trace of type ((K, V), ()), used to validate proposed extensions.
    validate_trace: TraceKeyHandle<(K, V), T, R>,
}

impl<K, V, T, R> Clone for CollectionIndex<K, V, T, R>
where
    K: ExchangeData+Hash,
    V: ExchangeData+Hash,
    T: Lattice+ExchangeData+Timestamp,
    R: Monoid+Mul<Output = R>+ExchangeData,
{
    fn clone(&self) -> Self {
        CollectionIndex {
            count_trace: self.count_trace.clone(),
            propose_trace: self.propose_trace.clone(),
            validate_trace: self.validate_trace.clone(),
        }
    }
}

impl<K, V, T, R> CollectionIndex<K, V, T, R>
where
    K: ExchangeData+Hash,
    V: ExchangeData+Hash,
    T: Lattice+ExchangeData+Timestamp,
    R: Monoid+Mul<Output = R>+ExchangeData,
{

    pub fn index<G: Scope<Timestamp = T>>(collection: &Collection<G, (K, V), R>) -> Self {
        // We need to count the number of (k, v) pairs and not rely on the given Monoid R and its binary addition operation.
        // counts and validate can share the base arrangement
        let arranged = collection.arrange_by_self();
        let counts = arranged
            .distinct()
            .map(|(k, _v)| k)
            .arrange_by_self()
            .trace;
        let propose = collection.arrange_by_key().trace;
        let validate = arranged.trace;

        CollectionIndex {
            count_trace: counts,
            propose_trace: propose,
            validate_trace: validate,
        }
    }
    pub fn extend_using<P, F: Fn(&P)->K>(&self, logic: F) -> CollectionExtender<K, V, T, R, P, F> {
        CollectionExtender {
            phantom: std::marker::PhantomData,
            indices: self.clone(),
            key_selector: Rc::new(logic),
        }
    }
}

pub struct CollectionExtender<K, V, T, R, P, F>
where
    K: ExchangeData,
    V: ExchangeData,
    T: Lattice+ExchangeData+Default,
    R: Monoid+Mul<Output = R>+ExchangeData,
    F: Fn(&P)->K,
{
    phantom: std::marker::PhantomData<P>,
    indices: CollectionIndex<K, V, T, R>,
    key_selector: Rc<F>,
}

impl<G, K, V, R, P, F> PrefixExtender<G, R> for CollectionExtender<K, V, G::Timestamp, R, P, F>
where
    G: Scope,
    K: ExchangeData+Hash,
    V: ExchangeData+Hash,
    P: ExchangeData,
    G::Timestamp: Lattice+ExchangeData,
    R: Monoid+Mul<Output = R>+ExchangeData,
    F: Fn(&P)->K+'static,
{
    type Prefix = P;
    type Extension = V;

    fn count(&mut self, prefixes: &Collection<G, (P, usize, usize), R>, index: usize) -> Collection<G, (P, usize, usize), R> {
        let counts = self.indices.count_trace.import(&prefixes.scope());
        operators::count::count(prefixes, counts, self.key_selector.clone(), index)
    }

    fn propose(&mut self, prefixes: &Collection<G, P, R>) -> Collection<G, (P, V), R> {
        let propose = self.indices.propose_trace.import(&prefixes.scope());
        operators::propose::propose(prefixes, propose, self.key_selector.clone())
    }

    fn validate(&mut self, extensions: &Collection<G, (P, V), R>) -> Collection<G, (P, V), R> {
        let validate = self.indices.validate_trace.import(&extensions.scope());
        operators::validate::validate(extensions, validate, self.key_selector.clone())
    }
}<|endoftext|>


<commit_before>extern crate google_maps_services;
extern crate dotenv;

use dotenv::dotenv;
use google_maps_services::distance_matrix::DistanceMatrixRequestBuilder;
use google_maps_services::distance_matrix::status::TopLevelStatus;
use google_maps_services::types::TravelMode;
use google_maps_services::types::TransitMode;
use std::env;

#[test]
fn address_minimum() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();

    let request = DistanceMatrixRequestBuilder::new(origin, destination, api_key)
                    .create();

    let result = request.send();

    assert_eq!(result.status, TopLevelStatus::Ok);
}

#[test]
fn address_travel_mode() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();

    let request = DistanceMatrixRequestBuilder::new(origin, destination, api_key)
                        .set_travel_mode(TravelMode::Transit)
                        .create();

    let result = request.send();

    assert_eq!(result.status, TopLevelStatus::Ok);
}

#[test]
fn address_transit_mode_success() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();

    let request = DistanceMatrixRequestBuilder::new(origin, destination, api_key)
                        .set_travel_mode(TravelMode::Transit)
                        .set_transit_mode(TransitMode::Rail)
                        .unwrap()
                        .create();

    let result = request.send();

    assert_eq!(result.status, TopLevelStatus::Ok);
}

#[test]
#[should_panic]
fn address_transit_mode_fail() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();

    let _ = DistanceMatrixRequestBuilder::new(origin, destination, api_key)
                        .set_travel_mode(TravelMode::Bicycling)
                        .set_transit_mode(TransitMode::Rail).unwrap()
                        .create();
}
<commit_msg>More idiomatic error test implemented<commit_after>extern crate google_maps_services;
extern crate dotenv;

use dotenv::dotenv;
use google_maps_services::distance_matrix::DistanceMatrixRequestBuilder;
use google_maps_services::distance_matrix::status::TopLevelStatus;
use google_maps_services::types::TravelMode;
use google_maps_services::types::TransitMode;
use std::env;

#[test]
fn address_minimum() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();

    let request = DistanceMatrixRequestBuilder::new(origin, destination, api_key)
                    .create();

    let result = request.send();

    assert_eq!(result.status, TopLevelStatus::Ok);
    // TODO: Insert assertions against the other response fields too
}

#[test]
fn address_travel_mode() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();

    let request = DistanceMatrixRequestBuilder::new(origin, destination, api_key)
                        .set_travel_mode(TravelMode::Transit)
                        .create();

    let result = request.send();

    assert_eq!(result.status, TopLevelStatus::Ok);
}

#[test]
fn address_transit_mode_success() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();

    let request = DistanceMatrixRequestBuilder::new(origin, destination, api_key)
                        .set_travel_mode(TravelMode::Transit)
                        .set_transit_mode(TransitMode::Rail)
                        .unwrap()
                        .create();

    let result = request.send();

    assert_eq!(result.status, TopLevelStatus::Ok);
}

#[test]
fn address_transit_mode_fail() {
    dotenv().ok();
    let api_key = env::var("API_KEY").expect("API_KEY must be set in the .env file");

    let origin = "Melbourne GPO".to_string();
    let destination = "Ballarat CBD".to_string();

    /*
        TODO: See if there's another way to check if an error has occurred and
        throw a panic when the expected error occurs
    */
    let builder = DistanceMatrixRequestBuilder::new(origin, destination, api_key)
                        .set_travel_mode(TravelMode::Bicycling)
                        .set_transit_mode(TransitMode::Rail);

    match builder {
        Err(e) => {
            assert_eq!(e, google_maps_services::distance_matrix::error::IncompatibleTravelModeError);
        },
        Ok(_) => {
            panic!("There should be an error here");
        },
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{BufReader, BufRead};
use std::path::Path;
use std::collections::HashSet;
use std::num::ParseIntError;
use std::str::FromStr;
use ::error::{ProcError, ProcFile, ProcOper};
use ::{TaskId, MemSize};

#[derive(Debug, PartialEq)]
pub struct PidStatus {
    pub name: String,
    pub tgid: TaskId,
    pub pid: TaskId,
    pub ppid: TaskId,
    pub tracerpid: TaskId,
    // uid: Real, Effective, Saved, Filesystem
    pub uid: (u32, u32, u32, u32),
    // gid: Real, Effective, Saved, Filesystem
    pub gid: (u32, u32, u32, u32),
    pub fdsize: u32,
    pub vmpeak: Option<MemSize>,
    pub vmsize: Option<MemSize>,
    pub vmlck: Option<MemSize>,
    pub vmpin: Option<MemSize>,
    pub vmhwm: Option<MemSize>,
    pub vmrss: Option<MemSize>,
    pub vmdata: Option<MemSize>,
    pub vmstk: Option<MemSize>,
    pub vmexe: Option<MemSize>,
    pub vmlib: Option<MemSize>,
    pub vmpte: Option<MemSize>,
    pub vmpmd: Option<MemSize>,
    pub vmswap: Option<MemSize>,
    pub threads: u32
}

/// Extract a line, and error on missing value, or parsing failure.
macro_rules! extract_line {
    ($lines:expr, $key: expr, $func: expr) => {
        // Default value for missing fields.
        match extract_line_opt!($lines, $key, $func) {
            Some(value) => value,
            None => return Err(
                ProcError::new_more(ProcOper::ParsingField, ProcFile::PidStatus,
                    Some(concat!("missing ", $key)))
            ),
        }
    }
}

/// Extract a line, evalute to an Option (None on missing field), error on parsing
/// failure.
macro_rules! extract_line_opt {
    ($lines:expr, $key: expr, $func: expr) => { {
        // Default value for missing fields>
        let mut value = None;
        for raw_line in $lines.by_ref() {
            // Unwrap error
            let line = try!(raw_line);
            // Find colon offset, error on no match.
            let colon_offset = match line.find(':') {
                Some(i) => i,
                None => return Err(
                    ProcError::new_more(ProcOper::ParsingField, ProcFile::PidStatus, Some("Line missing colon"))
                ),
            };
            // Split into Key: Value based on colon offset.
            let (first, second) = line.split_at(colon_offset);
            let key = first.trim();
            let (_, last) = second.split_at(1);
            let line_val = last.trim();
            // If we're not looking for this key, try the next one.
            if !STATUS_COLS.contains(key) {
                continue;
            }
            // If key doesn't match, break
            if $key != key {
                break;
            }

            // Call parsing function after trimming value.
            value = Some(try!(
                $func(line_val).map_err(|e|
                    ProcError::new(ProcOper::ParsingField, ProcFile::PidStatus,
                        Some(e), Some($key))
                )
            ));
            // We have finished finding this value
            break;
        }
        value
    } }
}

impl PidStatus {
    // Generate PidStatus struct given a process directory
    pub fn new(pid_dir: &Path) -> Result<Self, ProcError> {
        // Try opening file
        let status_file = try!(
            File::open(pid_dir.join("status"))
                .map_err(|e| ProcError::new_err(ProcOper::Opening, ProcFile::PidStatus, e))
        );

        let lines =
            BufReader::with_capacity(4096, status_file)
                .lines()
                .map(|r|
                    match r {
                        Ok(o) => Ok(o),
                        Err(e) => Err(ProcError::new_err(ProcOper::Reading, ProcFile::PidStatus, e))
                    }
                );
        Self::parse_string(lines)
    }

    fn parse_string<I: Iterator<Item=Result<String, ProcError>>>(mut lines: I) -> Result<Self, ProcError> {
        // It's quite important that these appear in the order that they
        // appear in the status file
        Ok(PidStatus{
            name: extract_line!(lines, "Name", |s| Ok((s as &str).to_owned()) as Result<String, ProcError>),
            tgid: extract_line!(lines, "Tgid", parse_any),
            pid: extract_line!(lines, "Pid", parse_any),
            ppid: extract_line!(lines, "PPid", parse_any),
            tracerpid: extract_line!(lines, "TracerPid", parse_any),
            uid : extract_line!(lines, "Uid", parse_uids),
            gid : extract_line!(lines, "Gid", parse_uids),
            fdsize : extract_line!(lines, "FDSize", parse_any),
            vmpeak: extract_line_opt!(lines, "VmPeak", parse_mem),
            vmsize: extract_line_opt!(lines, "VmSize", parse_mem),
            vmlck: extract_line_opt!(lines, "VmLck", parse_mem),
            vmpin: extract_line_opt!(lines, "VmPin", parse_mem),
            vmhwm: extract_line_opt!(lines, "VmHWM", parse_mem),
            vmrss: extract_line_opt!(lines, "VmRSS", parse_mem),
            vmdata: extract_line_opt!(lines, "VmData", parse_mem),
            vmstk: extract_line_opt!(lines, "VmStk", parse_mem),
            vmexe: extract_line_opt!(lines, "VmExe", parse_mem),
            vmlib: extract_line_opt!(lines, "VmLib", parse_mem),
            vmpte: extract_line_opt!(lines, "VmPTE", parse_mem),
            vmpmd: extract_line_opt!(lines, "VmPMD", parse_mem),
            vmswap: extract_line_opt!(lines, "VmSwap", parse_mem),
            threads: extract_line!(lines, "Threads", parse_any)
        })
    }
}

lazy_static! {
    // This vec should contain all columns that the parser is looking for,
    // at the moment this is definitely static.
    static ref STATUS_COLS: HashSet<String> = vec!["Name", "Tgid", "Pid", "PPid",
        "TracerPid", "Uid", "Gid", "FDSize", "VmPeak", "VmSize", "VmLck",
        "VmPin", "VmHWM", "VmRSS", "VmData", "VmStk", "VmExe", "VmLib",
        "VmPMD", "VmPTE", "VmSwap", "Threads"]
            .into_iter()
            .map(|s| s.to_owned())
            .collect();
}

// Parse anything that's parsable (type checker didn't like simple closures).
fn parse_any<N: FromStr>(str: &str) -> Result<N, N::Err> {
    str.parse()
}

fn parse_uids(uid_str: &str) -> Result<(u32, u32, u32, u32), ProcError> {
    let uids = try!(
        uid_str.split("\t")
            .filter(|s| s != &"")
            .map(|s|
                s.parse()
            ).collect::<Result<Vec<_>, _>>()
            .map_err(|e|
                ProcError::new(ProcOper::ParsingField, ProcFile::PidStatus,
                    Some(e), Some("parsing uid"))
            )

    );
    if uids.len() != 4 {
        return Err(ProcError::new_more(ProcOper::ParsingField,
            ProcFile::PidStatus, Some("missing uids")));
    }
    Ok((uids[0], uids[1], uids[2], uids[3]))
}

fn parse_mem(mem_str: &str) -> Result<MemSize, ParseIntError> {
    mem_str.trim_right_matches(" kB")
        .parse::<MemSize>()
        .map(|n| n * 1024)
}

#[test]
fn test_no_colon() {
    let lines = "Name".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Err(ProcError::new_more(ProcOper::ParsingField, ProcFile::PidStatus, Some("Line missing colon")))
    );
}

#[test]
fn test_missing_tgid() {
    let lines = "Name: a\n\
                 Pid: 4\n\
                 ".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Err(ProcError::new_more(ProcOper::ParsingField, ProcFile::PidStatus, Some("missing Tgid")))
    );
}

#[test]
fn test_uid_parse() {
    let lines = "Name:	bash\n\
                 Tgid:	27899\n\
                 Ngid:	0\n\
                 Pid:	27899\n\
                 PPid:	4351\n\
                 TracerPid:	0\n\
                 Uid:	1000	1000	a000	1000\n\
                 ".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Err(ProcError::new(ProcOper::ParsingField, ProcFile::PidStatus,
            Some("a".parse::<u8>().unwrap_err()), Some("Uid")))
    );
}

#[test]
fn test_uid_count() {
    let lines = "Name:	bash\n\
                 Tgid:	27899\n\
                 Ngid:	0\n\
                 Pid:	27899\n\
                 PPid:	4351\n\
                 TracerPid:	0\n\
                 Uid:	1000	1000	1000\n\
                 ".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Err(ProcError::new_more(ProcOper::ParsingField, ProcFile::PidStatus, Some("Uid")))
    );
}

#[test]
fn test_mem_parse() {
    let lines = "Name:	bash\n\
                 Tgid:	27899\n\
                 Ngid:	0\n\
                 Pid:	27899\n\
                 PPid:	4351\n\
                 TracerPid:	0\n\
                 Uid:	1000	1000	1000	1000\n\
                 Gid:	1000	1000	1000	1000\n\
                 FDSize:	256\n\
                 Groups:	10 18 27 35 101 103 104 105 250 1000 1001 \n\
                 NStgid:	27899\n\
                 NSpid:	27899\n\
                 NSpgid:	27899\n\
                 NSsid:	27899\n\
                 VmPeak:	   a0896 kB\n\
                 ".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Err(ProcError::new(ProcOper::ParsingField, ProcFile::PidStatus,
            Some("a".parse::<u8>().unwrap_err()), Some("VmPeak")))
    );
}

#[test]
fn test_parsing() {
    let lines = "Name:	bash\n\
                 Tgid:	27899\n\
                 Pid:	27899\n\
                 PPid:	4351\n\
                 TracerPid:	0\n\
                 Uid:	1000	1000	1000	1000\n\
                 Gid:	1000	1000	1000	1000\n\
                 FDSize:	256\n\
                 Groups:	10 18 27 35 101 103 104 105 250 1000 1001 \n\
                 NStgid:	27899\n\
                 NSpid:	27899\n\
                 NSpgid:	27899\n\
                 NSsid:	27899\n\
                 VmPeak:	   20896 kB\n\
                 VmSize:	   20868 kB\n\
                 VmLck:	       0 kB\n\
                 VmPin:	       0 kB\n\
                 VmHWM:	    4584 kB\n\
                 VmRSS:	    4584 kB\n\
                 VmData:	    1176 kB\n\
                 VmStk:	     136 kB\n\
                 VmExe:	     688 kB\n\
                 VmLib:	    2540 kB\n\
                 VmPTE:	      64 kB\n\
                 VmPMD:	      12 kB\n\
                 VmSwap:	       0 kB\n\
                 Threads:	1\n\
                 ".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Ok(PidStatus {
            name: "bash".to_owned(),
            tgid: 27899,
            pid: 27899,
            ppid: 4351,
            tracerpid: 0,
            uid: (1000, 1000, 1000, 1000),
            gid: (1000, 1000, 1000, 1000),
            fdsize: 256,
            vmpeak: Some(21397504),
            vmsize: Some(21368832),
            vmlck: Some(0),
            vmpin: Some(0),
            vmhwm: Some(4694016),
            vmrss: Some(4694016),
            vmdata: Some(1204224),
            vmstk: Some(139264),
            vmexe: Some(704512),
            vmlib: Some(2600960),
            vmpte: Some(65536),
            vmpmd: Some(12288),
            vmswap: Some(0),
            threads: 1
        })
    );
}
<commit_msg>Add comments<commit_after>use std::fs::File;
use std::io::{BufReader, BufRead};
use std::path::Path;
use std::collections::HashSet;
use std::num::ParseIntError;
use std::str::FromStr;
use ::error::{ProcError, ProcFile, ProcOper};
use ::{TaskId, MemSize};

#[derive(Debug, PartialEq)]
pub struct PidStatus {
    // TODO: Maybe these should all be optional, and be more annoying to call
    pub name: String,
    pub tgid: TaskId,
    pub pid: TaskId,
    pub ppid: TaskId,
    pub tracerpid: TaskId,
    // uid: Real, Effective, Saved, Filesystem
    pub uid: (u32, u32, u32, u32),
    // gid: Real, Effective, Saved, Filesystem
    pub gid: (u32, u32, u32, u32),
    pub fdsize: u32,
    pub vmpeak: Option<MemSize>,
    pub vmsize: Option<MemSize>,
    pub vmlck: Option<MemSize>,
    pub vmpin: Option<MemSize>,
    pub vmhwm: Option<MemSize>,
    pub vmrss: Option<MemSize>,
    pub vmdata: Option<MemSize>,
    pub vmstk: Option<MemSize>,
    pub vmexe: Option<MemSize>,
    pub vmlib: Option<MemSize>,
    pub vmpte: Option<MemSize>,
    pub vmpmd: Option<MemSize>,
    pub vmswap: Option<MemSize>,
    pub threads: u32
}

/// Extract a line, and error on missing value, or parsing failure.
macro_rules! extract_line {
    ($lines:expr, $key: expr, $func: expr) => {
        // Default value for missing fields.
        match extract_line_opt!($lines, $key, $func) {
            Some(value) => value,
            None => return Err(
                ProcError::new_more(ProcOper::ParsingField, ProcFile::PidStatus,
                    Some(concat!("missing ", $key)))
            ),
        }
    }
}

/// Extract a line, evalute to an Option (None on missing field), error on parsing
/// failure.
macro_rules! extract_line_opt {
    ($lines:expr, $key: expr, $func: expr) => { {
        // Default value for missing fields>
        let mut value = None;
        for raw_line in $lines.by_ref() {
            // Unwrap error
            let line = try!(raw_line);
            // Find colon offset, error on no match.
            let colon_offset = match line.find(':') {
                Some(i) => i,
                None => return Err(
                    ProcError::new_more(ProcOper::ParsingField, ProcFile::PidStatus, Some("Line missing colon"))
                ),
            };
            // Split into Key: Value based on colon offset.
            let (first, second) = line.split_at(colon_offset);
            let key = first.trim();
            let (_, last) = second.split_at(1);
            let line_val = last.trim();
            // If we're not looking for this key, try the next one.
            if !STATUS_COLS.contains(key) {
                continue;
            }
            // If key doesn't match, break
            if $key != key {
                break;
            }

            // Call parsing function after trimming value.
            value = Some(try!(
                $func(line_val).map_err(|e|
                    ProcError::new(ProcOper::ParsingField, ProcFile::PidStatus,
                        Some(e), Some($key))
                )
            ));
            // We have finished finding this value
            break;
        }
        value
    } }
}

impl PidStatus {
    // Generate PidStatus struct given a process directory
    pub fn new(pid_dir: &Path) -> Result<Self, ProcError> {
        // Try opening file
        let status_file = try!(
            File::open(pid_dir.join("status"))
                .map_err(|e| ProcError::new_err(ProcOper::Opening, ProcFile::PidStatus, e))
        );

        let lines =
            BufReader::with_capacity(4096, status_file)
                .lines()
                .map(|r|
                    match r {
                        Ok(o) => Ok(o),
                        Err(e) => Err(ProcError::new_err(ProcOper::Reading, ProcFile::PidStatus, e))
                    }
                );
        Self::parse_string(lines)
    }

    fn parse_string<I: Iterator<Item=Result<String, ProcError>>>(mut lines: I) -> Result<Self, ProcError> {
        // It's quite important that these appear in the order that they
        // appear in the status file
        Ok(PidStatus{
            name: extract_line!(lines, "Name", |s| Ok((s as &str).to_owned()) as Result<String, ProcError>),
            tgid: extract_line!(lines, "Tgid", parse_any),
            pid: extract_line!(lines, "Pid", parse_any),
            ppid: extract_line!(lines, "PPid", parse_any),
            tracerpid: extract_line!(lines, "TracerPid", parse_any),
            uid : extract_line!(lines, "Uid", parse_uids),
            gid : extract_line!(lines, "Gid", parse_uids),
            fdsize : extract_line!(lines, "FDSize", parse_any),
            vmpeak: extract_line_opt!(lines, "VmPeak", parse_mem),
            vmsize: extract_line_opt!(lines, "VmSize", parse_mem),
            vmlck: extract_line_opt!(lines, "VmLck", parse_mem),
            vmpin: extract_line_opt!(lines, "VmPin", parse_mem),
            vmhwm: extract_line_opt!(lines, "VmHWM", parse_mem),
            vmrss: extract_line_opt!(lines, "VmRSS", parse_mem),
            vmdata: extract_line_opt!(lines, "VmData", parse_mem),
            vmstk: extract_line_opt!(lines, "VmStk", parse_mem),
            vmexe: extract_line_opt!(lines, "VmExe", parse_mem),
            vmlib: extract_line_opt!(lines, "VmLib", parse_mem),
            vmpte: extract_line_opt!(lines, "VmPTE", parse_mem),
            vmpmd: extract_line_opt!(lines, "VmPMD", parse_mem),
            vmswap: extract_line_opt!(lines, "VmSwap", parse_mem),
            threads: extract_line!(lines, "Threads", parse_any)
        })
    }
}

lazy_static! {
    // This vec should contain all columns that the parser is looking for,
    // at the moment this is definitely static.
    //
    // If this is not kept uptodate, the values will be ignored.
    static ref STATUS_COLS: HashSet<String> = vec!["Name", "Tgid", "Pid", "PPid",
        "TracerPid", "Uid", "Gid", "FDSize", "VmPeak", "VmSize", "VmLck",
        "VmPin", "VmHWM", "VmRSS", "VmData", "VmStk", "VmExe", "VmLib",
        "VmPMD", "VmPTE", "VmSwap", "Threads"]
            .into_iter()
            .map(|s| s.to_owned())
            .collect();
}

// Parse anything that's parsable (type checker didn't like simple closures).
fn parse_any<N: FromStr>(str: &str) -> Result<N, N::Err> {
    str.parse()
}

fn parse_uids(uid_str: &str) -> Result<(u32, u32, u32, u32), ProcError> {
    let uids = try!(
        uid_str.split("\t")
            .filter(|s| s != &"")
            .map(|s|
                s.parse()
            ).collect::<Result<Vec<_>, _>>()
            .map_err(|e|
                ProcError::new(ProcOper::ParsingField, ProcFile::PidStatus,
                    Some(e), Some("parsing uid"))
            )

    );
    if uids.len() != 4 {
        return Err(ProcError::new_more(ProcOper::ParsingField,
            ProcFile::PidStatus, Some("missing uids")));
    }
    Ok((uids[0], uids[1], uids[2], uids[3]))
}

fn parse_mem(mem_str: &str) -> Result<MemSize, ParseIntError> {
    mem_str.trim_right_matches(" kB")
        .parse::<MemSize>()
        .map(|n| n * 1024)
}

#[test]
fn test_no_colon() {
    let lines = "Name".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Err(ProcError::new_more(ProcOper::ParsingField, ProcFile::PidStatus, Some("Line missing colon")))
    );
}

#[test]
fn test_missing_tgid() {
    let lines = "Name: a\n\
                 Pid: 4\n\
                 ".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Err(ProcError::new_more(ProcOper::ParsingField, ProcFile::PidStatus, Some("missing Tgid")))
    );
}

#[test]
fn test_uid_parse() {
    let lines = "Name:	bash\n\
                 Tgid:	27899\n\
                 Ngid:	0\n\
                 Pid:	27899\n\
                 PPid:	4351\n\
                 TracerPid:	0\n\
                 Uid:	1000	1000	a000	1000\n\
                 ".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Err(ProcError::new(ProcOper::ParsingField, ProcFile::PidStatus,
            Some("a".parse::<u8>().unwrap_err()), Some("Uid")))
    );
}

#[test]
fn test_uid_count() {
    let lines = "Name:	bash\n\
                 Tgid:	27899\n\
                 Ngid:	0\n\
                 Pid:	27899\n\
                 PPid:	4351\n\
                 TracerPid:	0\n\
                 Uid:	1000	1000	1000\n\
                 ".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Err(ProcError::new_more(ProcOper::ParsingField, ProcFile::PidStatus, Some("Uid")))
    );
}

#[test]
fn test_mem_parse() {
    let lines = "Name:	bash\n\
                 Tgid:	27899\n\
                 Ngid:	0\n\
                 Pid:	27899\n\
                 PPid:	4351\n\
                 TracerPid:	0\n\
                 Uid:	1000	1000	1000	1000\n\
                 Gid:	1000	1000	1000	1000\n\
                 FDSize:	256\n\
                 Groups:	10 18 27 35 101 103 104 105 250 1000 1001 \n\
                 NStgid:	27899\n\
                 NSpid:	27899\n\
                 NSpgid:	27899\n\
                 NSsid:	27899\n\
                 VmPeak:	   a0896 kB\n\
                 ".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Err(ProcError::new(ProcOper::ParsingField, ProcFile::PidStatus,
            Some("a".parse::<u8>().unwrap_err()), Some("VmPeak")))
    );
}

#[test]
fn test_parsing() {
    let lines = "Name:	bash\n\
                 Tgid:	27899\n\
                 Pid:	27899\n\
                 PPid:	4351\n\
                 TracerPid:	0\n\
                 Uid:	1000	1000	1000	1000\n\
                 Gid:	1000	1000	1000	1000\n\
                 FDSize:	256\n\
                 Groups:	10 18 27 35 101 103 104 105 250 1000 1001 \n\
                 NStgid:	27899\n\
                 NSpid:	27899\n\
                 NSpgid:	27899\n\
                 NSsid:	27899\n\
                 VmPeak:	   20896 kB\n\
                 VmSize:	   20868 kB\n\
                 VmLck:	       0 kB\n\
                 VmPin:	       0 kB\n\
                 VmHWM:	    4584 kB\n\
                 VmRSS:	    4584 kB\n\
                 VmData:	    1176 kB\n\
                 VmStk:	     136 kB\n\
                 VmExe:	     688 kB\n\
                 VmLib:	    2540 kB\n\
                 VmPTE:	      64 kB\n\
                 VmPMD:	      12 kB\n\
                 VmSwap:	       0 kB\n\
                 Threads:	1\n\
                 ".lines().map(|l| Ok(l.to_owned()));
    let status = PidStatus::parse_string(lines);
    assert_eq!(status,
        Ok(PidStatus {
            name: "bash".to_owned(),
            tgid: 27899,
            pid: 27899,
            ppid: 4351,
            tracerpid: 0,
            uid: (1000, 1000, 1000, 1000),
            gid: (1000, 1000, 1000, 1000),
            fdsize: 256,
            vmpeak: Some(21397504),
            vmsize: Some(21368832),
            vmlck: Some(0),
            vmpin: Some(0),
            vmhwm: Some(4694016),
            vmrss: Some(4694016),
            vmdata: Some(1204224),
            vmstk: Some(139264),
            vmexe: Some(704512),
            vmlib: Some(2600960),
            vmpte: Some(65536),
            vmpmd: Some(12288),
            vmswap: Some(0),
            threads: 1
        })
    );
}
<|endoftext|>


<commit_before>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

pub mod avcodec;
mod avutil;
pub use avutil::*;
mod error;
pub use error::*;
mod ffmpeg;
use ffmpeg as ffi;
pub mod swscale;

pub use ffi::AVPixelFormat_AV_PIX_FMT_NV12;
pub use ffi::AVPixelFormat_AV_PIX_FMT_YUV420P;
pub use ffi::AV_CODEC_CAP_DR1;
pub use ffi::FF_PROFILE_H264_BASELINE;
pub use ffi::FF_PROFILE_H264_EXTENDED;
pub use ffi::FF_PROFILE_H264_HIGH;
pub use ffi::FF_PROFILE_H264_HIGH_10;
pub use ffi::FF_PROFILE_H264_HIGH_422;
pub use ffi::FF_PROFILE_H264_HIGH_444_PREDICTIVE;
pub use ffi::FF_PROFILE_H264_MAIN;
pub use ffi::FF_PROFILE_H264_MULTIVIEW_HIGH;
pub use ffi::FF_PROFILE_H264_STEREO_HIGH;
pub use ffi::FF_PROFILE_HEVC_MAIN;
pub use ffi::FF_PROFILE_HEVC_MAIN_10;
pub use ffi::FF_PROFILE_HEVC_MAIN_STILL_PICTURE;
pub use ffi::FF_PROFILE_VP9_0;
pub use ffi::FF_PROFILE_VP9_1;
pub use ffi::FF_PROFILE_VP9_2;
pub use ffi::FF_PROFILE_VP9_3;
<commit_msg>media: ffmpeg: Fix doctest failure.<commit_after>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

pub mod avcodec;
mod avutil;
pub use avutil::*;
mod error;
pub use error::*;
mod ffmpeg;
use crate::ffmpeg as ffi;
pub mod swscale;

pub use ffi::AVPixelFormat_AV_PIX_FMT_NV12;
pub use ffi::AVPixelFormat_AV_PIX_FMT_YUV420P;
pub use ffi::AV_CODEC_CAP_DR1;
pub use ffi::FF_PROFILE_H264_BASELINE;
pub use ffi::FF_PROFILE_H264_EXTENDED;
pub use ffi::FF_PROFILE_H264_HIGH;
pub use ffi::FF_PROFILE_H264_HIGH_10;
pub use ffi::FF_PROFILE_H264_HIGH_422;
pub use ffi::FF_PROFILE_H264_HIGH_444_PREDICTIVE;
pub use ffi::FF_PROFILE_H264_MAIN;
pub use ffi::FF_PROFILE_H264_MULTIVIEW_HIGH;
pub use ffi::FF_PROFILE_H264_STEREO_HIGH;
pub use ffi::FF_PROFILE_HEVC_MAIN;
pub use ffi::FF_PROFILE_HEVC_MAIN_10;
pub use ffi::FF_PROFILE_HEVC_MAIN_STILL_PICTURE;
pub use ffi::FF_PROFILE_VP9_0;
pub use ffi::FF_PROFILE_VP9_1;
pub use ffi::FF_PROFILE_VP9_2;
pub use ffi::FF_PROFILE_VP9_3;
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{context::Context, filters};

use diem_config::config::ApiConfig;
use diem_types::chain_id::ChainId;
use storage_interface::MoveDbReader;

use std::sync::Arc;
use tokio::runtime::{Builder, Runtime};

/// Creates HTTP server (warp-based)
/// Returns handle to corresponding Tokio runtime
pub fn bootstrap(chain_id: ChainId, db: Arc<dyn MoveDbReader>, config: &ApiConfig) -> Runtime {
    let runtime = Builder::new_multi_thread()
        .thread_name("api")
        .enable_all()
        .build()
        .expect("[api] failed to create runtime");

    let service = Arc::new(Context::new(chain_id, db));
    let routes = filters::routes(service);

    // Ensure that we actually bind to the socket first before spawning the
    // server tasks. This helps in tests to prevent races where a client attempts
    // to make a request before the server task is actually listening on the
    // socket.
    //
    // Note: we need to enter the runtime context first to actually bind, since
    //       tokio TcpListener can only be bound inside a tokio context.

    let _guard = runtime.enter();

    let server = warp::serve(routes).bind(config.address);
    runtime.handle().spawn(server);
    runtime
}
<commit_msg>start service inside tokio runtime<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{context::Context, filters};

use diem_config::config::ApiConfig;
use diem_types::chain_id::ChainId;
use storage_interface::MoveDbReader;

use std::sync::Arc;
use tokio::runtime::{Builder, Runtime};

/// Creates HTTP server (warp-based)
/// Returns handle to corresponding Tokio runtime
pub fn bootstrap(chain_id: ChainId, db: Arc<dyn MoveDbReader>, config: &ApiConfig) -> Runtime {
    let runtime = Builder::new_multi_thread()
        .thread_name("api")
        .enable_all()
        .build()
        .expect("[api] failed to create runtime");

    let address = config.address.clone();
    runtime.spawn(async move {
        let service = Arc::new(Context::new(chain_id, db));
        let routes = filters::routes(service);
        let server = warp::serve(routes).bind(address);
        server.await
    });
    runtime
}
<|endoftext|>


<commit_before>use ast::Expression;

// Such imports are used to allow for the expr_literal macro to work
use parser::number::numeric_literal;
use parser::identifier::identifier_literal;

// Temp do bad stuff
named!(pub expression_literal<Expression>,
    complete!(alt!(numeric_literal | identifier_literal))
);<commit_msg>Add parse_expression function<commit_after>use nom::IResult;
use ast::Expression;
use std::boxed::Box;

// Such imports are used to allow for the expr_literal macro to work
use parser::number::numeric_literal;
use parser::identifier::identifier_literal;

pub enum ParseResult<'a> {
    Done(Box<Expression>),
    Error(&'a [u8], Box<Expression>),
}

pub fn parse_expression(bytes: &[u8]) -> ParseResult {
    match expression_literal(bytes) {
        IResult::Done(rest, complete) => {
            if rest.len() > 0 {
                ParseResult::Error(rest, Box::new(complete))

            } else {
                ParseResult::Done(Box::new(complete))
            }
        },

        // TODO: Better error here
        _ => panic!("Parsing error here"),
    }
}

// Temp do bad stuff
named!(pub expression_literal<Expression>,
    complete!(alt!(numeric_literal | identifier_literal))
);<|endoftext|>