<commit_before>use self::code_from_cargo::Kind;
use crate::errors::*;
use serde::Deserialize;
use std::collections::HashMap;
use std::env::current_dir;
use std::path::{Path, PathBuf};
use url::Url;

const CRATES_IO_INDEX: &str = "https://github.com/rust-lang/crates.io-index";
const CRATES_IO_REGISTRY: &str = "crates-io";

pub fn registry_path() -> Result<PathBuf> {
    Ok(cargo_home()?
        .join("registry")
        .join("index")
        .join(short_name(&registry_url()?)))
}

#[derive(Debug, Deserialize)]
struct Source {
    #[serde(rename = "replace-with")]
    replace_with: Option<String>,
    registry: Option<String>,
}

#[derive(Debug, Deserialize)]
struct CargoConfig {
    #[serde(default)]
    sources: HashMap<String, Source>,
}

fn cargo_home() -> Result<PathBuf> {
    let default_cargo_home = dirs::home_dir()
        .map(|x| x.join(".cargo"))
        .chain_err(|| ErrorKind::ReadHomeDirFailure)?;
    let cargo_home = std::env::var("CARGO_HOME")
        .map(PathBuf::from)
        .unwrap_or(default_cargo_home);
    Ok(cargo_home)
}

pub fn registry_url() -> Result<Url> {
    // TODO support local registry sources, directory sources, git sources: https://doc.rust-lang.org/cargo/reference/source-replacement.html?highlight=replace-with#source-replacement
    fn read_config(registries: &mut HashMap<String, Source>, path: impl AsRef<Path>) -> Result<()> {
        let content = std::fs::read(path)?;
        let config =
            toml::from_slice::<CargoConfig>(&content).map_err(|_| ErrorKind::InvalidCargoConfig)?;
        for (key, value) in config.sources {
            registries.entry(key).or_insert(value);
        }
        Ok(())
    }
    // registry might be replaced with another source
    // it's looks like a singly linked list
    // put relations in this map.
    let mut registries: HashMap<String, Source> = HashMap::new();

    // ref: https://doc.rust-lang.org/cargo/reference/config.html#hierarchical-structure
    for work_dir in current_dir()?.ancestors() {
        let config_path = work_dir.join(".cargo").join("config");
        if config_path.is_file() {
            read_config(&mut registries, config_path)?;
        }
    }

    let default_config_path = cargo_home()?.join("config");
    if default_config_path.is_file() {
        read_config(&mut registries, default_config_path)?;
    }

    // find head of the linked list
    let mut source = registries
        .remove(CRATES_IO_REGISTRY)
        .unwrap_or_else(|| Source {
            replace_with: None,
            registry: Some(CRATES_IO_INDEX.to_string()),
        });

    // search this linked list and find the tail
    while let Some(replace_with) = &source.replace_with {
        source = registries
            .remove(replace_with)
            .chain_err(|| ErrorKind::NoSuchSourceFound(replace_with.to_string()))?;
    }

    let registry_url = source
        .registry
        .and_then(|x| Url::parse(&x).ok())
        .chain_err(|| ErrorKind::InvalidCargoConfig)?;

    Ok(registry_url)
}

fn short_name(registry: &Url) -> String {
    // ref: https://github.com/rust-lang/cargo/blob/4c1fa54d10f58d69ac9ff55be68e1b1c25ecb816/src/cargo/sources/registry/mod.rs#L386-L390
    #![allow(deprecated)]
    use std::hash::{Hash, Hasher, SipHasher};

    let mut hasher = SipHasher::new_with_keys(0, 0);
    Kind::Registry.hash(&mut hasher);
    registry.as_str().hash(&mut hasher);
    let hash = hex::encode(hasher.finish().to_le_bytes());

    let ident = registry.host_str().unwrap_or("").to_string();

    format!("{}-{}", ident, hash)
}

#[test]
fn test_short_name() {
    fn test_helper(url: &str, name: &str) {
        let url = Url::parse(url).unwrap();
        assert_eq!(short_name(&url), name);
    }
    test_helper(
        "https://github.com/rust-lang/crates.io-index",
        "github.com-1ecc6299db9ec823",
    );
}

mod code_from_cargo {
    #![allow(dead_code)]

    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
    pub enum Kind {
        Git(GitReference),
        Path,
        Registry,
        LocalRegistry,
        Directory,
    }

    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
    pub enum GitReference {
        Tag(String),
        Branch(String),
        Rev(String),
    }
}
<commit_msg>fix typo(CargoConfig): 'sources' -> 'source'<commit_after>use self::code_from_cargo::Kind;
use crate::errors::*;
use serde::Deserialize;
use std::collections::HashMap;
use std::env::current_dir;
use std::path::{Path, PathBuf};
use url::Url;

const CRATES_IO_INDEX: &str = "https://github.com/rust-lang/crates.io-index";
const CRATES_IO_REGISTRY: &str = "crates-io";

pub fn registry_path() -> Result<PathBuf> {
    Ok(cargo_home()?
        .join("registry")
        .join("index")
        .join(short_name(&registry_url()?)))
}

#[derive(Debug, Deserialize)]
struct Source {
    #[serde(rename = "replace-with")]
    replace_with: Option<String>,
    registry: Option<String>,
}

#[derive(Debug, Deserialize)]
struct CargoConfig {
    #[serde(default)]
    source: HashMap<String, Source>,
}

fn cargo_home() -> Result<PathBuf> {
    let default_cargo_home = dirs::home_dir()
        .map(|x| x.join(".cargo"))
        .chain_err(|| ErrorKind::ReadHomeDirFailure)?;
    let cargo_home = std::env::var("CARGO_HOME")
        .map(PathBuf::from)
        .unwrap_or(default_cargo_home);
    Ok(cargo_home)
}

pub fn registry_url() -> Result<Url> {
    // TODO support local registry sources, directory sources, git sources: https://doc.rust-lang.org/cargo/reference/source-replacement.html?highlight=replace-with#source-replacement
    fn read_config(registries: &mut HashMap<String, Source>, path: impl AsRef<Path>) -> Result<()> {
        let content = std::fs::read(path)?;
        let config =
            toml::from_slice::<CargoConfig>(&content).map_err(|_| ErrorKind::InvalidCargoConfig)?;
        for (key, value) in config.source {
            registries.entry(key).or_insert(value);
        }
        Ok(())
    }
    // registry might be replaced with another source
    // it's looks like a singly linked list
    // put relations in this map.
    let mut registries: HashMap<String, Source> = HashMap::new();

    // ref: https://doc.rust-lang.org/cargo/reference/config.html#hierarchical-structure
    for work_dir in current_dir()?.ancestors() {
        let config_path = work_dir.join(".cargo").join("config");
        if config_path.is_file() {
            read_config(&mut registries, config_path)?;
        }
    }

    let default_config_path = cargo_home()?.join("config");
    if default_config_path.is_file() {
        read_config(&mut registries, default_config_path)?;
    }

    // find head of the linked list
    let mut source = registries
        .remove(CRATES_IO_REGISTRY)
        .unwrap_or_else(|| Source {
            replace_with: None,
            registry: Some(CRATES_IO_INDEX.to_string()),
        });

    // search this linked list and find the tail
    while let Some(replace_with) = &source.replace_with {
        source = registries
            .remove(replace_with)
            .chain_err(|| ErrorKind::NoSuchSourceFound(replace_with.to_string()))?;
    }

    let registry_url = source
        .registry
        .and_then(|x| Url::parse(&x).ok())
        .chain_err(|| ErrorKind::InvalidCargoConfig)?;

    Ok(registry_url)
}

fn short_name(registry: &Url) -> String {
    // ref: https://github.com/rust-lang/cargo/blob/4c1fa54d10f58d69ac9ff55be68e1b1c25ecb816/src/cargo/sources/registry/mod.rs#L386-L390
    #![allow(deprecated)]
    use std::hash::{Hash, Hasher, SipHasher};

    let mut hasher = SipHasher::new_with_keys(0, 0);
    Kind::Registry.hash(&mut hasher);
    registry.as_str().hash(&mut hasher);
    let hash = hex::encode(hasher.finish().to_le_bytes());

    let ident = registry.host_str().unwrap_or("").to_string();

    format!("{}-{}", ident, hash)
}

#[test]
fn test_short_name() {
    fn test_helper(url: &str, name: &str) {
        let url = Url::parse(url).unwrap();
        assert_eq!(short_name(&url), name);
    }
    test_helper(
        "https://github.com/rust-lang/crates.io-index",
        "github.com-1ecc6299db9ec823",
    );
}

mod code_from_cargo {
    #![allow(dead_code)]

    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
    pub enum Kind {
        Git(GitReference),
        Path,
        Registry,
        LocalRegistry,
        Directory,
    }

    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
    pub enum GitReference {
        Tag(String),
        Branch(String),
        Rev(String),
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Some crumminess to make sure we link correctly

#[cfg(target_os = "linux")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
// fontconfig must come before expat for linking to succeed
#[link(name = "fontconfig")]
#[link(name = "expat")]
#[link(name = "X11")]
extern { }

#[cfg(target_os = "android")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
#[link(name = "expat")]
#[link(name = "fontconfig")]
#[link(name = "EGL")]
extern { }

#[cfg(target_os = "macos")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
#[link(name = "objc")]
#[link(name = "IOSurface", kind = "framework")]
#[link(name = "OpenGL", kind = "framework")]
#[link(name = "Foundation", kind = "framework")]
#[link(name = "QuartzCore", kind = "framework")]
#[link(name = "ApplicationServices", kind = "framework")]
extern { }
<commit_msg>Update link libraries to ensure that check-servo-net can link skia<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Some crumminess to make sure we link correctly

#[cfg(target_os = "linux")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
// skia must come before freetype for linking to succeed
#[link(name = "freetype")]
// fontconfig must come before expat for linking to succeed
#[link(name = "fontconfig")]
#[link(name = "expat")]
#[link(name = "X11")]
extern { }

#[cfg(target_os = "android")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
#[link(name = "expat")]
#[link(name = "fontconfig")]
#[link(name = "EGL")]
extern { }

#[cfg(target_os = "macos")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
#[link(name = "objc")]
#[link(name = "IOSurface", kind = "framework")]
#[link(name = "OpenGL", kind = "framework")]
#[link(name = "Foundation", kind = "framework")]
#[link(name = "QuartzCore", kind = "framework")]
#[link(name = "ApplicationServices", kind = "framework")]
extern { }
<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Nick Platt <platt.nicholas@gmail.com>
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
//
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.

// spell-checker:ignore (ToDO) filetime strptime utcoff strs datetime MMDDhhmm

pub extern crate filetime;

#[macro_use]
extern crate uucore;

use clap::{App, Arg, ArgGroup};
use filetime::*;
use std::fs::{self, File};
use std::io::Error;
use std::path::Path;

static VERSION: &str = env!("CARGO_PKG_VERSION");
static ABOUT: &str = "Update the access and modification times of each FILE to the current time.";
pub mod options {
    pub mod sources {
        pub static DATE: &str = "date";
        pub static REFERENCE: &str = "reference";
        pub static CURRENT: &str = "current";
    }
    pub static ACCESS: &str = "access";
    pub static MODIFICATION: &str = "modification";
    pub static NO_CREATE: &str = "no-create";
    pub static NO_DEREF: &str = "no-dereference";
    pub static TIME: &str = "time";
}

static ARG_FILES: &str = "files";

// Since touch's date/timestamp parsing doesn't account for timezone, the
// returned value from time::strptime() is UTC. We get system's timezone to
// localize the time.
macro_rules! to_local(
    ($exp:expr) => ({
        let mut tm = $exp;
        tm.tm_utcoff = time::now().tm_utcoff;
        tm
    })
);

macro_rules! local_tm_to_filetime(
    ($exp:expr) => ({
        let ts = $exp.to_timespec();
        FileTime::from_unix_time(ts.sec as i64, ts.nsec as u32)
    })
);

fn get_usage() -> String {
    format!("{0} [OPTION]... [USER]", executable!())
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    let matches = App::new(executable!())
        .version(VERSION)
        .about(ABOUT)
        .usage(&usage[..])
        .arg(
            Arg::with_name(options::ACCESS)
                .short("a")
                .help("change only the access time"),
        )
        .arg(
            Arg::with_name(options::sources::CURRENT)
                .short("t")
                .help("use [[CC]YY]MMDDhhmm[.ss] instead of the current time")
                .value_name("STAMP")
                .takes_value(true),
        )
        .arg(
            Arg::with_name(options::sources::DATE)
                .short("d")
                .long(options::sources::DATE)
                .help("parse argument and use it instead of current time")
                .value_name("STRING"),
        )
        .arg(
            Arg::with_name(options::MODIFICATION)
                .short("m")
                .help("change only the modification time"),
        )
        .arg(
            Arg::with_name(options::NO_CREATE)
                .short("c")
                .long(options::NO_CREATE)
                .help("do not create any files"),
        )
        .arg(
            Arg::with_name(options::NO_DEREF)
                .short("h")
                .long(options::NO_DEREF)
                .help(
                    "affect each symbolic link instead of any referenced file \
                     (only for systems that can change the timestamps of a symlink)",
                ),
        )
        .arg(
            Arg::with_name(options::sources::REFERENCE)
                .short("r")
                .long(options::sources::REFERENCE)
                .help("use this file's times instead of the current time")
                .value_name("FILE"),
        )
        .arg(
            Arg::with_name(options::TIME)
                .long(options::TIME)
                .help(
                    "change only the specified time: \"access\", \"atime\", or \
                     \"use\" are equivalent to -a; \"modify\" or \"mtime\" are \
                     equivalent to -m",
                )
                .value_name("WORD")
                .possible_values(&["access", "atime", "use"])
                .takes_value(true),
        )
        .arg(
            Arg::with_name(ARG_FILES)
                .multiple(true)
                .takes_value(true)
                .min_values(1),
        )
        .group(ArgGroup::with_name("sources").args(&[
            options::sources::CURRENT,
            options::sources::DATE,
            options::sources::REFERENCE,
        ]))
        .get_matches_from(args);

    let files: Vec<String> = matches
        .values_of(ARG_FILES)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    let (mut atime, mut mtime) = if matches.is_present(options::sources::REFERENCE) {
        stat(
            &matches.value_of(options::sources::REFERENCE).unwrap()[..],
            !matches.is_present(options::NO_DEREF),
        )
    } else if matches.is_present(options::sources::DATE)
        || matches.is_present(options::sources::CURRENT)
    {
        let timestamp = if matches.is_present(options::sources::DATE) {
            parse_date(matches.value_of(options::sources::DATE).unwrap().as_ref())
        } else {
            parse_timestamp(
                matches
                    .value_of(options::sources::CURRENT)
                    .unwrap()
                    .as_ref(),
            )
        };
        (timestamp, timestamp)
    } else {
        let now = local_tm_to_filetime!(time::now());
        (now, now)
    };

    for filename in &files {
        let path = &filename[..];

        if !Path::new(path).exists() {
            // no-dereference included here for compatibility
            if matches.is_present(options::NO_CREATE) || matches.is_present(options::NO_DEREF) {
                continue;
            }

            if let Err(e) = File::create(path) {
                show_warning!("cannot touch '{}': {}", path, e);
                continue;
            };

            // Minor optimization: if no reference time was specified, we're done.
            if !matches.is_present("sources") {
                continue;
            }
        }

        // If changing "only" atime or mtime, grab the existing value of the other.
        // Note that "-a" and "-m" may be passed together; this is not an xor.
        if matches.is_present(options::ACCESS)
            || matches.is_present(options::MODIFICATION)
            || matches.is_present(options::TIME)
        {
            let st = stat(path, !matches.is_present(options::NO_DEREF));
            let time = matches.value_of(options::TIME).unwrap_or("");

            if !(matches.is_present(options::ACCESS)
                || time.contains(&"access".to_owned())
                || time.contains(&"atime".to_owned())
                || time.contains(&"use".to_owned()))
            {
                atime = st.0;
            }

            if !(matches.is_present(options::MODIFICATION)
                || time.contains(&"modify".to_owned())
                || time.contains(&"mtime".to_owned()))
            {
                mtime = st.1;
            }
        }

        if matches.is_present(options::NO_DEREF) {
            if let Err(e) = set_symlink_file_times(path, atime, mtime) {
                show_warning!("cannot touch '{}': {}", path, e);
            }
        } else if let Err(e) = filetime::set_file_times(path, atime, mtime) {
            show_warning!("cannot touch '{}': {}", path, e);
        }
    }

    0
}

fn stat(path: &str, follow: bool) -> (FileTime, FileTime) {
    let metadata = if follow {
        fs::symlink_metadata(path)
    } else {
        fs::metadata(path)
    };

    match metadata {
        Ok(m) => (
            FileTime::from_last_access_time(&m),
            FileTime::from_last_modification_time(&m),
        ),
        Err(_) => crash!(
            1,
            "failed to get attributes of '{}': {}",
            path,
            Error::last_os_error()
        ),
    }
}

fn parse_date(str: &str) -> FileTime {
    // This isn't actually compatible with GNU touch, but there doesn't seem to
    // be any simple specification for what format this parameter allows and I'm
    // not about to implement GNU parse_datetime.
    // http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=lib/parse-datetime.y
    match time::strptime(str, "%c") {
        Ok(tm) => local_tm_to_filetime!(to_local!(tm)),
        Err(e) => panic!("Unable to parse date\n{}", e),
    }
}

fn parse_timestamp(s: &str) -> FileTime {
    let now = time::now();
    let (format, ts) = match s.chars().count() {
        15 => ("%Y%m%d%H%M.%S", s.to_owned()),
        12 => ("%Y%m%d%H%M", s.to_owned()),
        13 => ("%y%m%d%H%M.%S", s.to_owned()),
        10 => ("%y%m%d%H%M", s.to_owned()),
        11 => ("%Y%m%d%H%M.%S", format!("{}{}", now.tm_year + 1900, s)),
        8 => ("%Y%m%d%H%M", format!("{}{}", now.tm_year + 1900, s)),
        _ => panic!("Unknown timestamp format"),
    };

    match time::strptime(&ts, format) {
        Ok(tm) => local_tm_to_filetime!(to_local!(tm)),
        Err(e) => panic!("Unable to parse timestamp\n{}", e),
    }
}
<commit_msg>touch: turn macros into functions<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Nick Platt <platt.nicholas@gmail.com>
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
//
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.

// spell-checker:ignore (ToDO) filetime strptime utcoff strs datetime MMDDhhmm

pub extern crate filetime;

#[macro_use]
extern crate uucore;

use clap::{App, Arg, ArgGroup};
use filetime::*;
use std::fs::{self, File};
use std::io::Error;
use std::path::Path;

static VERSION: &str = env!("CARGO_PKG_VERSION");
static ABOUT: &str = "Update the access and modification times of each FILE to the current time.";
pub mod options {
    pub mod sources {
        pub static DATE: &str = "date";
        pub static REFERENCE: &str = "reference";
        pub static CURRENT: &str = "current";
    }
    pub static ACCESS: &str = "access";
    pub static MODIFICATION: &str = "modification";
    pub static NO_CREATE: &str = "no-create";
    pub static NO_DEREF: &str = "no-dereference";
    pub static TIME: &str = "time";
}

static ARG_FILES: &str = "files";

fn to_local(mut tm: time::Tm) -> time::Tm {
    tm.tm_utcoff = time::now().tm_utcoff;
    tm
}

fn local_tm_to_filetime(tm: time::Tm) -> FileTime {
    let ts = tm.to_timespec();
    FileTime::from_unix_time(ts.sec as i64, ts.nsec as u32)
}

fn get_usage() -> String {
    format!("{0} [OPTION]... [USER]", executable!())
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    let matches = App::new(executable!())
        .version(VERSION)
        .about(ABOUT)
        .usage(&usage[..])
        .arg(
            Arg::with_name(options::ACCESS)
                .short("a")
                .help("change only the access time"),
        )
        .arg(
            Arg::with_name(options::sources::CURRENT)
                .short("t")
                .help("use [[CC]YY]MMDDhhmm[.ss] instead of the current time")
                .value_name("STAMP")
                .takes_value(true),
        )
        .arg(
            Arg::with_name(options::sources::DATE)
                .short("d")
                .long(options::sources::DATE)
                .help("parse argument and use it instead of current time")
                .value_name("STRING"),
        )
        .arg(
            Arg::with_name(options::MODIFICATION)
                .short("m")
                .help("change only the modification time"),
        )
        .arg(
            Arg::with_name(options::NO_CREATE)
                .short("c")
                .long(options::NO_CREATE)
                .help("do not create any files"),
        )
        .arg(
            Arg::with_name(options::NO_DEREF)
                .short("h")
                .long(options::NO_DEREF)
                .help(
                    "affect each symbolic link instead of any referenced file \
                     (only for systems that can change the timestamps of a symlink)",
                ),
        )
        .arg(
            Arg::with_name(options::sources::REFERENCE)
                .short("r")
                .long(options::sources::REFERENCE)
                .help("use this file's times instead of the current time")
                .value_name("FILE"),
        )
        .arg(
            Arg::with_name(options::TIME)
                .long(options::TIME)
                .help(
                    "change only the specified time: \"access\", \"atime\", or \
                     \"use\" are equivalent to -a; \"modify\" or \"mtime\" are \
                     equivalent to -m",
                )
                .value_name("WORD")
                .possible_values(&["access", "atime", "use"])
                .takes_value(true),
        )
        .arg(
            Arg::with_name(ARG_FILES)
                .multiple(true)
                .takes_value(true)
                .min_values(1),
        )
        .group(ArgGroup::with_name("sources").args(&[
            options::sources::CURRENT,
            options::sources::DATE,
            options::sources::REFERENCE,
        ]))
        .get_matches_from(args);

    let files: Vec<String> = matches
        .values_of(ARG_FILES)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    let (mut atime, mut mtime) = if matches.is_present(options::sources::REFERENCE) {
        stat(
            &matches.value_of(options::sources::REFERENCE).unwrap()[..],
            !matches.is_present(options::NO_DEREF),
        )
    } else if matches.is_present(options::sources::DATE)
        || matches.is_present(options::sources::CURRENT)
    {
        let timestamp = if matches.is_present(options::sources::DATE) {
            parse_date(matches.value_of(options::sources::DATE).unwrap().as_ref())
        } else {
            parse_timestamp(
                matches
                    .value_of(options::sources::CURRENT)
                    .unwrap()
                    .as_ref(),
            )
        };
        (timestamp, timestamp)
    } else {
        let now = local_tm_to_filetime(time::now());
        (now, now)
    };

    for filename in &files {
        let path = &filename[..];

        if !Path::new(path).exists() {
            // no-dereference included here for compatibility
            if matches.is_present(options::NO_CREATE) || matches.is_present(options::NO_DEREF) {
                continue;
            }

            if let Err(e) = File::create(path) {
                show_warning!("cannot touch '{}': {}", path, e);
                continue;
            };

            // Minor optimization: if no reference time was specified, we're done.
            if !matches.is_present("sources") {
                continue;
            }
        }

        // If changing "only" atime or mtime, grab the existing value of the other.
        // Note that "-a" and "-m" may be passed together; this is not an xor.
        if matches.is_present(options::ACCESS)
            || matches.is_present(options::MODIFICATION)
            || matches.is_present(options::TIME)
        {
            let st = stat(path, !matches.is_present(options::NO_DEREF));
            let time = matches.value_of(options::TIME).unwrap_or("");

            if !(matches.is_present(options::ACCESS)
                || time.contains(&"access".to_owned())
                || time.contains(&"atime".to_owned())
                || time.contains(&"use".to_owned()))
            {
                atime = st.0;
            }

            if !(matches.is_present(options::MODIFICATION)
                || time.contains(&"modify".to_owned())
                || time.contains(&"mtime".to_owned()))
            {
                mtime = st.1;
            }
        }

        if matches.is_present(options::NO_DEREF) {
            if let Err(e) = set_symlink_file_times(path, atime, mtime) {
                show_warning!("cannot touch '{}': {}", path, e);
            }
        } else if let Err(e) = filetime::set_file_times(path, atime, mtime) {
            show_warning!("cannot touch '{}': {}", path, e);
        }
    }

    0
}

fn stat(path: &str, follow: bool) -> (FileTime, FileTime) {
    let metadata = if follow {
        fs::symlink_metadata(path)
    } else {
        fs::metadata(path)
    };

    match metadata {
        Ok(m) => (
            FileTime::from_last_access_time(&m),
            FileTime::from_last_modification_time(&m),
        ),
        Err(_) => crash!(
            1,
            "failed to get attributes of '{}': {}",
            path,
            Error::last_os_error()
        ),
    }
}

fn parse_date(str: &str) -> FileTime {
    // This isn't actually compatible with GNU touch, but there doesn't seem to
    // be any simple specification for what format this parameter allows and I'm
    // not about to implement GNU parse_datetime.
    // http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=lib/parse-datetime.y
    match time::strptime(str, "%c") {
        Ok(tm) => local_tm_to_filetime(to_local(tm)),
        Err(e) => panic!("Unable to parse date\n{}", e),
    }
}

fn parse_timestamp(s: &str) -> FileTime {
    let now = time::now();
    let (format, ts) = match s.chars().count() {
        15 => ("%Y%m%d%H%M.%S", s.to_owned()),
        12 => ("%Y%m%d%H%M", s.to_owned()),
        13 => ("%y%m%d%H%M.%S", s.to_owned()),
        10 => ("%y%m%d%H%M", s.to_owned()),
        11 => ("%Y%m%d%H%M.%S", format!("{}{}", now.tm_year + 1900, s)),
        8 => ("%Y%m%d%H%M", format!("{}{}", now.tm_year + 1900, s)),
        _ => panic!("Unknown timestamp format"),
    };

    match time::strptime(&ts, format) {
        Ok(tm) => local_tm_to_filetime(to_local(tm)),
        Err(e) => panic!("Unable to parse timestamp\n{}", e),
    }
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate notify;

use self::notify::{Watcher, RecursiveMode, DebouncedEvent};
use std::sync::mpsc::channel;
use std::time::Duration;
use std::env;
use std::fs;
use std::thread;
use std::process::{Command,Child};

/// watches the debug build, restarts server on build
pub fn watcher (matches: &getopts::Matches) {
    if !matches.opt_present("w") { return }

    let mut stratis_path = env::var("STRATIS").expect("no \'STRATIS\' path found in environment vars");
    let stratis_dest;

    if matches.opt_present("d") {
        stratis_path.push_str("\\server\\target\\debug\\");
        stratis_dest = stratis_path.clone()+"PAN_stratis.exe";
    }
    else {
        stratis_path.push_str("\\server\\target\\release\\");
        stratis_dest = stratis_path.clone()+"\\PAN_stratis.exe";
    }

    let (tx, rx) = channel();
    let mut w = self::notify::watcher(tx,Duration::from_secs(3)).expect("unable to create filesys watcher");

    w.watch(stratis_path.clone()+"\\stratis.exe",RecursiveMode::NonRecursive).expect("unable to watch directory");

    let mut spawn_handle: Option<Child> = None;

    for n in rx.iter() {
        let mut new_spawn_handle = None;
        println!("event: {:?}",n);

        match n {
            DebouncedEvent::Write(path) => {
                if let Some(ref mut h) = spawn_handle {
                    if let Ok(_) = h.kill() {
                        println!("process-killed\n");
                        thread::sleep(Duration::from_secs(1));

                        if let Ok(r) = fs::copy(path,&stratis_dest) {
                            println!("watcher-copy:{:?}",r);
                            new_spawn_handle = spawn(&stratis_dest);
                        }
                    }
                }
                else { //no child process alive?
                    if let Ok(r) = fs::copy(path,&stratis_dest) {
                        println!("watcher-copy:{:?}",r);
                        new_spawn_handle = spawn(&stratis_dest);
                    }
                }

                spawn_handle = new_spawn_handle;
                if let Some(ref h) = spawn_handle {
                    println!("process-spawned:{:?}\n",h.id());
                }
            },
            _ => {  },
        }
    }

}

fn spawn(path: &str) -> Option<Child> {
    let r = Command::new(path).spawn();
    match r {
        Ok(h) => {
            Some(h)
        },
        Err(e) => {
            println!("spawn-err:{:?}",e);
            None
        }
    }
}
<commit_msg>include unity in build watcher<commit_after>extern crate getopts;
extern crate notify;

use self::notify::{Watcher, RecursiveMode, DebouncedEvent};
use std::sync::mpsc::channel;
use std::time::Duration;
use std::env;
use std::fs;
use std::path;
use std::thread;
use std::process::{Command,Child};

/// watches the debug build, restarts server on build
pub fn watcher (matches: &getopts::Matches) {
    if !matches.opt_present("w") { return }

    let stratis_project = env::var("STRATIS").expect("no \'STRATIS\' path found in environment vars");
    let stratis_path;
    let stratis_dest;

    let unity_path;
    let unity_dest = env::var("STRATIS_UNITY");

    if matches.opt_present("d") {
        stratis_path = stratis_project.clone() + "\\server\\target\\debug\\";
        stratis_dest = stratis_path.clone()+"PAN_stratis.exe";

        unity_path = stratis_project.clone()+"\\unity\\target\\debug";
    }
    else {
        stratis_path = stratis_project.clone() + "\\server\\target\\release\\";
        stratis_dest = stratis_path.clone()+"\\PAN_stratis.exe";

        unity_path = stratis_project.clone()+"\\unity\\target\\release";
    }

    let (tx, rx) = channel();
    let mut w = self::notify::watcher(tx,Duration::from_secs(3)).expect("unable to create filesys watcher");

    w.watch(stratis_path.clone()+"\\stratis.exe",RecursiveMode::NonRecursive).expect("unable to watch directory");

    if let Ok(ref dest) = unity_dest {
        println!("watching stratis_unity builds for:{:?}",dest);
        w.watch(unity_path.clone()+"\\stratis_unity.dll",RecursiveMode::NonRecursive).expect("unable to watch directory");

    }

    let mut spawn_handle: Option<Child> = None;

    for n in rx.iter() {
        let mut new_spawn_handle = None;
        println!("event: {:?}",n);

        match n {
            DebouncedEvent::Write(path) => {
                if path == path::PathBuf::from(stratis_path.clone()+"stratis.exe") {
                    if let Some(ref mut h) = spawn_handle {
                        if let Ok(_) = h.kill() {
                            println!("process-killed\n");
                            thread::sleep(Duration::from_secs(1));

                            if let Ok(r) = fs::copy(&path,&stratis_dest) {
                                println!("watcher-copy:{:?}",r);
                                new_spawn_handle = spawn(&stratis_dest);
                            }
                        }
                    }
                    else { //no child process alive?
                        if let Ok(r) = fs::copy(&path,&stratis_dest) {
                            println!("watcher-copy:{:?}",r);
                            new_spawn_handle = spawn(&stratis_dest);
                        }
                    }

                    spawn_handle = new_spawn_handle;
                    if let Some(ref h) = spawn_handle {
                        println!("process-spawned:{:?}\n",h.id());
                    }
                }
                else if path == path::PathBuf::from(unity_path.clone()+"\\stratis_unity.dll") {
                    if let Ok(ref unity_dest) = unity_dest {
                        println!("copying unity dll");
                        let r = fs::copy(&path,unity_dest.clone()+"\\Assets\\Plugins\\stratis_unity.dll");
                        println!("watcher-copy:{:?}",r);
                    }
                }
            },
            _ => {  },
        }
    }

}

fn spawn(path: &str) -> Option<Child> {
    let r = Command::new(path).spawn();
    match r {
        Ok(h) => {
            Some(h)
        },
        Err(e) => {
            println!("spawn-err:{:?}",e);
            None
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use fnv::FnvHashSet;
use graphql_ir::{Program, ValidationResult};
use graphql_transforms::{
    apply_fragment_arguments, client_extensions, flatten, generate_id_field, generate_typename,
    handle_field_transform, inline_fragments, mask, remove_base_fragments, skip_client_extensions,
    skip_redundant_nodes, skip_split_operation, skip_unreachable_node, split_module_import,
    transform_connections, transform_defer_stream, transform_match, validate_module_conflicts,
    ConnectionInterface,
};
use interner::StringKey;

pub struct Programs<'schema> {
    pub source: Program<'schema>,
    pub reader: Program<'schema>,
    pub normalization: Program<'schema>,
    pub operation_text: Program<'schema>,
    pub typegen: Program<'schema>,
}

pub fn apply_transforms<'schema, TConnectionInterface: ConnectionInterface>(
    program: Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
    connection_interface: &TConnectionInterface,
) -> ValidationResult<Programs<'schema>> {
    // common
    //  |- reader
    //  |- operation
    //     |- normalization
    //     |- operation_text
    let common_program = apply_common_transforms(&program, connection_interface)?;
    let reader_program = apply_reader_transforms(&common_program, base_fragment_names);
    let operation_program = apply_operation_transforms(&common_program)?;
    let normalization_program = apply_normalization_transforms(&operation_program)?;
    let operation_text_program = apply_operation_text_transforms(&operation_program);
    let typegen_program = apply_typegen_transforms(&program, base_fragment_names);

    Ok(Programs {
        source: program,
        reader: reader_program,
        normalization: normalization_program,
        operation_text: operation_text_program,
        typegen: typegen_program,
    })
}

/// Applies transforms that apply to every output.
fn apply_common_transforms<'schema, TConnectionInterface: ConnectionInterface>(
    program: &Program<'schema>,
    connection_interface: &TConnectionInterface,
) -> ValidationResult<Program<'schema>> {
    // JS compiler
    // - DisallowIdAsAlias
    // + ConnectionTransform
    // - RelayDirectiveTransform
    // + MaskTransform
    // + MatchTransform
    // - RefetchableFragmentTransform
    // + DeferStreamTransform

    let program = transform_connections(program, connection_interface);
    let program = mask(&program);
    let program = transform_match(&program)?;
    transform_defer_stream(&program)
}

/// Applies transforms only for generated reader code.
/// Corresponds to the "fragment transforms" in the JS compiler.
fn apply_reader_transforms<'schema>(
    program: &Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
) -> Program<'schema> {
    // JS compiler
    // + ClientExtensionsTransform
    // + FieldHandleTransform
    // - InlineDataFragmentTransform
    // + FlattenTransform, flattenAbstractTypes: true
    // - SkipRedundantNodesTransform
    let program = handle_field_transform(&program);
    let program = remove_base_fragments(&program, base_fragment_names);
    let program = flatten(&program, true);
    client_extensions(&program)
}

/// Applies transforms that apply to all operation artifacts.
/// Corresponds to the "query transforms" in the JS compiler.
fn apply_operation_transforms<'schema>(
    program: &Program<'schema>,
) -> ValidationResult<Program<'schema>> {
    // JS compiler
    // + SplitModuleImportTransform
    // - ValidateUnusedVariablesTransform
    // + ApplyFragmentArgumentTransform
    // - ValidateGlobalVariablesTransform
    // + GenerateIDFieldTransform
    // - TestOperationTransform
    let program = split_module_import(&program);
    let program = apply_fragment_arguments(&program)?;
    let program = generate_id_field(&program);

    Ok(program)
}

/// After the operation transforms, this applies further transforms that only
/// apply to the generated normalization code.
///
/// Corresponds to the "codegen transforms" in the JS compiler
fn apply_normalization_transforms<'schema>(
    program: &Program<'schema>,
) -> ValidationResult<Program<'schema>> {
    // JS compiler
    // + SkipUnreachableNodeTransform
    // + InlineFragmentsTransform
    // + ClientExtensionsTransform
    // + FlattenTransform, flattenAbstractTypes: true
    // + SkipRedundantNodesTransform
    // + GenerateTypeNameTransform
    // - ValidateServerOnlyDirectivesTransform

    let program = skip_unreachable_node(&program);
    let program = inline_fragments(&program);
    let program = flatten(&program, true);
    validate_module_conflicts(&program)?;
    let program = skip_redundant_nodes(&program);
    let program = client_extensions(&program);
    Ok(generate_typename(&program))
}

/// After the operation transforms, this applies further transforms that only
/// apply to the printed operation text.
///
/// Corresponds to the "print transforms" in the JS compiler
fn apply_operation_text_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // + SkipSplitOperationTransform
    // - ClientExtensionsTransform
    // + SkipClientExtensionsTransform
    // + SkipUnreachableNodeTransform
    // + FlattenTransform, flattenAbstractTypes: false
    // + GenerateTypeNameTransform
    // - SkipHandleFieldTransform
    // - FilterDirectivesTransform
    // - SkipUnusedVariablesTransform
    // - ValidateRequiredArgumentsTransform

    let program = skip_split_operation(&program);
    let program = skip_client_extensions(&program);
    let program = skip_unreachable_node(&program);
    let program = flatten(&program, false);
    generate_typename(&program)
}

fn apply_typegen_transforms<'schema>(
    program: &Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
) -> Program<'schema> {
    // JS compiler
    // - RelayDirectiveTransform,
    // - MaskTransform
    // - MatchTransform
    // + FlattenTransform, flattenAbstractTypes: false
    // - RefetchableFragmentTransform,

    let program = remove_base_fragments(&program, base_fragment_names);
    flatten(&program, false)
}
<commit_msg>Wrap transforms with Timer:time(...)<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use common::Timer;
use fnv::FnvHashSet;
use graphql_ir::{Program, ValidationResult};
use graphql_transforms::{
    apply_fragment_arguments, client_extensions, flatten, generate_id_field, generate_typename,
    handle_field_transform, inline_fragments, mask, remove_base_fragments, skip_client_extensions,
    skip_redundant_nodes, skip_split_operation, skip_unreachable_node, split_module_import,
    transform_connections, transform_defer_stream, transform_match, validate_module_conflicts,
    ConnectionInterface,
};
use interner::StringKey;

pub struct Programs<'schema> {
    pub source: Program<'schema>,
    pub reader: Program<'schema>,
    pub normalization: Program<'schema>,
    pub operation_text: Program<'schema>,
    pub typegen: Program<'schema>,
}

pub fn apply_transforms<'schema, TConnectionInterface: ConnectionInterface>(
    program: Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
    connection_interface: &TConnectionInterface,
) -> ValidationResult<Programs<'schema>> {
    // common
    //  |- reader
    //  |- operation
    //     |- normalization
    //     |- operation_text
    let common_program = apply_common_transforms(&program, connection_interface)?;
    let reader_program = apply_reader_transforms(&common_program, base_fragment_names);
    let operation_program = apply_operation_transforms(&common_program)?;
    let normalization_program = apply_normalization_transforms(&operation_program)?;
    let operation_text_program = apply_operation_text_transforms(&operation_program);
    let typegen_program = apply_typegen_transforms(&program, base_fragment_names);

    Ok(Programs {
        source: program,
        reader: reader_program,
        normalization: normalization_program,
        operation_text: operation_text_program,
        typegen: typegen_program,
    })
}

/// Applies transforms that apply to every output.
fn apply_common_transforms<'schema, TConnectionInterface: ConnectionInterface>(
    program: &Program<'schema>,
    connection_interface: &TConnectionInterface,
) -> ValidationResult<Program<'schema>> {
    // JS compiler
    // - DisallowIdAsAlias
    // + ConnectionTransform
    // - RelayDirectiveTransform
    // + MaskTransform
    // + MatchTransform
    // - RefetchableFragmentTransform
    // + DeferStreamTransform
    println!("apply_common_transforms");

    let program = Timer::time("transform_connections", || {
        transform_connections(program, connection_interface)
    });
    let program = Timer::time("mask", || mask(&program));
    let program = Timer::time("transform_match", || transform_match(&program))?;
    Timer::time("transform_defer_stream", || {
        transform_defer_stream(&program)
    })
}

/// Applies transforms only for generated reader code.
/// Corresponds to the "fragment transforms" in the JS compiler.
fn apply_reader_transforms<'schema>(
    program: &Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
) -> Program<'schema> {
    // JS compiler
    // + ClientExtensionsTransform
    // + FieldHandleTransform
    // - InlineDataFragmentTransform
    // + FlattenTransform, flattenAbstractTypes: true
    // - SkipRedundantNodesTransform
    println!("apply_reader_transforms");

    let program = Timer::time("handle_field_transform", || {
        handle_field_transform(&program)
    });
    let program = Timer::time("remove_base_fragments", || {
        remove_base_fragments(&program, base_fragment_names)
    });
    let program = Timer::time("flatten", || flatten(&program, true));

    Timer::time("client_extensions", || client_extensions(&program))
}

/// Applies transforms that apply to all operation artifacts.
/// Corresponds to the "query transforms" in the JS compiler.
fn apply_operation_transforms<'schema>(
    program: &Program<'schema>,
) -> ValidationResult<Program<'schema>> {
    // JS compiler
    // + SplitModuleImportTransform
    // - ValidateUnusedVariablesTransform
    // + ApplyFragmentArgumentTransform
    // - ValidateGlobalVariablesTransform
    // + GenerateIDFieldTransform
    // - TestOperationTransform
    println!("apply_operation_transforms");
    let program = Timer::time("split_module_import", || split_module_import(&program));
    let program = Timer::time("apply_fragment_arguments", || {
        apply_fragment_arguments(&program)
    })?;
    let program = Timer::time("generate_id_field", || generate_id_field(&program));

    Ok(program)
}

/// After the operation transforms, this applies further transforms that only
/// apply to the generated normalization code.
///
/// Corresponds to the "codegen transforms" in the JS compiler
fn apply_normalization_transforms<'schema>(
    program: &Program<'schema>,
) -> ValidationResult<Program<'schema>> {
    // JS compiler
    // + SkipUnreachableNodeTransform
    // + InlineFragmentsTransform
    // + ClientExtensionsTransform
    // + FlattenTransform, flattenAbstractTypes: true
    // + SkipRedundantNodesTransform
    // + GenerateTypeNameTransform
    // - ValidateServerOnlyDirectivesTransform
    println!("apply_normalization_transforms");
    let program = Timer::time("skip_unreachable_node", || skip_unreachable_node(&program));
    let program = Timer::time("inline_fragments", || inline_fragments(&program));
    let program = Timer::time("inline_fragments", || flatten(&program, true));
    Timer::time("validate_module_conflicts", || {
        validate_module_conflicts(&program)
    })?;
    let program = Timer::time("skip_redundant_nodes", || skip_redundant_nodes(&program));
    let program = Timer::time("client_extensions", || client_extensions(&program));

    let program = Timer::time("generate_typename", || generate_typename(&program));

    Ok(program)
}

/// After the operation transforms, this applies further transforms that only
/// apply to the printed operation text.
///
/// Corresponds to the "print transforms" in the JS compiler
fn apply_operation_text_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // + SkipSplitOperationTransform
    // - ClientExtensionsTransform
    // + SkipClientExtensionsTransform
    // + SkipUnreachableNodeTransform
    // + FlattenTransform, flattenAbstractTypes: false
    // + GenerateTypeNameTransform
    // - SkipHandleFieldTransform
    // - FilterDirectivesTransform
    // - SkipUnusedVariablesTransform
    // - ValidateRequiredArgumentsTransform
    println!("apply_operation_text_transforms");
    let program = Timer::time("skip_split_operation", || skip_split_operation(&program));
    let program = Timer::time("skip_client_extensions", || {
        skip_client_extensions(&program)
    });
    let program = Timer::time("skip_unreachable_node", || skip_unreachable_node(&program));
    let program = Timer::time("flatten", || flatten(&program, false));

    Timer::time("generate_typename", || generate_typename(&program))
}

fn apply_typegen_transforms<'schema>(
    program: &Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
) -> Program<'schema> {
    // JS compiler
    // - RelayDirectiveTransform,
    // - MaskTransform
    // - MatchTransform
    // + FlattenTransform, flattenAbstractTypes: false
    // - RefetchableFragmentTransform,
    println!("apply_typegen_transforms");
    let program = Timer::time("remove_base_fragments", || {
        remove_base_fragments(&program, base_fragment_names)
    });

    Timer::time("flatten", || flatten(&program, false))
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate criterion;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate named_type_derive;

#[macro_use]
extern crate derivative;

#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate serde_json;

extern crate byteorder;
extern crate indy;
extern crate indy_crypto;
extern crate uuid;
extern crate named_type;
extern crate rmp_serde;
extern crate rust_base58;
extern crate time;
extern crate serde;
extern crate rand;

// Workaround to share some utils code based on indy sdk types between tests and indy sdk
use indy::api as api;

#[path = "../tests/utils/mod.rs"]
#[macro_use]
mod utils;

use utils::wallet::WalletUtils;
use utils::non_secrets::NonSecretsUtils;
use utils::test::TestUtils;
use utils::constants::*;

use criterion::{Criterion, Benchmark, ParameterizedBenchmark};

use utils::sequence::SequenceUtils;
use rand::Rng;

mod create {
    use super::*;

    fn setup() {
        TestUtils::cleanup_storage();
    }

    fn create_wallet(credentials: &str) {
        WalletUtils::create_wallet(DEFAULT_WALLET_CONFIG, credentials).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        c.bench(
            "wallet_create",
            ParameterizedBenchmark::new(
                "wallet_create",
                |b, credentials| b.iter_with_setup(setup, |()| create_wallet(credentials)),
                vec![WALLET_CREDENTIALS_ARGON2I_MOD, WALLET_CREDENTIALS_ARGON2I_INT, WALLET_CREDENTIALS_RAW],
            ).sample_size(10),
        );
    }
}

mod open {
    use super::*;
    use utils::sequence::SequenceUtils;

    pub static mut WALLET_HANDLE: i32 = 0;

    pub const WALLET_CONFIG_ARGON2I_MOD: &'static str = r#"{"id":"wallet_open_ARGON2I_MOD"}"#;
    pub const WALLET_CONFIG_ARGON2I_INT: &'static str = r#"{"id":"wallet_open_ARGON2I_INT"}"#;
    pub const WALLET_CONFIG_RAW: &'static str = r#"{"id":"wallet_open_RAW"}"#;

    fn pre_setup() {
        TestUtils::cleanup_storage();

        WalletUtils::create_wallet(WALLET_CONFIG_ARGON2I_MOD, WALLET_CREDENTIALS_ARGON2I_MOD).unwrap();
        WalletUtils::create_wallet(WALLET_CONFIG_ARGON2I_INT, WALLET_CREDENTIALS_ARGON2I_INT).unwrap();
        WalletUtils::create_wallet(WALLET_CONFIG_RAW, WALLET_CREDENTIALS_RAW).unwrap();
    }

    fn setup<'a>(params: &'a (&'a str, &'a str)) -> &'a (&'a str, &'a str) {
        unsafe { if WALLET_HANDLE != 0 { WalletUtils::close_wallet(WALLET_HANDLE).unwrap(); } }
        params
    }

    fn open_wallet(config: &str, credentials: &str) {
        unsafe { WALLET_HANDLE = WalletUtils::open_wallet(config, credentials).unwrap(); }
    }

    pub fn bench(c: &mut Criterion) {
        pre_setup();

        c.bench(
            "wallet_open",
            ParameterizedBenchmark::new(
                "wallet_open",
                |b, params| b.iter_with_setup(|| setup(params), |(config, credentials)| open_wallet(config, credentials)),
                vec![(WALLET_CONFIG_ARGON2I_MOD, WALLET_CREDENTIALS_ARGON2I_MOD),
                     (WALLET_CONFIG_ARGON2I_INT, WALLET_CREDENTIALS_ARGON2I_INT),
                     (WALLET_CONFIG_RAW, WALLET_CREDENTIALS_RAW)],
            ).sample_size(10),
        );
    }
}

mod close {
    use super::*;

    pub const WALLET_CONFIG_ARGON2I_MOD: &'static str = r#"{"id":"wallet_close_ARGON2I_MOD"}"#;
    pub const WALLET_CONFIG_ARGON2I_INT: &'static str = r#"{"id":"wallet_close_ARGON2I_INT"}"#;
    pub const WALLET_CONFIG_RAW: &'static str = r#"{"id":"wallet_close_RAW"}"#;

    fn pre_setup() {
        TestUtils::cleanup_storage();

        WalletUtils::create_wallet(WALLET_CONFIG_ARGON2I_MOD, WALLET_CREDENTIALS_ARGON2I_MOD).unwrap();
        WalletUtils::create_wallet(WALLET_CONFIG_ARGON2I_INT, WALLET_CREDENTIALS_ARGON2I_INT).unwrap();
        WalletUtils::create_wallet(WALLET_CONFIG_RAW, WALLET_CREDENTIALS_RAW).unwrap();
    }

    fn setup<'a>(params: &'a (&'a str, &'a str)) -> i32 {
        let (config, credentials) = params;
        WalletUtils::open_wallet(config, credentials).unwrap()
    }

    fn close_wallet(handle: i32) {
        WalletUtils::close_wallet(handle).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        pre_setup();

        c.bench(
            "wallet_close",
            ParameterizedBenchmark::new(
                "wallet_close",
                |b, params| b.iter_with_setup(|| setup(params), |handle| close_wallet(handle)),
                vec![(WALLET_CONFIG_ARGON2I_MOD, WALLET_CREDENTIALS_ARGON2I_MOD),
                     (WALLET_CONFIG_ARGON2I_INT, WALLET_CREDENTIALS_ARGON2I_INT),
                     (WALLET_CONFIG_RAW, WALLET_CREDENTIALS_RAW)],
            ).sample_size(10),
        );
    }
}

mod delete {
    use super::*;

    fn pre_setup() {
        TestUtils::cleanup_storage();
    }

    fn setup(credentials: &str) {
        WalletUtils::create_wallet(DEFAULT_WALLET_CONFIG, credentials).unwrap();
    }

    fn delete_wallet(credentials: &str) {
        WalletUtils::delete_wallet(DEFAULT_WALLET_CONFIG, credentials).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        pre_setup();

        c.bench(
            "wallet_delete",
            ParameterizedBenchmark::new(
                "wallet_delete",
                |b, credentials| b.iter_with_setup(|| setup(credentials), |()| delete_wallet(credentials)),
                vec![WALLET_CREDENTIALS_ARGON2I_MOD, WALLET_CREDENTIALS_ARGON2I_INT, WALLET_CREDENTIALS_RAW],
            ).sample_size(10),
        );
    }
}

mod get_record {
    use super::*;

    fn get_record(wallet_handle: i32, type_: &str, id: &str) {
        NonSecretsUtils::get_wallet_record(wallet_handle, type_, id, "{}").unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        c.bench(
            "wallet_get_record",
            Benchmark::new("wallet_get_record", move |b|
                b.iter_with_setup(get_rand_key, |(type_, id): (String, String)| get_record(wallet_handle, &type_, &id)))
                .sample_size(50));
    }
}

mod delete_record {
    use super::*;

    static mut INDEX: usize = 0;

    fn setup() -> (String, String) {
        unsafe {
            INDEX = INDEX + 1;
            (_type(INDEX), _id(INDEX))
        }
    }

    fn delete_record(wallet_handle: i32, type_: &str, id: &str) {
        NonSecretsUtils::delete_wallet_record(wallet_handle, type_, id).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        c.bench(
            "wallet_delete_record",
            Benchmark::new("wallet_delete_record", move |b|
                b.iter_with_setup(setup, |(type_, id): (String, String)| delete_record(wallet_handle, &type_, &id)))
                .sample_size(10));
    }
}

mod add_record {
    use super::*;

    static mut INDEX: usize = COUNT;

    fn setup() -> (String, String, String, String) {
        unsafe {
            INDEX = INDEX + 1;
            (_type(INDEX), _id(INDEX), _value(INDEX), _tags(INDEX))
        }
    }

    fn add_record(wallet_handle: i32, type_: &str, id: &str, value: &str, tags: &str) {
        NonSecretsUtils::add_wallet_record(wallet_handle, type_, id, value, Some(tags)).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        c.bench(
            "wallet_add_record",
            Benchmark::new("wallet_add_record", move |b|
                b.iter_with_setup(
                    setup, |(type_, id, value, tags): (String, String, String, String)|
                        add_record(wallet_handle, &type_, &id, &value, &tags)))
                .sample_size(10));
    }
}

mod add_record_tags {
    use super::*;

    fn setup() -> (String, String, String) {
        let (type_, id) = get_rand_key();
        (type_, id, r#"{"tag_1": "value_1", "~tag_2": "value_2"}"#.to_string())
    }

    fn add_record_tags(wallet_handle: i32, type_: &str, id: &str, tags: &str) {
        NonSecretsUtils::add_wallet_record_tags(wallet_handle, type_, id, tags).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        c.bench(
            "wallet_add_record_tags",
            Benchmark::new("wallet_add_record_tags", move |b|
                b.iter_with_setup(
                    setup,
                    |(type_, id, tags): (String, String, String)| add_record_tags(wallet_handle, &type_, &id, &tags)))
                .sample_size(10));
    }
}

mod delete_record_tags {
    use super::*;

    fn setup() -> (String, String, String) {
        let (type_, id) = get_rand_key();
        (type_, id, r#"["tag_id_1"]"#.to_string())
    }

    fn delete_record_tags(wallet_handle: i32, type_: &str, id: &str, tag_names: &str) {
        NonSecretsUtils::delete_wallet_record_tags(wallet_handle, type_, id, tag_names).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        c.bench(
            "wallet_delete_record_tags",
            Benchmark::new("wallet_delete_record_tags", move |b|
                b.iter_with_setup(
                    setup,
                    |(type_, id, tag_names): (String, String, String)| delete_record_tags(wallet_handle, &type_, &id, &tag_names)))
                .sample_size(10));
    }
}

mod search_records {
    use super::*;

    fn open_search(wallet_handle: i32, query: &str) {
        NonSecretsUtils::open_wallet_search(wallet_handle, TYPE_1, query, "{}").unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        let queries = vec![
            r#"{}"#,
            r#"{
                "tag_id_1": "tag_value_10_1"
            }"#,
            r#"{
                "~tag_id_3": {
                    "$gt": "30"
                }
            }"#,
            r#"{
                "tag_id_1": {
                    "$in": ["tag_value_10_1", "tag_value_11_1", "tag_value_70_1", "tag_value_71_1"]
                }
            }"#,
            r#"{
                "tag_id_1": "tag_value_11_1",
                "~tag_id_3": "10"
            }"#,
            r#"{
                "$or": [
                    {"tag_id_1": "tag_value_11_1"},
                    {"tag_id_3": "90"}
                ]
            }"#
        ];

        c.bench(
            "wallet_search",
            ParameterizedBenchmark::new(
                "wallet_search",
                move |b, query| b.iter(|| open_search(wallet_handle, query)),
                queries,
            ).sample_size(10),
        );
    }
}

pub const COUNT: usize = 1000;
pub const TYPE_1: &'static str = "type_1";
pub const TYPE_2: &'static str = "type_2";

fn _type(suffix: usize) -> String {
    if suffix % 2 != 0 { TYPE_1.to_string() } else { TYPE_2.to_string() }
}

fn _id(suffix: usize) -> String { format!("id_{}", suffix) }

fn _value(suffix: usize) -> String {
    format!("value_{}", suffix)
}

fn _tags(suffix: usize) -> String {
    json!({
            "tag_id_1":  format!("tag_value_{}_1", suffix),
            "tag_id_2":  format!("tag_value_{}_2", suffix),
            "~tag_id_3":  format!("{}", suffix),
        }).to_string()
}

fn add_records(wallet_handle: i32) {
    for i in 0..COUNT {
        NonSecretsUtils::add_wallet_record(wallet_handle,
                                           &_type(i),
                                           &_id(i),
                                           &_value(i),
                                           Some(&_tags(i))).unwrap();
    }
}

fn init_wallet() -> i32 {
    TestUtils::cleanup_storage();

    let config = json!({
            "id": format!("default-wallet_id-{}", SequenceUtils::get_next_id())
        }).to_string();

    WalletUtils::create_wallet(&config, WALLET_CREDENTIALS_RAW).unwrap();
    let wallet_handle = WalletUtils::open_wallet(&config, WALLET_CREDENTIALS_RAW).unwrap();

    add_records(wallet_handle);

    wallet_handle
}

fn get_rand_key() -> (String, String) {
    let i = rand::thread_rng().gen_range(0, COUNT);
    (_type(i), _id(i))
}

criterion_group!(benches, create::bench,
                          open::bench,
                          close::bench,
                          delete::bench,
                          get_record::bench,
                          delete_record::bench,
                          add_record::bench,
                          add_record_tags::bench,
                          delete_record_tags::bench,
                          search_records::bench);
criterion_main!(benches);<commit_msg>use separated benchmarks instead of parametrized benchmarks<commit_after>#[macro_use]
extern crate criterion;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate named_type_derive;

#[macro_use]
extern crate derivative;

#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate serde_json;

extern crate byteorder;
extern crate indy;
extern crate indy_crypto;
extern crate uuid;
extern crate named_type;
extern crate rmp_serde;
extern crate rust_base58;
extern crate time;
extern crate serde;
extern crate rand;

// Workaround to share some utils code based on indy sdk types between tests and indy sdk
use indy::api as api;

#[path = "../tests/utils/mod.rs"]
#[macro_use]
mod utils;

use utils::wallet::WalletUtils;
use utils::non_secrets::NonSecretsUtils;
use utils::test::TestUtils;
use utils::constants::*;

use criterion::{Criterion, Benchmark, ParameterizedBenchmark};

use utils::sequence::SequenceUtils;
use rand::Rng;

mod create {
    use super::*;

    fn setup() {
        TestUtils::cleanup_storage();
    }

    fn create_wallet(credentials: &str) {
        WalletUtils::create_wallet(DEFAULT_WALLET_CONFIG, credentials).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        c.bench(
            "wallet_create",
            Benchmark::new(
                "wallet_create_argon2i_mod",
                |b| b.iter_with_setup(setup, |()| create_wallet(WALLET_CREDENTIALS_ARGON2I_MOD))
            ).sample_size(10),
        );

        c.bench(
            "wallet_create",
            Benchmark::new(
                "wallet_create_argon2i_int",
                |b| b.iter_with_setup(setup, |()| create_wallet(WALLET_CREDENTIALS_ARGON2I_INT))
            ).sample_size(20),
        );

        c.bench(
            "wallet_create",
            Benchmark::new(
                "wallet_create_raw",
                |b| b.iter_with_setup(setup, |()| create_wallet(WALLET_CREDENTIALS_RAW))
            ).sample_size(50),
        );
    }
}

mod open {
    use super::*;
    use utils::sequence::SequenceUtils;

    pub static mut WALLET_HANDLE: i32 = 0;

    pub const WALLET_CONFIG_ARGON2I_MOD: &'static str = r#"{"id":"wallet_open_ARGON2I_MOD"}"#;
    pub const WALLET_CONFIG_ARGON2I_INT: &'static str = r#"{"id":"wallet_open_ARGON2I_INT"}"#;
    pub const WALLET_CONFIG_RAW: &'static str = r#"{"id":"wallet_open_RAW"}"#;

    fn pre_setup() {
        TestUtils::cleanup_storage();

        WalletUtils::create_wallet(WALLET_CONFIG_ARGON2I_MOD, WALLET_CREDENTIALS_ARGON2I_MOD).unwrap();
        WalletUtils::create_wallet(WALLET_CONFIG_ARGON2I_INT, WALLET_CREDENTIALS_ARGON2I_INT).unwrap();
        WalletUtils::create_wallet(WALLET_CONFIG_RAW, WALLET_CREDENTIALS_RAW).unwrap();
    }

    fn setup(config: &str, credentials: &str) {
        unsafe { if WALLET_HANDLE != 0 { WalletUtils::close_wallet(WALLET_HANDLE).unwrap(); } }
    }

    fn open_wallet(config: &str, credentials: &str) {
        unsafe { WALLET_HANDLE = WalletUtils::open_wallet(config, credentials).unwrap(); }
    }

    pub fn bench(c: &mut Criterion) {
        pre_setup();

        c.bench(
            "wallet_open",
            Benchmark::new(
                "wallet_open_argon2i_mod",
                |b| b.iter_with_setup(|| setup(WALLET_CONFIG_ARGON2I_MOD, WALLET_CREDENTIALS_ARGON2I_MOD), |()| open_wallet(WALLET_CONFIG_ARGON2I_MOD, WALLET_CREDENTIALS_ARGON2I_MOD))
            ).sample_size(10),
        );

        c.bench(
            "wallet_open",
            Benchmark::new(
                "wallet_open_argon2i_mod",
                |b| b.iter_with_setup(|| setup(WALLET_CONFIG_ARGON2I_INT, WALLET_CREDENTIALS_ARGON2I_INT), |()| open_wallet(WALLET_CONFIG_ARGON2I_INT, WALLET_CREDENTIALS_ARGON2I_INT))
            ).sample_size(20),
        );

        c.bench(
            "wallet_open",
            Benchmark::new(
                "wallet_open_raw",
                |b| b.iter_with_setup(|| setup(WALLET_CONFIG_RAW, WALLET_CREDENTIALS_RAW), |()| open_wallet(WALLET_CONFIG_RAW, WALLET_CREDENTIALS_RAW))
            ).sample_size(50),
        );
    }
}

mod close {
    use super::*;

    pub const WALLET_CONFIG_ARGON2I_MOD: &'static str = r#"{"id":"wallet_close_ARGON2I_MOD"}"#;
    pub const WALLET_CONFIG_ARGON2I_INT: &'static str = r#"{"id":"wallet_close_ARGON2I_INT"}"#;
    pub const WALLET_CONFIG_RAW: &'static str = r#"{"id":"wallet_close_RAW"}"#;

    fn pre_setup() {
        TestUtils::cleanup_storage();

        WalletUtils::create_wallet(WALLET_CONFIG_ARGON2I_MOD, WALLET_CREDENTIALS_ARGON2I_MOD).unwrap();
        WalletUtils::create_wallet(WALLET_CONFIG_ARGON2I_INT, WALLET_CREDENTIALS_ARGON2I_INT).unwrap();
        WalletUtils::create_wallet(WALLET_CONFIG_RAW, WALLET_CREDENTIALS_RAW).unwrap();
    }

    fn setup(config: &str, credentials: &str) -> i32 {
        WalletUtils::open_wallet(config, credentials).unwrap()
    }

    fn close_wallet(handle: i32) {
        WalletUtils::close_wallet(handle).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        pre_setup();

        c.bench(
            "wallet_close",
            Benchmark::new(
                "wallet_close_argon2i_mod",
                |b| b.iter_with_setup(|| setup(WALLET_CONFIG_ARGON2I_MOD, WALLET_CREDENTIALS_ARGON2I_MOD), |handle| close_wallet(handle)),
            ).sample_size(10),
        );

        c.bench(
            "wallet_close",
            Benchmark::new(
                "wallet_close_argon2i_int",
                |b| b.iter_with_setup(|| setup(WALLET_CONFIG_ARGON2I_INT, WALLET_CREDENTIALS_ARGON2I_INT), |handle| close_wallet(handle)),
            ).sample_size(20),
        );

        c.bench(
            "wallet_close",
            Benchmark::new(
                "wallet_close_argon2i_mod",
                |b| b.iter_with_setup(|| setup(WALLET_CONFIG_RAW, WALLET_CREDENTIALS_RAW), |handle| close_wallet(handle)),
            ).sample_size(50),
        );
    }
}

mod delete {
    use super::*;

    fn pre_setup() {
        TestUtils::cleanup_storage();
    }

    fn setup(credentials: &str) {
        WalletUtils::create_wallet(DEFAULT_WALLET_CONFIG, credentials).unwrap();
    }

    fn delete_wallet(credentials: &str) {
        WalletUtils::delete_wallet(DEFAULT_WALLET_CONFIG, credentials).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        pre_setup();

        c.bench(
            "wallet_delete",
            Benchmark::new(
                "wallet_delete_argon2i_mod",
                |b| b.iter_with_setup(|| setup(WALLET_CREDENTIALS_ARGON2I_MOD), |()| delete_wallet(WALLET_CREDENTIALS_ARGON2I_MOD)),
            ).sample_size(10),
        );

        c.bench(
            "wallet_delete",
            Benchmark::new(
                "wallet_delete_argon2i_int",
                |b| b.iter_with_setup(|| setup(WALLET_CREDENTIALS_ARGON2I_INT), |()| delete_wallet(WALLET_CREDENTIALS_ARGON2I_INT)),
            ).sample_size(20),
        );

        c.bench(
            "wallet_delete",
            Benchmark::new(
                "wallet_delete_raw",
                |b| b.iter_with_setup(|| setup(WALLET_CREDENTIALS_RAW), |()| delete_wallet(WALLET_CREDENTIALS_RAW)),
            ).sample_size(50),
        );
    }
}

mod get_record {
    use super::*;

    fn get_record(wallet_handle: i32, type_: &str, id: &str) {
        NonSecretsUtils::get_wallet_record(wallet_handle, type_, id, "{}").unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        c.bench(
            "wallet_get_record",
            Benchmark::new("wallet_get_record", move |b|
                b.iter_with_setup(get_rand_key, |(type_, id): (String, String)| get_record(wallet_handle, &type_, &id)))
                .sample_size(50));
    }
}

mod delete_record {
    use super::*;

    static mut INDEX: usize = 0;

    fn setup() -> (String, String) {
        unsafe {
            INDEX = INDEX + 1;
            (_type(INDEX), _id(INDEX))
        }
    }

    fn delete_record(wallet_handle: i32, type_: &str, id: &str) {
        NonSecretsUtils::delete_wallet_record(wallet_handle, type_, id).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        c.bench(
            "wallet_delete_record",
            Benchmark::new("wallet_delete_record", move |b|
                b.iter_with_setup(setup, |(type_, id): (String, String)| delete_record(wallet_handle, &type_, &id)))
                .sample_size(10));
    }
}

mod add_record {
    use super::*;

    static mut INDEX: usize = COUNT;

    fn setup() -> (String, String, String, String) {
        unsafe {
            INDEX = INDEX + 1;
            (_type(INDEX), _id(INDEX), _value(INDEX), _tags(INDEX))
        }
    }

    fn add_record(wallet_handle: i32, type_: &str, id: &str, value: &str, tags: &str) {
        NonSecretsUtils::add_wallet_record(wallet_handle, type_, id, value, Some(tags)).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        c.bench(
            "wallet_add_record",
            Benchmark::new("wallet_add_record", move |b|
                b.iter_with_setup(
                    setup, |(type_, id, value, tags): (String, String, String, String)|
                        add_record(wallet_handle, &type_, &id, &value, &tags)))
                .sample_size(10));
    }
}

mod add_record_tags {
    use super::*;

    fn setup() -> (String, String, String) {
        let (type_, id) = get_rand_key();
        (type_, id, r#"{"tag_1": "value_1", "~tag_2": "value_2"}"#.to_string())
    }

    fn add_record_tags(wallet_handle: i32, type_: &str, id: &str, tags: &str) {
        NonSecretsUtils::add_wallet_record_tags(wallet_handle, type_, id, tags).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        c.bench(
            "wallet_add_record_tags",
            Benchmark::new("wallet_add_record_tags", move |b|
                b.iter_with_setup(
                    setup,
                    |(type_, id, tags): (String, String, String)| add_record_tags(wallet_handle, &type_, &id, &tags)))
                .sample_size(10));
    }
}

mod delete_record_tags {
    use super::*;

    fn setup() -> (String, String, String) {
        let (type_, id) = get_rand_key();
        (type_, id, r#"["tag_id_1"]"#.to_string())
    }

    fn delete_record_tags(wallet_handle: i32, type_: &str, id: &str, tag_names: &str) {
        NonSecretsUtils::delete_wallet_record_tags(wallet_handle, type_, id, tag_names).unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        c.bench(
            "wallet_delete_record_tags",
            Benchmark::new("wallet_delete_record_tags", move |b|
                b.iter_with_setup(
                    setup,
                    |(type_, id, tag_names): (String, String, String)| delete_record_tags(wallet_handle, &type_, &id, &tag_names)))
                .sample_size(10));
    }
}

mod search_records {
    use super::*;

    fn open_search(wallet_handle: i32, query: &str) {
        NonSecretsUtils::open_wallet_search(wallet_handle, TYPE_1, query, "{}").unwrap();
    }

    pub fn bench(c: &mut Criterion) {
        let wallet_handle = init_wallet();

        let query = r#"{}"#;

        c.bench(
            "wallet_search",
            Benchmark::new(
                "wallet_search_empty",
                move |b| b.iter(|| open_search(wallet_handle, r#"{}"#)),
            ).sample_size(20),
        );

        let query = r#"{
            "tag_id_1": "tag_value_10_1"
        }"#;

        c.bench(
            "wallet_search",
            Benchmark::new(
                "wallet_search_eq",
                move |b| b.iter(|| open_search(wallet_handle, query)),
            ).sample_size(20),
        );

        let query = r#"{
            "~tag_id_3": {
                "$gt": "30"
            }
        }"#;

        c.bench(
            "wallet_search",
            Benchmark::new(
                "wallet_search_gt",
                move |b| b.iter(|| open_search(wallet_handle, query)),
            ).sample_size(20),
        );

        let query = r#"{
                    "tag_id_1": {
                        "$in": ["tag_value_10_1", "tag_value_11_1", "tag_value_70_1", "tag_value_71_1"]
                    }
                }"#;

        c.bench(
            "wallet_search",
            Benchmark::new(
                "wallet_search_in",
                move |b| b.iter(|| open_search(wallet_handle, query)),
            ).sample_size(20),
        );

        let query = r#"{
            "tag_id_1": "tag_value_11_1",
            "~tag_id_3": "10"
        }"#;

        c.bench(
            "wallet_search",
            Benchmark::new(
                "wallet_search_and",
                move |b| b.iter(|| open_search(wallet_handle, query)),
            ).sample_size(20),
        );

        let query = r#"{
            "$or": [
                {"tag_id_1": "tag_value_11_1"},
                {"tag_id_3": "90"}
            ]
        }"#;

        c.bench(
            "wallet_search",
            Benchmark::new(
                "wallet_search_or",
                move |b| b.iter(|| open_search(wallet_handle, query)),
            ).sample_size(20),
        );
    }
}

pub const COUNT: usize = 1000;
pub const TYPE_1: &'static str = "type_1";
pub const TYPE_2: &'static str = "type_2";

fn _type(suffix: usize) -> String {
    if suffix % 2 != 0 { TYPE_1.to_string() } else { TYPE_2.to_string() }
}

fn _id(suffix: usize) -> String { format!("id_{}", suffix) }

fn _value(suffix: usize) -> String {
    format!("value_{}", suffix)
}

fn _tags(suffix: usize) -> String {
    json!({
            "tag_id_1":  format!("tag_value_{}_1", suffix),
            "tag_id_2":  format!("tag_value_{}_2", suffix),
            "~tag_id_3":  format!("{}", suffix),
        }).to_string()
}

fn add_records(wallet_handle: i32) {
    for i in 0..COUNT {
        NonSecretsUtils::add_wallet_record(wallet_handle,
                                           &_type(i),
                                           &_id(i),
                                           &_value(i),
                                           Some(&_tags(i))).unwrap();
    }
}

fn init_wallet() -> i32 {
    TestUtils::cleanup_storage();

    let config = json!({
            "id": format!("default-wallet_id-{}", SequenceUtils::get_next_id())
        }).to_string();

    WalletUtils::create_wallet(&config, WALLET_CREDENTIALS_RAW).unwrap();
    let wallet_handle = WalletUtils::open_wallet(&config, WALLET_CREDENTIALS_RAW).unwrap();

    add_records(wallet_handle);

    wallet_handle
}

fn get_rand_key() -> (String, String) {
    let i = rand::thread_rng().gen_range(0, COUNT);
    (_type(i), _id(i))
}

criterion_group!(benches, create::bench,
                          open::bench,
                          close::bench,
                          delete::bench,
                          get_record::bench,
                          delete_record::bench,
                          add_record::bench,
                          add_record_tags::bench,
                          delete_record_tags::bench,
                          search_records::bench);
criterion_main!(benches);<|endoftext|>


<commit_before>//! Standard library macros
//!
//! This module contains a set of macros which are exported from the standard
//! library. Each macro is available for use when linking against the standard
//! library.

#[doc(include = "../../core/src/macros/panic.md")]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(libstd_sys_internals)]
macro_rules! panic {
    () => ({ $crate::panic!("explicit panic") });
    ($msg:expr) => ({ $crate::rt::begin_panic($msg) });
    ($msg:expr,) => ({ $crate::panic!($msg) });
    ($fmt:expr, $($arg:tt)+) => ({
        $crate::rt::begin_panic_fmt(&$crate::format_args!($fmt, $($arg)+))
    });
}

/// Prints to the standard output.
///
/// Equivalent to the [`println!`] macro except that a newline is not printed at
/// the end of the message.
///
/// Note that stdout is frequently line-buffered by default so it may be
/// necessary to use [`io::stdout().flush()`][flush] to ensure the output is emitted
/// immediately.
///
/// Use `print!` only for the primary output of your program. Use
/// [`eprint!`] instead to print error and progress messages.
///
/// [flush]: crate::io::Write::flush
///
/// # Panics
///
/// Panics if writing to `io::stdout()` fails.
///
/// # Examples
///
/// ```
/// use std::io::{self, Write};
///
/// print!("this ");
/// print!("will ");
/// print!("be ");
/// print!("on ");
/// print!("the ");
/// print!("same ");
/// print!("line ");
///
/// io::stdout().flush().unwrap();
///
/// print!("this string has a newline, why not choose println! instead?\n");
///
/// io::stdout().flush().unwrap();
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals)]
macro_rules! print {
    ($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*)));
}

/// Prints to the standard output, with a newline.
///
/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
/// (no additional CARRIAGE RETURN (`\r`/`U+000D`)).
///
/// Use the [`format!`] syntax to write data to the standard output.
/// See [`std::fmt`] for more information.
///
/// Use `println!` only for the primary output of your program. Use
/// [`eprintln!`] instead to print error and progress messages.
///
/// # Panics
///
/// Panics if writing to `io::stdout` fails.
///
/// [`io::stdout`]: crate::io::stdout
///
/// # Examples
///
/// ```
/// println!(); // prints just a newline
/// println!("hello there!");
/// println!("format {} arguments", "some");
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! println {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ({
        $crate::io::_print($crate::format_args_nl!($($arg)*));
    })
}

/// Prints to the standard error.
///
/// Equivalent to the [`print!`] macro, except that output goes to
/// [`io::stderr`] instead of `io::stdout`. See [`print!`] for
/// example usage.
///
/// Use `eprint!` only for error and progress messages. Use `print!`
/// instead for the primary output of your program.
///
/// [`io::stderr`]: crate::io::stderr
/// [`io::stdout`]: crate::io::stdout
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Examples
///
/// ```
/// eprint!("Error: Could not complete task");
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable(print_internals)]
macro_rules! eprint {
    ($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*)));
}

/// Prints to the standard error, with a newline.
///
/// Equivalent to the [`println!`] macro, except that output goes to
/// [`io::stderr`] instead of `io::stdout`. See [`println!`] for
/// example usage.
///
/// Use `eprintln!` only for error and progress messages. Use `println!`
/// instead for the primary output of your program.
///
/// [`io::stderr`]: crate::io::stderr
/// [`io::stdout`]: crate::io::stdout
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Examples
///
/// ```
/// eprintln!("Error: Could not complete task");
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! eprintln {
    () => ($crate::eprint!("\n"));
    ($($arg:tt)*) => ({
        $crate::io::_eprint($crate::format_args_nl!($($arg)*));
    })
}

/// Prints and returns the value of a given expression for quick and dirty
/// debugging.
///
/// An example:
///
/// ```rust
/// let a = 2;
/// let b = dbg!(a * 2) + 1;
/// //      ^-- prints: [src/main.rs:2] a * 2 = 4
/// assert_eq!(b, 5);
/// ```
///
/// The macro works by using the `Debug` implementation of the type of
/// the given expression to print the value to [stderr] along with the
/// source location of the macro invocation as well as the source code
/// of the expression.
///
/// Invoking the macro on an expression moves and takes ownership of it
/// before returning the evaluated expression unchanged. If the type
/// of the expression does not implement `Copy` and you don't want
/// to give up ownership, you can instead borrow with `dbg!(&expr)`
/// for some expression `expr`.
///
/// The `dbg!` macro works exactly the same in release builds.
/// This is useful when debugging issues that only occur in release
/// builds or when debugging in release mode is significantly faster.
///
/// Note that the macro is intended as a debugging tool and therefore you
/// should avoid having uses of it in version control for long periods.
/// Use cases involving debug output that should be added to version control
/// are better served by macros such as [`debug!`] from the [`log`] crate.
///
/// # Stability
///
/// The exact output printed by this macro should not be relied upon
/// and is subject to future changes.
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Further examples
///
/// With a method call:
///
/// ```rust
/// fn foo(n: usize) {
///     if let Some(_) = dbg!(n.checked_sub(4)) {
///         // ...
///     }
/// }
///
/// foo(3)
/// ```
///
/// This prints to [stderr]:
///
/// ```text,ignore
/// [src/main.rs:4] n.checked_sub(4) = None
/// ```
///
/// Naive factorial implementation:
///
/// ```rust
/// fn factorial(n: u32) -> u32 {
///     if dbg!(n <= 1) {
///         dbg!(1)
///     } else {
///         dbg!(n * factorial(n - 1))
///     }
/// }
///
/// dbg!(factorial(4));
/// ```
///
/// This prints to [stderr]:
///
/// ```text,ignore
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = true
/// [src/main.rs:4] 1 = 1
/// [src/main.rs:5] n * factorial(n - 1) = 2
/// [src/main.rs:5] n * factorial(n - 1) = 6
/// [src/main.rs:5] n * factorial(n - 1) = 24
/// [src/main.rs:11] factorial(4) = 24
/// ```
///
/// The `dbg!(..)` macro moves the input:
///
/// ```compile_fail
/// /// A wrapper around `usize` which importantly is not Copyable.
/// #[derive(Debug)]
/// struct NoCopy(usize);
///
/// let a = NoCopy(42);
/// let _ = dbg!(a); // <-- `a` is moved here.
/// let _ = dbg!(a); // <-- `a` is moved again; error!
/// ```
///
/// You can also use `dbg!()` without a value to just print the
/// file and line whenever it's reached.
///
/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as
/// a tuple (and return it, too):
///
/// ```
/// assert_eq!(dbg!(1usize, 2u32), (1, 2));
/// ```
///
/// However, a single argument with a trailing comma will still not be treated
/// as a tuple, following the convention of ignoring trailing commas in macro
/// invocations. You can use a 1-tuple directly if you need one:
///
/// ```
/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored
/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple
/// ```
///
/// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)
/// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html
/// [`log`]: https://crates.io/crates/log
#[macro_export]
#[stable(feature = "dbg_macro", since = "1.32.0")]
macro_rules! dbg {
    () => {
        $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());
    };
    ($val:expr) => {
        // Use of `match` here is intentional because it affects the lifetimes
        // of temporaries - https://stackoverflow.com/a/48732525/1063961
        match $val {
            tmp => {
                $crate::eprintln!("[{}:{}] {} = {:#?}",
                    $crate::file!(), $crate::line!(), $crate::stringify!($val), &tmp);
                tmp
            }
        }
    };
    // Trailing comma with single argument is ignored
    ($val:expr,) => { $crate::dbg!($val) };
    ($($val:expr),+ $(,)?) => {
        ($($crate::dbg!($val)),+,)
    };
}

#[cfg(test)]
macro_rules! assert_approx_eq {
    ($a:expr, $b:expr) => {{
        let (a, b) = (&$a, &$b);
        assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
    }};
}
<commit_msg>Add missing intra-doc link<commit_after>//! Standard library macros
//!
//! This module contains a set of macros which are exported from the standard
//! library. Each macro is available for use when linking against the standard
//! library.

#[doc(include = "../../core/src/macros/panic.md")]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(libstd_sys_internals)]
macro_rules! panic {
    () => ({ $crate::panic!("explicit panic") });
    ($msg:expr) => ({ $crate::rt::begin_panic($msg) });
    ($msg:expr,) => ({ $crate::panic!($msg) });
    ($fmt:expr, $($arg:tt)+) => ({
        $crate::rt::begin_panic_fmt(&$crate::format_args!($fmt, $($arg)+))
    });
}

/// Prints to the standard output.
///
/// Equivalent to the [`println!`] macro except that a newline is not printed at
/// the end of the message.
///
/// Note that stdout is frequently line-buffered by default so it may be
/// necessary to use [`io::stdout().flush()`][flush] to ensure the output is emitted
/// immediately.
///
/// Use `print!` only for the primary output of your program. Use
/// [`eprint!`] instead to print error and progress messages.
///
/// [flush]: crate::io::Write::flush
///
/// # Panics
///
/// Panics if writing to `io::stdout()` fails.
///
/// # Examples
///
/// ```
/// use std::io::{self, Write};
///
/// print!("this ");
/// print!("will ");
/// print!("be ");
/// print!("on ");
/// print!("the ");
/// print!("same ");
/// print!("line ");
///
/// io::stdout().flush().unwrap();
///
/// print!("this string has a newline, why not choose println! instead?\n");
///
/// io::stdout().flush().unwrap();
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals)]
macro_rules! print {
    ($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*)));
}

/// Prints to the standard output, with a newline.
///
/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
/// (no additional CARRIAGE RETURN (`\r`/`U+000D`)).
///
/// Use the [`format!`] syntax to write data to the standard output.
/// See [`std::fmt`] for more information.
///
/// Use `println!` only for the primary output of your program. Use
/// [`eprintln!`] instead to print error and progress messages.
///
/// [`std::fmt`]: crate::fmt
///
/// # Panics
///
/// Panics if writing to `io::stdout` fails.
///
/// [`io::stdout`]: crate::io::stdout
///
/// # Examples
///
/// ```
/// println!(); // prints just a newline
/// println!("hello there!");
/// println!("format {} arguments", "some");
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! println {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ({
        $crate::io::_print($crate::format_args_nl!($($arg)*));
    })
}

/// Prints to the standard error.
///
/// Equivalent to the [`print!`] macro, except that output goes to
/// [`io::stderr`] instead of `io::stdout`. See [`print!`] for
/// example usage.
///
/// Use `eprint!` only for error and progress messages. Use `print!`
/// instead for the primary output of your program.
///
/// [`io::stderr`]: crate::io::stderr
/// [`io::stdout`]: crate::io::stdout
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Examples
///
/// ```
/// eprint!("Error: Could not complete task");
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable(print_internals)]
macro_rules! eprint {
    ($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*)));
}

/// Prints to the standard error, with a newline.
///
/// Equivalent to the [`println!`] macro, except that output goes to
/// [`io::stderr`] instead of `io::stdout`. See [`println!`] for
/// example usage.
///
/// Use `eprintln!` only for error and progress messages. Use `println!`
/// instead for the primary output of your program.
///
/// [`io::stderr`]: crate::io::stderr
/// [`io::stdout`]: crate::io::stdout
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Examples
///
/// ```
/// eprintln!("Error: Could not complete task");
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! eprintln {
    () => ($crate::eprint!("\n"));
    ($($arg:tt)*) => ({
        $crate::io::_eprint($crate::format_args_nl!($($arg)*));
    })
}

/// Prints and returns the value of a given expression for quick and dirty
/// debugging.
///
/// An example:
///
/// ```rust
/// let a = 2;
/// let b = dbg!(a * 2) + 1;
/// //      ^-- prints: [src/main.rs:2] a * 2 = 4
/// assert_eq!(b, 5);
/// ```
///
/// The macro works by using the `Debug` implementation of the type of
/// the given expression to print the value to [stderr] along with the
/// source location of the macro invocation as well as the source code
/// of the expression.
///
/// Invoking the macro on an expression moves and takes ownership of it
/// before returning the evaluated expression unchanged. If the type
/// of the expression does not implement `Copy` and you don't want
/// to give up ownership, you can instead borrow with `dbg!(&expr)`
/// for some expression `expr`.
///
/// The `dbg!` macro works exactly the same in release builds.
/// This is useful when debugging issues that only occur in release
/// builds or when debugging in release mode is significantly faster.
///
/// Note that the macro is intended as a debugging tool and therefore you
/// should avoid having uses of it in version control for long periods.
/// Use cases involving debug output that should be added to version control
/// are better served by macros such as [`debug!`] from the [`log`] crate.
///
/// # Stability
///
/// The exact output printed by this macro should not be relied upon
/// and is subject to future changes.
///
/// # Panics
///
/// Panics if writing to `io::stderr` fails.
///
/// # Further examples
///
/// With a method call:
///
/// ```rust
/// fn foo(n: usize) {
///     if let Some(_) = dbg!(n.checked_sub(4)) {
///         // ...
///     }
/// }
///
/// foo(3)
/// ```
///
/// This prints to [stderr]:
///
/// ```text,ignore
/// [src/main.rs:4] n.checked_sub(4) = None
/// ```
///
/// Naive factorial implementation:
///
/// ```rust
/// fn factorial(n: u32) -> u32 {
///     if dbg!(n <= 1) {
///         dbg!(1)
///     } else {
///         dbg!(n * factorial(n - 1))
///     }
/// }
///
/// dbg!(factorial(4));
/// ```
///
/// This prints to [stderr]:
///
/// ```text,ignore
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = false
/// [src/main.rs:3] n <= 1 = true
/// [src/main.rs:4] 1 = 1
/// [src/main.rs:5] n * factorial(n - 1) = 2
/// [src/main.rs:5] n * factorial(n - 1) = 6
/// [src/main.rs:5] n * factorial(n - 1) = 24
/// [src/main.rs:11] factorial(4) = 24
/// ```
///
/// The `dbg!(..)` macro moves the input:
///
/// ```compile_fail
/// /// A wrapper around `usize` which importantly is not Copyable.
/// #[derive(Debug)]
/// struct NoCopy(usize);
///
/// let a = NoCopy(42);
/// let _ = dbg!(a); // <-- `a` is moved here.
/// let _ = dbg!(a); // <-- `a` is moved again; error!
/// ```
///
/// You can also use `dbg!()` without a value to just print the
/// file and line whenever it's reached.
///
/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as
/// a tuple (and return it, too):
///
/// ```
/// assert_eq!(dbg!(1usize, 2u32), (1, 2));
/// ```
///
/// However, a single argument with a trailing comma will still not be treated
/// as a tuple, following the convention of ignoring trailing commas in macro
/// invocations. You can use a 1-tuple directly if you need one:
///
/// ```
/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored
/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple
/// ```
///
/// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)
/// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html
/// [`log`]: https://crates.io/crates/log
#[macro_export]
#[stable(feature = "dbg_macro", since = "1.32.0")]
macro_rules! dbg {
    () => {
        $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());
    };
    ($val:expr) => {
        // Use of `match` here is intentional because it affects the lifetimes
        // of temporaries - https://stackoverflow.com/a/48732525/1063961
        match $val {
            tmp => {
                $crate::eprintln!("[{}:{}] {} = {:#?}",
                    $crate::file!(), $crate::line!(), $crate::stringify!($val), &tmp);
                tmp
            }
        }
    };
    // Trailing comma with single argument is ignored
    ($val:expr,) => { $crate::dbg!($val) };
    ($($val:expr),+ $(,)?) => {
        ($($crate::dbg!($val)),+,)
    };
}

#[cfg(test)]
macro_rules! assert_approx_eq {
    ($a:expr, $b:expr) => {{
        let (a, b) = (&$a, &$b);
        assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
    }};
}
<|endoftext|>


<commit_before>#![recursion_limit = "128"]
extern crate proc_macro;
extern crate proc_macro2;

use proc_macro::TokenStream;

use quote::quote;
use syn;
use syn::Error;
use syn::ItemFn;

#[proc_macro_attribute]
pub fn libtock_main(_: TokenStream, input: TokenStream) -> TokenStream {
    generate_main_wrapped(input.into()).into()
}

fn generate_main_wrapped(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
    try_generate_main_wrapped(input).unwrap_or_else(|err| err.to_compile_error().into())
}

fn try_generate_main_wrapped(
    input: proc_macro2::TokenStream,
) -> Result<proc_macro2::TokenStream, Error> {
    let ast = syn::parse2::<ItemFn>(input)?;
    let block = ast.block;
    Ok(quote!(
        fn main() -> ::libtock::result::TockResult<()> {
            unsafe {::core::executor::block_on( async #block ) }
        }
    ))
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn wraps_main_into_blocking_executor() {
        let method_def: proc_macro2::TokenStream = quote! {
            async fn main() {
                do_stuff().await;
            }
        }
        .into();
        let actual: ItemFn = syn::parse2::<ItemFn>(generate_main_wrapped(method_def.into()))
            .unwrap()
            .into();
        let expected: ItemFn = syn::parse2::<ItemFn>(quote!(
            fn main() {
                ::core::executor::block_on(async {
                    do_stuff().await;
                });
            }
        ))
        .unwrap()
        .into();
        assert_eq!(actual, expected);
    }
}
<commit_msg>Solve issues with unsafe<commit_after>#![recursion_limit = "128"]
extern crate proc_macro;
extern crate proc_macro2;

use proc_macro::TokenStream;

use quote::quote;
use syn;
use syn::Error;
use syn::ItemFn;

#[proc_macro_attribute]
pub fn libtock_main(_: TokenStream, input: TokenStream) -> TokenStream {
    generate_main_wrapped(input.into()).into()
}

fn generate_main_wrapped(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
    try_generate_main_wrapped(input).unwrap_or_else(|err| err.to_compile_error().into())
}

fn try_generate_main_wrapped(
    input: proc_macro2::TokenStream,
) -> Result<proc_macro2::TokenStream, Error> {
    let ast = syn::parse2::<ItemFn>(input)?;
    let block = ast.block;
    Ok(quote!(
        fn main() -> ::libtock::result::TockResult<()> {
            let _block = async #block;
            unsafe {::core::executor::block_on(_block) }
        }
    ))
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn wraps_main_into_blocking_executor() {
        let method_def: proc_macro2::TokenStream = quote! {
            async fn main() -> ::libtock::result::TockResult<()>{
                method_call().await;
            }
        }
        .into();
        let actual: ItemFn = syn::parse2::<ItemFn>(generate_main_wrapped(method_def.into()))
            .unwrap()
            .into();
        let expected: ItemFn = syn::parse2::<ItemFn>(quote!(
            fn main() -> ::libtock::result::TockResult<()> {
                let _block = async {
                    method_call().await;
                };
                unsafe { ::core::executor::block_on(_block) }
            }
        ))
        .unwrap()
        .into();
        assert_eq!(actual, expected);
    }
}
<|endoftext|>