<commit_before>#[macro_use]
extern crate assert_cli;
extern crate tempdir;
extern crate toml;

use std::process;
mod utils;
use utils::{clone_out_test, execute_command, get_toml, no_manifest_failures};

#[test]
fn adds_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package").is_none());

    execute_command(&["add", "my-package"], &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
}

#[test]
fn adds_multiple_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependencies not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package1").is_none());
    assert!(toml.lookup("dependencies.my-package2").is_none());

    execute_command(&["add", "my-package1", "my-package2"], &manifest);

    // dependencies present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package1").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
    let val = toml.lookup("dependencies.my-package2").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
}

#[test]
fn adds_dev_build_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dev-dependencies.my-dev-package").is_none());
    assert!(toml.lookup("build-dependencies.my-build-package").is_none());

    execute_command(&["add", "my-dev-package", "--dev"], &manifest);
    execute_command(&["add", "my-build-package", "--build"], &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dev-dependencies.my-dev-package").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
    let val = toml.lookup("build-dependencies.my-build-package").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");

    // cannot run with both --dev and --build at the same time
    let call = process::Command::new("target/debug/cargo-add")
                   .args(&["add", "failure", "--dev", "--build"])
                   .arg(format!("--manifest-path={}", &manifest))
                   .output()
                   .unwrap();

    assert!(!call.status.success());
    assert!(no_manifest_failures(&get_toml(&manifest)));
}

#[test]
fn adds_multiple_dev_build_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependencies not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dev-dependencies.my-dev-package1").is_none());
    assert!(toml.lookup("dev-dependencies.my-dev-package2").is_none());
    assert!(toml.lookup("build-dependencies.my-build-package1").is_none());
    assert!(toml.lookup("build-dependencies.my-build-package2").is_none());

    execute_command(&["add", "my-dev-package1", "my-dev-package2", "--dev"], &manifest);
    execute_command(&["add", "my-build-package1", "--build", "my-build-package2"], &manifest);

    // dependencies present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dev-dependencies.my-dev-package1").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
    let val = toml.lookup("dev-dependencies.my-dev-package2").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
    let val = toml.lookup("build-dependencies.my-build-package1").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
    let val = toml.lookup("build-dependencies.my-build-package2").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
}

#[test]
fn adds_specified_version() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.versioned-package").is_none());

    execute_command(&["add", "versioned-package", "--vers", ">=0.1.1"],
                    &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.versioned-package").expect("not added");
    assert_eq!(val.as_str().expect("not string"), ">=0.1.1");

    // cannot run with both --dev and --build at the same time
    let call = process::Command::new("target/debug/cargo-add")
                   .args(&["add", "failure", "--vers", "invalid version string"])
                   .arg(format!("--manifest-path={}", &manifest))
                   .output()
                   .unwrap();

    assert!(!call.status.success());
    assert!(no_manifest_failures(&get_toml(&manifest)));
}

#[test]
fn adds_specified_version_with_inline_notation() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.versioned-package").is_none());

    execute_command(&["add", "versioned-package@>=0.1.1"], &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.versioned-package").expect("not added");
    assert_eq!(val.as_str().expect("not string"), ">=0.1.1");
}

#[test]
fn adds_multiple_dependencies_with_versions() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependencies not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package1").is_none());
    assert!(toml.lookup("dependencies.my-package2").is_none());

    execute_command(&["add", "my-package1@>=0.1.1", "my-package2@0.2.3"], &manifest);

    // dependencies present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package1").expect("not added");
    assert_eq!(val.as_str().expect("not string"), ">=0.1.1");
    let val = toml.lookup("dependencies.my-package2").expect("not added");
    assert_eq!(val.as_str().expect("not string"), "0.2.3");
}

#[test]
fn adds_multiple_dependencies_with_some_versions() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependencies not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package1").is_none());
    assert!(toml.lookup("dependencies.my-package2").is_none());

    execute_command(&["add", "my-package1", "my-package2@0.2.3"], &manifest);

    // dependencies present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package1").expect("not added");
    assert_eq!(val.as_str().expect("not string"), "CURRENT_VERSION_TEST");
    let val = toml.lookup("dependencies.my-package2").expect("not added");
    assert_eq!(val.as_str().expect("not string"), "0.2.3");
}

#[test]
fn adds_git_source() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.git-package").is_none());

    execute_command(&["add", "git-package", "--git", "http://localhost/git-package.git"],
                    &manifest);

    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.git-package").unwrap();
    assert_eq!(val.as_table().unwrap().get("git").unwrap().as_str().unwrap(),
               "http://localhost/git-package.git");

    // check this works with other flags (e.g. --dev) as well
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dev-dependencies.git-dev-pkg").is_none());

    execute_command(&["add", "git-dev-pkg", "--git", "http://site/gp.git", "--dev"],
                    &manifest);

    let toml = get_toml(&manifest);
    let val = toml.lookup("dev-dependencies.git-dev-pkg").unwrap();
    assert_eq!(val.as_table().unwrap().get("git").unwrap().as_str().unwrap(),
               "http://site/gp.git");
}

#[test]
fn adds_local_source() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.local").is_none());

    execute_command(&["add", "local", "--path", "/path/to/pkg"], &manifest);

    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.local").unwrap();
    assert_eq!(val.as_table().unwrap().get("path").unwrap().as_str().unwrap(),
               "/path/to/pkg");

    // check this works with other flags (e.g. --dev) as well
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dev-dependencies.local-dev").is_none());

    execute_command(&["add", "local-dev", "--path", "/path/to/pkg-dev", "--dev"],
                    &manifest);

    let toml = get_toml(&manifest);
    let val = toml.lookup("dev-dependencies.local-dev").unwrap();
    assert_eq!(val.as_table().unwrap().get("path").unwrap().as_str().unwrap(),
               "/path/to/pkg-dev");
}

#[test]
fn package_kinds_are_mutually_exclusive() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    let call = process::Command::new("target/debug/cargo-add")
                   .args(&["add", "failure"])
                   .args(&["--vers", "0.4.3"])
                   .args(&["--git", "git://git.git"])
                   .args(&["--path", "/path/here"])
                   .arg(format!("--manifest-path={}", &manifest))
                   .output()
                   .unwrap();

    assert!(!call.status.success());
    assert!(no_manifest_failures(&get_toml(&manifest)));
}

#[test]
fn adds_optional_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.versioned-package").is_none());

    execute_command(&["add", "versioned-package", "--vers", ">=0.1.1", "--optional"],
                    &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.versioned-package.optional").expect("not added optionally");
    assert_eq!(val.as_bool().expect("optional not a bool"), true);
}

#[test]
fn adds_multiple_optional_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependencies not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package1").is_none());
    assert!(toml.lookup("dependencies.my-package2").is_none());

    execute_command(&["add", "--optional", "my-package1", "my-package2"],
                    &manifest);

    // dependencies present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package1.optional").expect("not added optionally");
    assert_eq!(val.as_bool().expect("optional not a bool"), true);
    let val = toml.lookup("dependencies.my-package2.optional").expect("not added optionally");
    assert_eq!(val.as_bool().expect("optional not a bool"), true);
}

#[test]
#[should_panic]
fn fails_to_add_optional_dev_dependency() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.versioned-package").is_none());

    // Fails because optional dependencies must be in `dependencies` table.
    execute_command(&["add", "versioned-package", "--vers", ">=0.1.1", "--dev", "--optional"],
                    &manifest);
}

#[test]
#[should_panic]
fn fails_to_add_multiple_optional_dev_dependency() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.versioned-package").is_none());

    // Fails because optional dependencies must be in `dependencies` table.
    execute_command(&["add", "--optional", "my-package1", "my-package2", "--dev"],
                    &manifest);
}

#[test]
fn no_argument() {
    assert_cli!("target/debug/cargo-add", &["add"] => Error 1,
                r"Invalid arguments.

Usage:
    cargo add <crate> [--dev|--build|--optional] [--vers=<ver>|--git=<uri>|--path=<uri>] [options]
    cargo add <crates>... [--dev|--build|--optional] [options]
    cargo add (-h|--help)
    cargo add --version")
        .unwrap();
}

#[test]
fn unknown_flags() {
    assert_cli!("target/debug/cargo-add", &["add", "foo", "--flag"] => Error 1,
                r"Unknown flag: '--flag'

Usage:
    cargo add <crate> [--dev|--build|--optional] [--vers=<ver>|--git=<uri>|--path=<uri>] [options]
    cargo add <crates>... [--dev|--build|--optional] [options]
    cargo add (-h|--help)
    cargo add --version")
        .unwrap();
}
<commit_msg>Fix most recent test<commit_after>#[macro_use]
extern crate assert_cli;
extern crate tempdir;
extern crate toml;

use std::process;
mod utils;
use utils::{clone_out_test, execute_command, get_toml, no_manifest_failures};

#[test]
fn adds_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package").is_none());

    execute_command(&["add", "my-package"], &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
}

#[test]
fn adds_multiple_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependencies not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package1").is_none());
    assert!(toml.lookup("dependencies.my-package2").is_none());

    execute_command(&["add", "my-package1", "my-package2"], &manifest);

    // dependencies present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package1").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
    let val = toml.lookup("dependencies.my-package2").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
}

#[test]
fn adds_dev_build_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dev-dependencies.my-dev-package").is_none());
    assert!(toml.lookup("build-dependencies.my-build-package").is_none());

    execute_command(&["add", "my-dev-package", "--dev"], &manifest);
    execute_command(&["add", "my-build-package", "--build"], &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dev-dependencies.my-dev-package").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
    let val = toml.lookup("build-dependencies.my-build-package").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");

    // cannot run with both --dev and --build at the same time
    let call = process::Command::new("target/debug/cargo-add")
                   .args(&["add", "failure", "--dev", "--build"])
                   .arg(format!("--manifest-path={}", &manifest))
                   .output()
                   .unwrap();

    assert!(!call.status.success());
    assert!(no_manifest_failures(&get_toml(&manifest)));
}

#[test]
fn adds_multiple_dev_build_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependencies not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dev-dependencies.my-dev-package1").is_none());
    assert!(toml.lookup("dev-dependencies.my-dev-package2").is_none());
    assert!(toml.lookup("build-dependencies.my-build-package1").is_none());
    assert!(toml.lookup("build-dependencies.my-build-package2").is_none());

    execute_command(&["add", "my-dev-package1", "my-dev-package2", "--dev"], &manifest);
    execute_command(&["add", "my-build-package1", "--build", "my-build-package2"], &manifest);

    // dependencies present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dev-dependencies.my-dev-package1").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
    let val = toml.lookup("dev-dependencies.my-dev-package2").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
    let val = toml.lookup("build-dependencies.my-build-package1").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
    let val = toml.lookup("build-dependencies.my-build-package2").unwrap();
    assert_eq!(val.as_str().unwrap(), "CURRENT_VERSION_TEST");
}

#[test]
fn adds_specified_version() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.versioned-package").is_none());

    execute_command(&["add", "versioned-package", "--vers", ">=0.1.1"],
                    &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.versioned-package").expect("not added");
    assert_eq!(val.as_str().expect("not string"), ">=0.1.1");

    // cannot run with both --dev and --build at the same time
    let call = process::Command::new("target/debug/cargo-add")
                   .args(&["add", "failure", "--vers", "invalid version string"])
                   .arg(format!("--manifest-path={}", &manifest))
                   .output()
                   .unwrap();

    assert!(!call.status.success());
    assert!(no_manifest_failures(&get_toml(&manifest)));
}

#[test]
fn adds_specified_version_with_inline_notation() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.versioned-package").is_none());

    execute_command(&["add", "versioned-package@>=0.1.1"], &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.versioned-package").expect("not added");
    assert_eq!(val.as_str().expect("not string"), ">=0.1.1");
}

#[test]
fn adds_multiple_dependencies_with_versions() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependencies not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package1").is_none());
    assert!(toml.lookup("dependencies.my-package2").is_none());

    execute_command(&["add", "my-package1@>=0.1.1", "my-package2@0.2.3"], &manifest);

    // dependencies present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package1").expect("not added");
    assert_eq!(val.as_str().expect("not string"), ">=0.1.1");
    let val = toml.lookup("dependencies.my-package2").expect("not added");
    assert_eq!(val.as_str().expect("not string"), "0.2.3");
}

#[test]
fn adds_multiple_dependencies_with_some_versions() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependencies not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package1").is_none());
    assert!(toml.lookup("dependencies.my-package2").is_none());

    execute_command(&["add", "my-package1", "my-package2@0.2.3"], &manifest);

    // dependencies present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package1").expect("not added");
    assert_eq!(val.as_str().expect("not string"), "CURRENT_VERSION_TEST");
    let val = toml.lookup("dependencies.my-package2").expect("not added");
    assert_eq!(val.as_str().expect("not string"), "0.2.3");
}

#[test]
fn adds_git_source() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.git-package").is_none());

    execute_command(&["add", "git-package", "--git", "http://localhost/git-package.git"],
                    &manifest);

    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.git-package").unwrap();
    assert_eq!(val.as_table().unwrap().get("git").unwrap().as_str().unwrap(),
               "http://localhost/git-package.git");

    // check this works with other flags (e.g. --dev) as well
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dev-dependencies.git-dev-pkg").is_none());

    execute_command(&["add", "git-dev-pkg", "--git", "http://site/gp.git", "--dev"],
                    &manifest);

    let toml = get_toml(&manifest);
    let val = toml.lookup("dev-dependencies.git-dev-pkg").unwrap();
    assert_eq!(val.as_table().unwrap().get("git").unwrap().as_str().unwrap(),
               "http://site/gp.git");
}

#[test]
fn adds_local_source() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.local").is_none());

    execute_command(&["add", "local", "--path", "/path/to/pkg"], &manifest);

    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.local").unwrap();
    assert_eq!(val.as_table().unwrap().get("path").unwrap().as_str().unwrap(),
               "/path/to/pkg");

    // check this works with other flags (e.g. --dev) as well
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dev-dependencies.local-dev").is_none());

    execute_command(&["add", "local-dev", "--path", "/path/to/pkg-dev", "--dev"],
                    &manifest);

    let toml = get_toml(&manifest);
    let val = toml.lookup("dev-dependencies.local-dev").unwrap();
    assert_eq!(val.as_table().unwrap().get("path").unwrap().as_str().unwrap(),
               "/path/to/pkg-dev");
}

#[test]
fn package_kinds_are_mutually_exclusive() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    let call = process::Command::new("target/debug/cargo-add")
                   .args(&["add", "failure"])
                   .args(&["--vers", "0.4.3"])
                   .args(&["--git", "git://git.git"])
                   .args(&["--path", "/path/here"])
                   .arg(format!("--manifest-path={}", &manifest))
                   .output()
                   .unwrap();

    assert!(!call.status.success());
    assert!(no_manifest_failures(&get_toml(&manifest)));
}

#[test]
fn adds_optional_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.versioned-package").is_none());

    execute_command(&["add", "versioned-package", "--vers", ">=0.1.1", "--optional"],
                    &manifest);

    // dependency present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.versioned-package.optional").expect("not added optionally");
    assert_eq!(val.as_bool().expect("optional not a bool"), true);
}

#[test]
fn adds_multiple_optional_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependencies not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package1").is_none());
    assert!(toml.lookup("dependencies.my-package2").is_none());

    execute_command(&["add", "--optional", "my-package1", "my-package2"],
                    &manifest);

    // dependencies present afterwards
    let toml = get_toml(&manifest);
    let val = toml.lookup("dependencies.my-package1.optional").expect("not added optionally");
    assert_eq!(val.as_bool().expect("optional not a bool"), true);
    let val = toml.lookup("dependencies.my-package2.optional").expect("not added optionally");
    assert_eq!(val.as_bool().expect("optional not a bool"), true);
}

#[test]
#[should_panic]
fn fails_to_add_optional_dev_dependency() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependency not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.versioned-package").is_none());

    // Fails because optional dependencies must be in `dependencies` table.
    execute_command(&["add", "versioned-package", "--vers", ">=0.1.1", "--dev", "--optional"],
                    &manifest);
}

#[test]
#[should_panic]
fn fails_to_add_multiple_optional_dev_dependencies() {
    let (_tmpdir, manifest) = clone_out_test("tests/fixtures/add/Cargo.toml.sample");

    // dependencies not present beforehand
    let toml = get_toml(&manifest);
    assert!(toml.lookup("dependencies.my-package1").is_none());
    assert!(toml.lookup("dependencies.my-package2").is_none());

    // Fails because optional dependencies must be in `dependencies` table.
    execute_command(&["add", "--optional", "my-package1", "my-package2", "--dev"],
                    &manifest);
}

#[test]
fn no_argument() {
    assert_cli!("target/debug/cargo-add", &["add"] => Error 1,
                r"Invalid arguments.

Usage:
    cargo add <crate> [--dev|--build|--optional] [--vers=<ver>|--git=<uri>|--path=<uri>] [options]
    cargo add <crates>... [--dev|--build|--optional] [options]
    cargo add (-h|--help)
    cargo add --version")
        .unwrap();
}

#[test]
fn unknown_flags() {
    assert_cli!("target/debug/cargo-add", &["add", "foo", "--flag"] => Error 1,
                r"Unknown flag: '--flag'

Usage:
    cargo add <crate> [--dev|--build|--optional] [--vers=<ver>|--git=<uri>|--path=<uri>] [options]
    cargo add <crates>... [--dev|--build|--optional] [options]
    cargo add (-h|--help)
    cargo add --version")
        .unwrap();
}
<|endoftext|>


<commit_before>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Expr, ExprRange};

#[test]
fn test_expr_parse() {
    let tokens = quote!(..100u32);
    snapshot!(tokens as Expr, @r###"
    Expr::Range {
        limits: HalfOpen,
        to: Some(Expr::Lit {
            lit: 100u32,
        }),
    }
    "###);

    let tokens = quote!(..100u32);
    snapshot!(tokens as ExprRange, @r###"
    ExprRange {
        limits: HalfOpen,
        to: Some(Expr::Lit {
            lit: 100u32,
        }),
    }
    "###);
}

#[test]
fn test_await() {
    // Must not parse as Expr::Field.
    let tokens = quote!(fut.await);

    snapshot!(tokens as Expr, @r###"
    Expr::Await {
        base: Expr::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "fut",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);
}

#[test]
fn test_tuple_multi_index() {
    let input = "tuple.0.0";
    snapshot!(input as Expr, @r###"
    Expr::Field {
        base: Expr::Field {
            base: Expr::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "tuple",
                            arguments: None,
                        },
                    ],
                },
            },
            member: Unnamed(Index {
                index: 0,
            }),
        },
        member: Unnamed(Index {
            index: 0,
        }),
    }
    "###);

    let tokens = quote!(tuple.0.0);
    snapshot!(tokens as Expr, @r###"
    Expr::Field {
        base: Expr::Field {
            base: Expr::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "tuple",
                            arguments: None,
                        },
                    ],
                },
            },
            member: Unnamed(Index {
                index: 0,
            }),
        },
        member: Unnamed(Index {
            index: 0,
        }),
    }
    "###);
}

#[test]
fn test_macro_variable_func() {
    // mimics the token stream corresponding to `$fn()`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { f })),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Call {
        func: Expr::Group {
            expr: Expr::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "f",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);

    let tokens = TokenStream::from_iter(vec![
        TokenTree::Punct(Punct::new('#', Spacing::Alone)),
        TokenTree::Group(Group::new(Delimiter::Bracket, quote! { outside })),
        TokenTree::Group(Group::new(Delimiter::None, quote! { #[inside] f })),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Call {
        attrs: [
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "outside",
                            arguments: None,
                        },
                    ],
                },
                tokens: TokenStream(``),
            },
        ],
        func: Expr::Group {
            expr: Expr::Path {
                attrs: [
                    Attribute {
                        style: Outer,
                        path: Path {
                            segments: [
                                PathSegment {
                                    ident: "inside",
                                    arguments: None,
                                },
                            ],
                        },
                        tokens: TokenStream(``),
                    },
                ],
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "f",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);
}

#[test]
fn test_macro_variable_macro() {
    // mimics the token stream corresponding to `$macro!()`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { m })),
        TokenTree::Punct(Punct::new('!', Spacing::Alone)),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Macro {
        mac: Macro {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "m",
                        arguments: None,
                    },
                ],
            },
            delimiter: Paren,
            tokens: TokenStream(``),
        },
    }
    "###);
}

#[test]
fn test_macro_variable_struct() {
    // mimics the token stream corresponding to `$struct {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { S })),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Struct {
        path: Path {
            segments: [
                PathSegment {
                    ident: "S",
                    arguments: None,
                },
            ],
        },
    }
    "###);
}

#[test]
fn test_macro_variable_match_arm() {
    // mimics the token stream corresponding to `match v { _ => $expr }`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("match", Span::call_site())),
        TokenTree::Ident(Ident::new("v", Span::call_site())),
        TokenTree::Group(Group::new(
            Delimiter::Brace,
            TokenStream::from_iter(vec![
                TokenTree::Punct(Punct::new('_', Spacing::Alone)),
                TokenTree::Punct(Punct::new('=', Spacing::Joint)),
                TokenTree::Punct(Punct::new('>', Spacing::Alone)),
                TokenTree::Group(Group::new(Delimiter::None, quote! { #[a] () })),
            ]),
        )),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Match {
        expr: Expr::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "v",
                        arguments: None,
                    },
                ],
            },
        },
        arms: [
            Arm {
                pat: Pat::Wild,
                body: Expr::Group {
                    expr: Expr::Tuple {
                        attrs: [
                            Attribute {
                                style: Outer,
                                path: Path {
                                    segments: [
                                        PathSegment {
                                            ident: "a",
                                            arguments: None,
                                        },
                                    ],
                                },
                                tokens: TokenStream(``),
                            },
                        ],
                    },
                },
            },
        ],
    }
    "###);
}
<commit_msg>Add regression test failing on `tuple.0. 0`<commit_after>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Expr, ExprRange};

#[test]
fn test_expr_parse() {
    let tokens = quote!(..100u32);
    snapshot!(tokens as Expr, @r###"
    Expr::Range {
        limits: HalfOpen,
        to: Some(Expr::Lit {
            lit: 100u32,
        }),
    }
    "###);

    let tokens = quote!(..100u32);
    snapshot!(tokens as ExprRange, @r###"
    ExprRange {
        limits: HalfOpen,
        to: Some(Expr::Lit {
            lit: 100u32,
        }),
    }
    "###);
}

#[test]
fn test_await() {
    // Must not parse as Expr::Field.
    let tokens = quote!(fut.await);

    snapshot!(tokens as Expr, @r###"
    Expr::Await {
        base: Expr::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "fut",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);
}

#[test]
fn test_tuple_multi_index() {
    for &input in &[
        "tuple.0.0",
        "tuple .0.0",
        "tuple. 0.0",
        "tuple.0 .0",
        "tuple.0. 0",
        "tuple . 0 . 0",
    ] {
        snapshot!(input as Expr, @r###"
        Expr::Field {
            base: Expr::Field {
                base: Expr::Path {
                    path: Path {
                        segments: [
                            PathSegment {
                                ident: "tuple",
                                arguments: None,
                            },
                        ],
                    },
                },
                member: Unnamed(Index {
                    index: 0,
                }),
            },
            member: Unnamed(Index {
                index: 0,
            }),
        }
        "###);
    }

    for tokens in vec![
        quote!(tuple.0.0),
        quote!(tuple .0.0),
        quote!(tuple. 0.0),
        quote!(tuple.0 .0),
        quote!(tuple.0. 0),
        quote!(tuple . 0 . 0),
    ] {
        snapshot!(tokens as Expr, @r###"
        Expr::Field {
            base: Expr::Field {
                base: Expr::Path {
                    path: Path {
                        segments: [
                            PathSegment {
                                ident: "tuple",
                                arguments: None,
                            },
                        ],
                    },
                },
                member: Unnamed(Index {
                    index: 0,
                }),
            },
            member: Unnamed(Index {
                index: 0,
            }),
        }
        "###);
    }
}

#[test]
fn test_macro_variable_func() {
    // mimics the token stream corresponding to `$fn()`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { f })),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Call {
        func: Expr::Group {
            expr: Expr::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "f",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);

    let tokens = TokenStream::from_iter(vec![
        TokenTree::Punct(Punct::new('#', Spacing::Alone)),
        TokenTree::Group(Group::new(Delimiter::Bracket, quote! { outside })),
        TokenTree::Group(Group::new(Delimiter::None, quote! { #[inside] f })),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Call {
        attrs: [
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "outside",
                            arguments: None,
                        },
                    ],
                },
                tokens: TokenStream(``),
            },
        ],
        func: Expr::Group {
            expr: Expr::Path {
                attrs: [
                    Attribute {
                        style: Outer,
                        path: Path {
                            segments: [
                                PathSegment {
                                    ident: "inside",
                                    arguments: None,
                                },
                            ],
                        },
                        tokens: TokenStream(``),
                    },
                ],
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "f",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);
}

#[test]
fn test_macro_variable_macro() {
    // mimics the token stream corresponding to `$macro!()`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { m })),
        TokenTree::Punct(Punct::new('!', Spacing::Alone)),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Macro {
        mac: Macro {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "m",
                        arguments: None,
                    },
                ],
            },
            delimiter: Paren,
            tokens: TokenStream(``),
        },
    }
    "###);
}

#[test]
fn test_macro_variable_struct() {
    // mimics the token stream corresponding to `$struct {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { S })),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Struct {
        path: Path {
            segments: [
                PathSegment {
                    ident: "S",
                    arguments: None,
                },
            ],
        },
    }
    "###);
}

#[test]
fn test_macro_variable_match_arm() {
    // mimics the token stream corresponding to `match v { _ => $expr }`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("match", Span::call_site())),
        TokenTree::Ident(Ident::new("v", Span::call_site())),
        TokenTree::Group(Group::new(
            Delimiter::Brace,
            TokenStream::from_iter(vec![
                TokenTree::Punct(Punct::new('_', Spacing::Alone)),
                TokenTree::Punct(Punct::new('=', Spacing::Joint)),
                TokenTree::Punct(Punct::new('>', Spacing::Alone)),
                TokenTree::Group(Group::new(Delimiter::None, quote! { #[a] () })),
            ]),
        )),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Match {
        expr: Expr::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "v",
                        arguments: None,
                    },
                ],
            },
        },
        arms: [
            Arm {
                pat: Pat::Wild,
                body: Expr::Group {
                    expr: Expr::Tuple {
                        attrs: [
                            Attribute {
                                style: Outer,
                                path: Path {
                                    segments: [
                                        PathSegment {
                                            ident: "a",
                                            arguments: None,
                                        },
                                    ],
                                },
                                tokens: TokenStream(``),
                            },
                        ],
                    },
                },
            },
        ],
    }
    "###);
}
<|endoftext|>


<commit_before>//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from MessagePack via the serialization API. To be able to serialize a piece of data, it must
//! implement the `serde::Serialize` trait. To be able to deserialize a piece of data, it must
//! implement the `serde::Deserialize` trait. Serde provides provides an annotation to
//! automatically generate the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! # Examples
//!
//! Let's try to encode and decode some built-in types.
//!
//! ```rust
//! extern crate serde;
//! extern crate rmp_serde as rmps;
//!
//! use serde::{Deserialize, Serialize};
//! use rmps::{Deserializer, Serializer};
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = (42u8, "the Answer");
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//!
//!     assert_eq!(vec![0x92, 0x2a, 0xaa, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72], buf);
//!
//!     let mut de = Deserializer::new(&buf[..]);
//!     assert_eq!((42, "the Answer".to_owned()), Deserialize::deserialize(&mut de).unwrap());
//! }
//! ```
//!
//! No one gonna hurt if we add some reflection magic.
//!
//! ```ignore
//! extern crate serde;
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate rmp_serde as rmps;
//!
//! use std::collections::HashMap;
//! use serde::{Deserialize, Serialize};
//! use rmps::{Deserializer, Serializer};
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Human {
//!     age: u32,
//!     name: String,
//! }
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = Human {
//!         age: 42,
//!         name: "John".into(),
//!     };
//!
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//! }
//! ```

#![warn(missing_debug_implementations, missing_docs)]

extern crate rmp;
extern crate byteorder;
#[macro_use]
extern crate serde;

use std::fmt::{self, Display, Formatter};
use std::mem;
use std::str::{self, Utf8Error};

use serde::Serialize;
use serde::de::{self, Deserialize};

pub use decode::{Deserializer, from_read, from_read_ref, from_slice};
pub use encode::{Serializer, to_vec, to_vec_named};

pub mod decode;
pub mod encode;
pub mod ext;

/// Helper that allows both to encode and decode strings no matter whether they contain valid or
/// invalid UTF-8.
///
/// Regardless of validity the UTF-8 content this type will always be serialized as a string.
#[derive(Clone, Debug, PartialEq)]
pub struct Raw {
    s: Result<String, (Vec<u8>, Utf8Error)>,
}

impl Raw {
    /// Constructs a new `Raw` from the UTF-8 string.
    pub fn new(v: String) -> Self {
        Self { s: Ok(v) }
    }

    /// Converts a vector of bytes to a `Raw`.
    pub fn from_utf8(v: Vec<u8>) -> Self {
        match String::from_utf8(v) {
            Ok(v) => Raw::new(v),
            Err(err) => {
                let e = err.utf8_error();
                Self {
                    s: Err((err.into_bytes(), e))
                }
            }
        }
    }

    /// Returns `true` if the raw is valid UTF-8.
    pub fn is_str(&self) -> bool {
        self.s.is_ok()
    }

    /// Returns `true` if the raw contains invalid UTF-8 sequence.
    pub fn is_err(&self) -> bool {
        self.s.is_err()
    }

    /// Returns the string reference if the raw is valid UTF-8, or else `None`.
    pub fn as_str(&self) -> Option<&str> {
        match self.s {
            Ok(ref s) => Some(s.as_str()),
            Err(..) => None,
        }
    }

    /// Returns the underlying `Utf8Error` if the raw contains invalid UTF-8 sequence, or
    /// else `None`.
    pub fn as_err(&self) -> Option<&Utf8Error> {
        match self.s {
            Ok(..) => None,
            Err((_, ref err)) => Some(&err),
        }
    }

    /// Returns a byte slice of this raw's contents.
    pub fn as_bytes(&self) -> &[u8] {
        match self.s {
            Ok(ref s) => s.as_bytes(),
            Err(ref err) => &err.0[..],
        }
    }

    /// Consumes this object, yielding the string if the raw is valid UTF-8, or else `None`.
    pub fn into_str(self) -> Option<String> {
        self.s.ok()
    }

    /// Converts a `Raw` into a byte vector.
    pub fn into_bytes(self) -> Vec<u8> {
        match self.s {
            Ok(s) => s.into_bytes(),
            Err(err) => err.0,
        }
    }
}

impl Serialize for Raw {
    fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer
    {
        let s = match self.s {
            Ok(ref s) => s.as_str(),
            Err((ref b, ..)) => unsafe { mem::transmute(&b[..]) },
        };

        se.serialize_str(s)
    }
}

struct RawVisitor;

impl<'de> de::Visitor<'de> for RawVisitor {
    type Value = Raw;

    fn expecting(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        "string or bytes".fmt(fmt)
    }

    #[inline]
    fn visit_string<E>(self, v: String) -> Result<Self::Value, E> {
        Ok(Raw { s: Ok(v) })
    }

    #[inline]
    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
        where E: de::Error
    {
        Ok(Raw { s: Ok(v.into()) })
    }

    #[inline]
    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match str::from_utf8(v) {
            Ok(s) => Ok(s.into()),
            Err(err) => Err((v.into(), err)),
        };

        Ok(Raw { s: s })
    }

    #[inline]
    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match String::from_utf8(v) {
            Ok(s) => Ok(s),
            Err(err) => {
                let e = err.utf8_error();
                Err((err.into_bytes(), e))
            }
        };

        Ok(Raw { s: s })
    }
}

impl<'de> Deserialize<'de> for Raw {
    #[inline]
    fn deserialize<D>(de: D) -> Result<Self, D::Error>
        where D: de::Deserializer<'de>
    {
        de.deserialize_any(RawVisitor)
    }
}

/// Helper that allows both to encode and decode strings no matter whether they contain valid or
/// invalid UTF-8.
///
/// Regardless of validity the UTF-8 content this type will always be serialized as a string.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct RawRef<'a> {
    s: Result<&'a str, (&'a [u8], Utf8Error)>,
}

impl<'a> RawRef<'a> {
    /// Constructs a new `RawRef` from the UTF-8 string.
    pub fn new(v: &'a str) -> Self {
        Self { s: Ok(v) }
    }

    /// Converts a vector of bytes to a `RawRef`.
    pub fn from_utf8(v: &'a [u8]) -> Self {
        match str::from_utf8(v) {
            Ok(v) => RawRef::new(v),
            Err(err) => {
                Self {
                    s: Err((v, err))
                }
            }
        }
    }

    /// Returns `true` if the raw is valid UTF-8.
    pub fn is_str(&self) -> bool {
        self.s.is_ok()
    }

    /// Returns `true` if the raw contains invalid UTF-8 sequence.
    pub fn is_err(&self) -> bool {
        self.s.is_err()
    }

    /// Returns the string reference if the raw is valid UTF-8, or else `None`.
    pub fn as_str(&self) -> Option<&str> {
        match self.s {
            Ok(ref s) => Some(s),
            Err(..) => None,
        }
    }

    /// Returns the underlying `Utf8Error` if the raw contains invalid UTF-8 sequence, or
    /// else `None`.
    pub fn as_err(&self) -> Option<&Utf8Error> {
        match self.s {
            Ok(..) => None,
            Err((_, ref err)) => Some(&err),
        }
    }

    /// Returns a byte slice of this raw's contents.
    pub fn as_bytes(&self) -> &[u8] {
        match self.s {
            Ok(ref s) => s.as_bytes(),
            Err(ref err) => &err.0[..],
        }
    }
}

impl<'a> Serialize for RawRef<'a> {
    fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer
    {
        let s = match self.s {
            Ok(ref s) => s,
            Err((ref b, ..)) => unsafe { mem::transmute(b) },
        };

        se.serialize_str(s)
    }
}

struct RawRefVisitor;

impl<'de> de::Visitor<'de> for RawRefVisitor {
    type Value = RawRef<'de>;

    fn expecting(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        "string or bytes".fmt(fmt)
    }

    #[inline]
    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
        where E: de::Error
    {
        Ok(RawRef { s: Ok(v) })
    }

    #[inline]
    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match str::from_utf8(v) {
            Ok(s) => Ok(s),
            Err(err) => Err((v, err)),
        };

        Ok(RawRef { s: s })
    }
}

impl<'de> Deserialize<'de> for RawRef<'de> {
    #[inline]
    fn deserialize<D>(de: D) -> Result<Self, D::Error>
        where D: de::Deserializer<'de>
    {
        de.deserialize_any(RawRefVisitor)
    }
}
<commit_msg>chore: activate a doctest<commit_after>//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from MessagePack via the serialization API. To be able to serialize a piece of data, it must
//! implement the `serde::Serialize` trait. To be able to deserialize a piece of data, it must
//! implement the `serde::Deserialize` trait. Serde provides provides an annotation to
//! automatically generate the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! # Examples
//!
//! Let's try to encode and decode some built-in types.
//!
//! ```
//! extern crate serde;
//! extern crate rmp_serde as rmps;
//!
//! use serde::{Deserialize, Serialize};
//! use rmps::{Deserializer, Serializer};
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = (42u8, "the Answer");
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//!
//!     assert_eq!(vec![0x92, 0x2a, 0xaa, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72], buf);
//!
//!     let mut de = Deserializer::new(&buf[..]);
//!     assert_eq!((42, "the Answer".to_owned()), Deserialize::deserialize(&mut de).unwrap());
//! }
//! ```
//!
//! No one gonna hurt if we add some reflection magic.
//!
//! ```
//! extern crate serde;
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate rmp_serde as rmps;
//!
//! use std::collections::HashMap;
//! use serde::{Deserialize, Serialize};
//! use rmps::{Deserializer, Serializer};
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Human {
//!     age: u32,
//!     name: String,
//! }
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = Human {
//!         age: 42,
//!         name: "John".into(),
//!     };
//!
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//! }
//! ```

#![warn(missing_debug_implementations, missing_docs)]

extern crate rmp;
extern crate byteorder;
#[macro_use]
extern crate serde;

use std::fmt::{self, Display, Formatter};
use std::mem;
use std::str::{self, Utf8Error};

use serde::Serialize;
use serde::de::{self, Deserialize};

pub use decode::{Deserializer, from_read, from_read_ref, from_slice};
pub use encode::{Serializer, to_vec, to_vec_named};

pub mod decode;
pub mod encode;
pub mod ext;

/// Helper that allows both to encode and decode strings no matter whether they contain valid or
/// invalid UTF-8.
///
/// Regardless of validity the UTF-8 content this type will always be serialized as a string.
#[derive(Clone, Debug, PartialEq)]
pub struct Raw {
    s: Result<String, (Vec<u8>, Utf8Error)>,
}

impl Raw {
    /// Constructs a new `Raw` from the UTF-8 string.
    pub fn new(v: String) -> Self {
        Self { s: Ok(v) }
    }

    /// Converts a vector of bytes to a `Raw`.
    pub fn from_utf8(v: Vec<u8>) -> Self {
        match String::from_utf8(v) {
            Ok(v) => Raw::new(v),
            Err(err) => {
                let e = err.utf8_error();
                Self {
                    s: Err((err.into_bytes(), e))
                }
            }
        }
    }

    /// Returns `true` if the raw is valid UTF-8.
    pub fn is_str(&self) -> bool {
        self.s.is_ok()
    }

    /// Returns `true` if the raw contains invalid UTF-8 sequence.
    pub fn is_err(&self) -> bool {
        self.s.is_err()
    }

    /// Returns the string reference if the raw is valid UTF-8, or else `None`.
    pub fn as_str(&self) -> Option<&str> {
        match self.s {
            Ok(ref s) => Some(s.as_str()),
            Err(..) => None,
        }
    }

    /// Returns the underlying `Utf8Error` if the raw contains invalid UTF-8 sequence, or
    /// else `None`.
    pub fn as_err(&self) -> Option<&Utf8Error> {
        match self.s {
            Ok(..) => None,
            Err((_, ref err)) => Some(&err),
        }
    }

    /// Returns a byte slice of this raw's contents.
    pub fn as_bytes(&self) -> &[u8] {
        match self.s {
            Ok(ref s) => s.as_bytes(),
            Err(ref err) => &err.0[..],
        }
    }

    /// Consumes this object, yielding the string if the raw is valid UTF-8, or else `None`.
    pub fn into_str(self) -> Option<String> {
        self.s.ok()
    }

    /// Converts a `Raw` into a byte vector.
    pub fn into_bytes(self) -> Vec<u8> {
        match self.s {
            Ok(s) => s.into_bytes(),
            Err(err) => err.0,
        }
    }
}

impl Serialize for Raw {
    fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer
    {
        let s = match self.s {
            Ok(ref s) => s.as_str(),
            Err((ref b, ..)) => unsafe { mem::transmute(&b[..]) },
        };

        se.serialize_str(s)
    }
}

struct RawVisitor;

impl<'de> de::Visitor<'de> for RawVisitor {
    type Value = Raw;

    fn expecting(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        "string or bytes".fmt(fmt)
    }

    #[inline]
    fn visit_string<E>(self, v: String) -> Result<Self::Value, E> {
        Ok(Raw { s: Ok(v) })
    }

    #[inline]
    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
        where E: de::Error
    {
        Ok(Raw { s: Ok(v.into()) })
    }

    #[inline]
    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match str::from_utf8(v) {
            Ok(s) => Ok(s.into()),
            Err(err) => Err((v.into(), err)),
        };

        Ok(Raw { s: s })
    }

    #[inline]
    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match String::from_utf8(v) {
            Ok(s) => Ok(s),
            Err(err) => {
                let e = err.utf8_error();
                Err((err.into_bytes(), e))
            }
        };

        Ok(Raw { s: s })
    }
}

impl<'de> Deserialize<'de> for Raw {
    #[inline]
    fn deserialize<D>(de: D) -> Result<Self, D::Error>
        where D: de::Deserializer<'de>
    {
        de.deserialize_any(RawVisitor)
    }
}

/// Helper that allows both to encode and decode strings no matter whether they contain valid or
/// invalid UTF-8.
///
/// Regardless of validity the UTF-8 content this type will always be serialized as a string.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct RawRef<'a> {
    s: Result<&'a str, (&'a [u8], Utf8Error)>,
}

impl<'a> RawRef<'a> {
    /// Constructs a new `RawRef` from the UTF-8 string.
    pub fn new(v: &'a str) -> Self {
        Self { s: Ok(v) }
    }

    /// Converts a vector of bytes to a `RawRef`.
    pub fn from_utf8(v: &'a [u8]) -> Self {
        match str::from_utf8(v) {
            Ok(v) => RawRef::new(v),
            Err(err) => {
                Self {
                    s: Err((v, err))
                }
            }
        }
    }

    /// Returns `true` if the raw is valid UTF-8.
    pub fn is_str(&self) -> bool {
        self.s.is_ok()
    }

    /// Returns `true` if the raw contains invalid UTF-8 sequence.
    pub fn is_err(&self) -> bool {
        self.s.is_err()
    }

    /// Returns the string reference if the raw is valid UTF-8, or else `None`.
    pub fn as_str(&self) -> Option<&str> {
        match self.s {
            Ok(ref s) => Some(s),
            Err(..) => None,
        }
    }

    /// Returns the underlying `Utf8Error` if the raw contains invalid UTF-8 sequence, or
    /// else `None`.
    pub fn as_err(&self) -> Option<&Utf8Error> {
        match self.s {
            Ok(..) => None,
            Err((_, ref err)) => Some(&err),
        }
    }

    /// Returns a byte slice of this raw's contents.
    pub fn as_bytes(&self) -> &[u8] {
        match self.s {
            Ok(ref s) => s.as_bytes(),
            Err(ref err) => &err.0[..],
        }
    }
}

impl<'a> Serialize for RawRef<'a> {
    fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer
    {
        let s = match self.s {
            Ok(ref s) => s,
            Err((ref b, ..)) => unsafe { mem::transmute(b) },
        };

        se.serialize_str(s)
    }
}

struct RawRefVisitor;

impl<'de> de::Visitor<'de> for RawRefVisitor {
    type Value = RawRef<'de>;

    fn expecting(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        "string or bytes".fmt(fmt)
    }

    #[inline]
    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
        where E: de::Error
    {
        Ok(RawRef { s: Ok(v) })
    }

    #[inline]
    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
        where E: de::Error
    {
        let s = match str::from_utf8(v) {
            Ok(s) => Ok(s),
            Err(err) => Err((v, err)),
        };

        Ok(RawRef { s: s })
    }
}

impl<'de> Deserialize<'de> for RawRef<'de> {
    #[inline]
    fn deserialize<D>(de: D) -> Result<Self, D::Error>
        where D: de::Deserializer<'de>
    {
        de.deserialize_any(RawRefVisitor)
    }
}
<|endoftext|>


<commit_before>use rand::*;
use basic_dsp::*;
use basic_dsp::traits::*;
use std::ops::Range;
use num::complex::Complex32;
use std::panic;
use std::fmt::{Display, Debug};

pub fn assert_vector_eq_with_reason<T>(left: &[T], right: &[T], reason: &str)
    where T: RealNumber + Debug + Display
{
    assert_vector_eq_with_reason_and_tolerance(left, right, T::from(1e-6).unwrap(), reason);
}

pub fn assert_vector_eq_with_reason_and_tolerance<T>(left: &[T],
                                                     right: &[T],
                                                     tolerance: T,
                                                     reason: &str)
    where T: RealNumber + Debug + Display
{
    let mut errors = Vec::new();
    if reason.len() > 0 {
        errors.push(format!("{}:\n", reason));
    }

    let size_assert_failed = left.len() != right.len();
    if size_assert_failed {
        errors.push(format!("Size difference {} != {}", left.len(), right.len()));
    }

    let len = if left.len() < right.len() {
        left.len()
    } else {
        right.len()
    };
    let mut differences = 0;
    for i in 0..len {
        if (left[i] - right[i]).abs() > tolerance {
            differences += 1;
            if differences <= 10 {
                errors.push(format!("Difference {} at index {}, left: {} != right: {}",
                                    differences,
                                    i,
                                    left[i],
                                    right[i]));
            }
        }
    }

    if differences > 0 {
        errors.push(format!("Total number of differences: {}/{}={}%",
                            differences,
                            len,
                            differences * 100 / len));
    }

    if differences > 0 || size_assert_failed {
        let all_errors = errors.join("\n");
        let header = "-----------------------".to_owned();
        let full_text = format!("\n{}\n{}\n{}\n", header, all_errors, header);
        panic!(full_text);
    }
}

pub fn assert_vector_eq<T>(left: &[T], right: &[T])
    where T: RealNumber + Debug + Display
{
    assert_vector_eq_with_reason(left, right, "");
}

pub fn assert_close(left: f32, right: f32) {
    assert_in_tolerance(left, right, 1e-6);
}

pub fn assert_complex_close(left: Complex32, right: Complex32) {
    assert_complex_in_tolerance(left, right, 1e-6);
}

pub fn assert_in_tolerance(left: f32, right: f32, tol: f32) {
    let tol = tol.abs();
    if (left - right).abs() > tol {
        panic!(format!("{} != {} (tol: {})", left, right, tol));
    }
}

pub fn assert_complex_in_tolerance(left: Complex32, right: Complex32, tol: f32) {
    let tol = tol.abs();
    if (left.re - right.re).abs() > tol || (left.im - right.im).abs() > tol {
        panic!(format!("{} != {} (tol: {})", left, right, tol));
    }
}

pub fn create_data(seed: usize, iteration: usize, from: usize, to: usize) -> Vec<f32> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = if from == to {
        from
    } else {
        rng.gen_range(from, to)
    };
    create_data_with_len(seed, iteration, len)
}

pub fn create_data64(seed: usize, iteration: usize, from: usize, to: usize) -> Vec<f64> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = if from == to {
        from
    } else {
        rng.gen_range(from, to)
    };
    create_data_with_len64(seed, iteration, len)
}

pub fn create_data_even(seed: usize, iteration: usize, from: usize, to: usize) -> Vec<f32> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = rng.gen_range(from, to);
    let len = len + len % 2;
    create_data_with_len(seed, iteration, len)
}

pub fn create_data_with_len(seed: usize, iteration: usize, len: usize) -> Vec<f32> {
    let seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(seed);
    let mut data = vec![0.0; len];
    for i in 0..len {
        data[i] = rng.gen_range(-10.0, 10.0);
    }
    data
}

pub fn create_data_with_len64(seed: usize, iteration: usize, len: usize) -> Vec<f64> {
    let seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(seed);
    let mut data = vec![0.0; len];
    for i in 0..len {
        data[i] = rng.gen_range(-10.0, 10.0);
    }
    data
}

pub fn create_data_even_in_range(seed: usize,
                                 iteration: usize,
                                 from: usize,
                                 to: usize,
                                 range_start: f32,
                                 range_end: f32)
                                 -> Vec<f32> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = rng.gen_range(from, to);
    let len = len + len % 2;
    create_data_in_range_with_len(seed, iteration, len, range_start, range_end)
}

pub fn create_data_simd_len_in_range(seed: usize,
                                     iteration: usize,
                                     from: usize,
                                     to: usize)
                                     -> Vec<f32> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = rng.gen_range(from, to);
    let len = (len / 8 + 1) + 8; // Not exact but good enough
    let len = if len > to { to } else { len };
    create_data_with_len(seed, iteration, len)
}

pub fn create_data_in_range_with_len(seed: usize,
                                     iteration: usize,
                                     len: usize,
                                     range_start: f32,
                                     range_end: f32)
                                     -> Vec<f32> {
    let seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(seed);
    let mut data = vec![0.0; len];
    for i in 0..len {
        data[i] = rng.gen_range(range_start, range_end);
    }
    data
}

pub fn create_delta(seed: usize, iteration: usize) -> f32 {
    let seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(seed);
    rng.gen_range(-10.0, 10.0)
}

pub fn create_random_multitones(seed: usize,
                         iteration: usize,
                         from: usize,
                         to: usize,
                         number_of_tones: usize) -> Vec<f32> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = 2 * rng.gen_range(from, to);
    let mut result = vec![0.0; len].to_real_time_vec();
    for _ in 0..number_of_tones {
        let mut arg = vec![0.0; len].to_real_time_vec();
        arg.map_inplace((), |_, i, _| i as f32);
        let freq = rng.gen_range(0.24, 0.76);
        let phase = rng.gen_range(-1.0, 1.0);
        arg.scale(freq);
        arg.offset(phase);
        arg.cos();
        result.add(&arg).unwrap();
    }

    let (result, _) = result.get();
    result
}

use std::sync::{Arc, Mutex};

pub const RANGE_SINGLE_CORE: Range<usize> = Range {
    start: 10000,
    end: 100000,
};
pub const RANGE_MULTI_CORE: Range<usize> = Range {
    start: 100001,
    end: 200000,
};

pub fn parameterized_vector_test<F>(test_code: F)
    where F: Fn(usize, Range<usize>) + Send + 'static + Sync
{
    let mut test_errors = Vec::new();

    // I don't know if there is a good reason for this, but Rust
    // requires us to lock the test_code function,
    // does catch_panic spawn really a new thread?
    let test_code = Arc::new(Mutex::new(test_code));
    for iteration in 0..10 {
        if test_errors.len() > 0 {
            break; // Stop on the first error to speed up things
        }

        let small_range = RANGE_SINGLE_CORE;
        let test_code = test_code.clone();
        let safe_iteration = panic::AssertUnwindSafe(iteration);
        let small_range = panic::AssertUnwindSafe(small_range);
        let test_code = panic::AssertUnwindSafe(test_code);
        let result = panic::catch_unwind(move || {
            let test_code = test_code.lock().unwrap();
            test_code(*safe_iteration, (*small_range).clone());
        });

        match result {
            Ok(_) => (),
            Err(e) => {
                if let Some(e) = e.downcast_ref::<&'static str>() {
                    test_errors.push(format!("\nSingle threaded execution path failed on iteration \
                                       {}\nFailure: {}",
                                      iteration,
                                      e));
                } else if let Some(e) = e.downcast_ref::<String>() {
                    test_errors.push(format!("\nSingle threaded execution path failed on iteration \
                                       {}\nFailure: {}",
                                      iteration,
                                      e));
                } else {
                    test_errors.push(format!("\nSingle threaded execution path failed on iteration \
                                       {}\nGot an unknown error: {:?}",
                                      iteration,
                                      e));
                }
            }
        }
    }

    for iteration in 0..3 {
        if test_errors.len() > 0 {
            break; // Stop on the first error to speed up things
        }

        let large_range = RANGE_MULTI_CORE;
        let test_code = test_code.clone();
        let safe_iteration = panic::AssertUnwindSafe(iteration);
        let large_range = panic::AssertUnwindSafe(large_range);
        let test_code = panic::AssertUnwindSafe(test_code);
        let result = panic::catch_unwind(move || {
            let test_code = test_code.lock().unwrap();
            test_code(*safe_iteration, (*large_range).clone());
        });

        match result {
            Ok(_) => (),
            Err(e) => {
                if let Some(e) = e.downcast_ref::<&'static str>() {
                    test_errors.push(format!("\nMulti threaded execution path failed on \
                                              iteration {}\nFailure: {}",
                                             iteration,
                                             e));
                } else if let Some(e) = e.downcast_ref::<String>() {
                    test_errors.push(format!("\nMulti threaded execution path failed on \
                                              iteration {}\nFailure: {}",
                                             iteration,
                                             e));
                } else {
                    test_errors.push(format!("\nMulti threaded execution path failed on \
                                              iteration {}\nGot an unknown error: {:?}",
                                             iteration,
                                             e));
                }
            }
        }
    }

    if test_errors.len() > 0 {
        let error_messages = test_errors.join("\n");
        panic!(error_messages);
    }
}
<commit_msg>Fixed incorrect import.<commit_after>use rand::*;
use basic_dsp::*;
use basic_dsp::numbers::*;
use std::ops::Range;
use num::complex::Complex32;
use std::panic;
use std::fmt::{Display, Debug};

pub fn assert_vector_eq_with_reason<T>(left: &[T], right: &[T], reason: &str)
    where T: RealNumber + Debug + Display
{
    assert_vector_eq_with_reason_and_tolerance(left, right, T::from(1e-6).unwrap(), reason);
}

pub fn assert_vector_eq_with_reason_and_tolerance<T>(left: &[T],
                                                     right: &[T],
                                                     tolerance: T,
                                                     reason: &str)
    where T: RealNumber + Debug + Display
{
    let mut errors = Vec::new();
    if reason.len() > 0 {
        errors.push(format!("{}:\n", reason));
    }

    let size_assert_failed = left.len() != right.len();
    if size_assert_failed {
        errors.push(format!("Size difference {} != {}", left.len(), right.len()));
    }

    let len = if left.len() < right.len() {
        left.len()
    } else {
        right.len()
    };
    let mut differences = 0;
    for i in 0..len {
        if (left[i] - right[i]).abs() > tolerance {
            differences += 1;
            if differences <= 10 {
                errors.push(format!("Difference {} at index {}, left: {} != right: {}",
                                    differences,
                                    i,
                                    left[i],
                                    right[i]));
            }
        }
    }

    if differences > 0 {
        errors.push(format!("Total number of differences: {}/{}={}%",
                            differences,
                            len,
                            differences * 100 / len));
    }

    if differences > 0 || size_assert_failed {
        let all_errors = errors.join("\n");
        let header = "-----------------------".to_owned();
        let full_text = format!("\n{}\n{}\n{}\n", header, all_errors, header);
        panic!(full_text);
    }
}

pub fn assert_vector_eq<T>(left: &[T], right: &[T])
    where T: RealNumber + Debug + Display
{
    assert_vector_eq_with_reason(left, right, "");
}

pub fn assert_close(left: f32, right: f32) {
    assert_in_tolerance(left, right, 1e-6);
}

pub fn assert_complex_close(left: Complex32, right: Complex32) {
    assert_complex_in_tolerance(left, right, 1e-6);
}

pub fn assert_in_tolerance(left: f32, right: f32, tol: f32) {
    let tol = tol.abs();
    if (left - right).abs() > tol {
        panic!(format!("{} != {} (tol: {})", left, right, tol));
    }
}

pub fn assert_complex_in_tolerance(left: Complex32, right: Complex32, tol: f32) {
    let tol = tol.abs();
    if (left.re - right.re).abs() > tol || (left.im - right.im).abs() > tol {
        panic!(format!("{} != {} (tol: {})", left, right, tol));
    }
}

pub fn create_data(seed: usize, iteration: usize, from: usize, to: usize) -> Vec<f32> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = if from == to {
        from
    } else {
        rng.gen_range(from, to)
    };
    create_data_with_len(seed, iteration, len)
}

pub fn create_data64(seed: usize, iteration: usize, from: usize, to: usize) -> Vec<f64> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = if from == to {
        from
    } else {
        rng.gen_range(from, to)
    };
    create_data_with_len64(seed, iteration, len)
}

pub fn create_data_even(seed: usize, iteration: usize, from: usize, to: usize) -> Vec<f32> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = rng.gen_range(from, to);
    let len = len + len % 2;
    create_data_with_len(seed, iteration, len)
}

pub fn create_data_with_len(seed: usize, iteration: usize, len: usize) -> Vec<f32> {
    let seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(seed);
    let mut data = vec![0.0; len];
    for i in 0..len {
        data[i] = rng.gen_range(-10.0, 10.0);
    }
    data
}

pub fn create_data_with_len64(seed: usize, iteration: usize, len: usize) -> Vec<f64> {
    let seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(seed);
    let mut data = vec![0.0; len];
    for i in 0..len {
        data[i] = rng.gen_range(-10.0, 10.0);
    }
    data
}

pub fn create_data_even_in_range(seed: usize,
                                 iteration: usize,
                                 from: usize,
                                 to: usize,
                                 range_start: f32,
                                 range_end: f32)
                                 -> Vec<f32> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = rng.gen_range(from, to);
    let len = len + len % 2;
    create_data_in_range_with_len(seed, iteration, len, range_start, range_end)
}

pub fn create_data_simd_len_in_range(seed: usize,
                                     iteration: usize,
                                     from: usize,
                                     to: usize)
                                     -> Vec<f32> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = rng.gen_range(from, to);
    let len = (len / 8 + 1) + 8; // Not exact but good enough
    let len = if len > to { to } else { len };
    create_data_with_len(seed, iteration, len)
}

pub fn create_data_in_range_with_len(seed: usize,
                                     iteration: usize,
                                     len: usize,
                                     range_start: f32,
                                     range_end: f32)
                                     -> Vec<f32> {
    let seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(seed);
    let mut data = vec![0.0; len];
    for i in 0..len {
        data[i] = rng.gen_range(range_start, range_end);
    }
    data
}

pub fn create_delta(seed: usize, iteration: usize) -> f32 {
    let seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(seed);
    rng.gen_range(-10.0, 10.0)
}

pub fn create_random_multitones(seed: usize,
                         iteration: usize,
                         from: usize,
                         to: usize,
                         number_of_tones: usize) -> Vec<f32> {
    let len_seed: &[_] = &[seed, iteration];
    let mut rng: StdRng = SeedableRng::from_seed(len_seed);
    let len = 2 * rng.gen_range(from, to);
    let mut result = vec![0.0; len].to_real_time_vec();
    for _ in 0..number_of_tones {
        let mut arg = vec![0.0; len].to_real_time_vec();
        arg.map_inplace((), |_, i, _| i as f32);
        let freq = rng.gen_range(0.24, 0.76);
        let phase = rng.gen_range(-1.0, 1.0);
        arg.scale(freq);
        arg.offset(phase);
        arg.cos();
        result.add(&arg).unwrap();
    }

    let (result, _) = result.get();
    result
}

use std::sync::{Arc, Mutex};

pub const RANGE_SINGLE_CORE: Range<usize> = Range {
    start: 10000,
    end: 100000,
};
pub const RANGE_MULTI_CORE: Range<usize> = Range {
    start: 100001,
    end: 200000,
};

pub fn parameterized_vector_test<F>(test_code: F)
    where F: Fn(usize, Range<usize>) + Send + 'static + Sync
{
    let mut test_errors = Vec::new();

    // I don't know if there is a good reason for this, but Rust
    // requires us to lock the test_code function,
    // does catch_panic spawn really a new thread?
    let test_code = Arc::new(Mutex::new(test_code));
    for iteration in 0..10 {
        if test_errors.len() > 0 {
            break; // Stop on the first error to speed up things
        }

        let small_range = RANGE_SINGLE_CORE;
        let test_code = test_code.clone();
        let safe_iteration = panic::AssertUnwindSafe(iteration);
        let small_range = panic::AssertUnwindSafe(small_range);
        let test_code = panic::AssertUnwindSafe(test_code);
        let result = panic::catch_unwind(move || {
            let test_code = test_code.lock().unwrap();
            test_code(*safe_iteration, (*small_range).clone());
        });

        match result {
            Ok(_) => (),
            Err(e) => {
                if let Some(e) = e.downcast_ref::<&'static str>() {
                    test_errors.push(format!("\nSingle threaded execution path failed on iteration \
                                       {}\nFailure: {}",
                                      iteration,
                                      e));
                } else if let Some(e) = e.downcast_ref::<String>() {
                    test_errors.push(format!("\nSingle threaded execution path failed on iteration \
                                       {}\nFailure: {}",
                                      iteration,
                                      e));
                } else {
                    test_errors.push(format!("\nSingle threaded execution path failed on iteration \
                                       {}\nGot an unknown error: {:?}",
                                      iteration,
                                      e));
                }
            }
        }
    }

    for iteration in 0..3 {
        if test_errors.len() > 0 {
            break; // Stop on the first error to speed up things
        }

        let large_range = RANGE_MULTI_CORE;
        let test_code = test_code.clone();
        let safe_iteration = panic::AssertUnwindSafe(iteration);
        let large_range = panic::AssertUnwindSafe(large_range);
        let test_code = panic::AssertUnwindSafe(test_code);
        let result = panic::catch_unwind(move || {
            let test_code = test_code.lock().unwrap();
            test_code(*safe_iteration, (*large_range).clone());
        });

        match result {
            Ok(_) => (),
            Err(e) => {
                if let Some(e) = e.downcast_ref::<&'static str>() {
                    test_errors.push(format!("\nMulti threaded execution path failed on \
                                              iteration {}\nFailure: {}",
                                             iteration,
                                             e));
                } else if let Some(e) = e.downcast_ref::<String>() {
                    test_errors.push(format!("\nMulti threaded execution path failed on \
                                              iteration {}\nFailure: {}",
                                             iteration,
                                             e));
                } else {
                    test_errors.push(format!("\nMulti threaded execution path failed on \
                                              iteration {}\nGot an unknown error: {:?}",
                                             iteration,
                                             e));
                }
            }
        }
    }

    if test_errors.len() > 0 {
        let error_messages = test_errors.join("\n");
        panic!(error_messages);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

use clap::{App, AppSettings, Arg};
use derive_more::From;

use diceware::*;

// #[non_exhaustive] // One day
#[derive(From, Debug)]
pub enum Error {
    // External Errors
    Io(std::io::Error),

    // My errors
    InvalidToken,

    // Allows you to add future errors without breaking compatibility
    // for your user's `match` arms.
    // This will eventually be done with #[non_exhaustive]
    #[doc(hidden)]
    __Nonexhaustive,
}

pub type Result<T> = std::result::Result<T, Error>;

fn main() -> Result<()> {
    let matches = App::new(crate_name!())
        .version(crate_version!())
        .about(crate_description!())
        .setting(AppSettings::DisableVersion) // no --version flag
        .setting(AppSettings::UnifiedHelpMessage)
        .arg(
            Arg::with_name("SEPARATOR")
                .short("j")
                .long("join")
                .help("Join words using separator [default: \\n]")
                .default_value("\n")
                .hide_default_value(true) // it doesn't print properly
                .takes_value(true),
        )
        .arg(
            Arg::with_name("NUMBER")
                .required(false)
                .help("Sets the number of diceware words to select")
                .default_value("4")
                .index(1),
        )
        .get_matches();

    let number = value_t!(matches.value_of("NUMBER"), u16).unwrap_or_else(|e| e.exit());

    // no longer using a functional word stream
    // it would be nice to do that again sometime.

    // let word_list = get_word_list();

    // let word_stream = iter::repeat_with(|| get_diceware_word(&word_list));
    // let mut words = word_stream.take(number as usize);

    // let separator = matches.value_of("SEPARATOR").unwrap_or("\n");
    // if let Some(word) = words.next() {
    //     print!("{}", word);
    //     for word in words {
    //         print!("{}", separator);
    //         print!("{}", word);
    //     }
    //     println!();
    // }

    let mut words = Vec::<String>::new();

    for _ in 0..number {
        let diceroll = roll();
        let word = get_word(&diceroll).unwrap();
        words.push(word);
    }

    let separator = matches.value_of("SEPARATOR").unwrap_or("\n");
    print!("{}", words.join(separator));
    println!();

    Ok(())
}
<commit_msg>Handle invalid rolls.  Adjust CLI argparse code.<commit_after>#[macro_use]
extern crate clap;

use clap::{App, AppSettings, Arg};
use derive_more::From;

use crate::Error::NoWordForRoll;
use diceware::*;

// #[non_exhaustive] // One day
#[derive(From, Debug)]
pub enum Error {
    // External Errors
    Io(std::io::Error),

    // My errors
    NoWordForRoll {
        roll: String,
    },

    // Allows you to add future errors without breaking compatibility
    // for your user's `match` arms.
    // This will eventually be done with #[non_exhaustive]
    #[doc(hidden)]
    __Nonexhaustive,
}

pub type Result<T> = std::result::Result<T, Error>;

fn main() -> Result<()> {
    let matches = App::new(crate_name!())
        .version(crate_version!())
        .about(crate_description!())
        .setting(AppSettings::DisableVersion) // no --version flag
        .setting(AppSettings::UnifiedHelpMessage)
        .arg(
            Arg::with_name("SEPARATOR")
                .short("j")
                .long("join")
                .takes_value(true)
                .default_value("\n")
                .hide_default_value(true) // it doesn't print properly
                .help("Join words using separator [default: \\n]"),
        )
        .arg(
            Arg::with_name("NUMBER")
                .required(false)
                .default_value("4")
                .help("Sets the number of diceware words to select"),
        )
        .get_matches();

    let separator = matches.value_of("SEPARATOR").unwrap_or("\n");
    let number = value_t!(matches.value_of("NUMBER"), u16).unwrap_or_else(|e| e.exit());

    // no longer using a functional word stream
    // it would be nice to do that again sometime.

    // let word_list = get_word_list();

    // let word_stream = iter::repeat_with(|| get_diceware_word(&word_list));
    // let mut words = word_stream.take(number as usize);

    // let separator = matches.value_of("SEPARATOR").unwrap_or("\n");
    // if let Some(word) = words.next() {
    //     print!("{}", word);
    //     for word in words {
    //         print!("{}", separator);
    //         print!("{}", word);
    //     }
    //     println!();
    // }

    let mut words = Vec::<String>::new();

    for _ in 0..number {
        let diceroll = roll();
        match get_word(&diceroll) {
            Some(word) => words.push(word),
            None => return Err(NoWordForRoll { roll: diceroll }),
        }
    }

    print!("{}", words.join(separator));
    println!();

    Ok(())
}
<|endoftext|>