<commit_before>use clap::crate_version;

use std::env;
use std::path::{Path, PathBuf};

use clap::{App, AppSettings, ArgMatches, SubCommand};

use mdbook::errors::Result as Result3;
use mdbook::MDBook;

use failure::Error;
#[cfg(feature = "linkcheck")]
use mdbook::renderer::RenderContext;
#[cfg(feature = "linkcheck")]
use mdbook_linkcheck::{self, errors::BrokenLinks};

fn main() {
    let d_message = "-d, --dest-dir=[dest-dir]
'The output directory for your book{n}(Defaults to ./book when omitted)'";
    let dir_message = "[dir]
'A directory for your book{n}(Defaults to Current Directory when omitted)'";

    let matches = App::new("rustbook")
        .about("Build a book with mdBook")
        .author("Steve Klabnik <steve@steveklabnik.com>")
        .version(&*format!("v{}", crate_version!()))
        .setting(AppSettings::SubcommandRequired)
        .subcommand(
            SubCommand::with_name("build")
                .about("Build the book from the markdown files")
                .arg_from_usage(d_message)
                .arg_from_usage(dir_message),
        )
        .subcommand(
            SubCommand::with_name("linkcheck")
                .about("Run linkcheck with mdBook 3")
                .arg_from_usage(dir_message),
        )
        .get_matches();

    // Check which subcomamnd the user ran...
    match matches.subcommand() {
        ("build", Some(sub_matches)) => {
            if let Err(e) = build(sub_matches) {
                eprintln!("Error: {}", e);

                for cause in e.iter().skip(1) {
                    eprintln!("\tCaused By: {}", cause);
                }

                ::std::process::exit(101);
            }
        }
        ("linkcheck", Some(sub_matches)) => {
            if let Err(err) = linkcheck(sub_matches) {
                eprintln!("Error: {}", err);

                // HACK: ignore timeouts
                let actually_broken = {
                    #[cfg(feature = "linkcheck")]
                    {
                        err.downcast::<BrokenLinks>()
                            .map(|broken_links| {
                                broken_links
                                    .links()
                                    .iter()
                                    .inspect(|cause| eprintln!("\tCaused By: {}", cause))
                                    .any(|cause| !format!("{}", cause).contains("timed out"))
                            })
                            .unwrap_or(false)
                    }

                    #[cfg(not(feature = "linkcheck"))]
                    {
                        false
                    }
                };

                if actually_broken {
                    std::process::exit(101);
                } else {
                    std::process::exit(0);
                }
            }
        }
        (_, _) => unreachable!(),
    };
}

#[cfg(feature = "linkcheck")]
pub fn linkcheck(args: &ArgMatches<'_>) -> Result<(), Error> {
    let book_dir = get_book_dir(args);
    let book = MDBook::load(&book_dir).unwrap();
    let cfg = book.config;
    let render_ctx = RenderContext::new(&book_dir, book.book, cfg, &book_dir);

    mdbook_linkcheck::check_links(&render_ctx)
}

#[cfg(not(feature = "linkcheck"))]
pub fn linkcheck(_args: &ArgMatches<'_>) -> Result<(), Error> {
    println!("mdbook-linkcheck is disabled.");
    Ok(())
}

// Build command implementation
pub fn build(args: &ArgMatches<'_>) -> Result3<()> {
    let book_dir = get_book_dir(args);
    let mut book = MDBook::load(&book_dir)?;

    // Set this to allow us to catch bugs in advance.
    book.config.build.create_missing = false;

    if let Some(dest_dir) = args.value_of("dest-dir") {
        book.config.build.build_dir = PathBuf::from(dest_dir);
    }

    book.build()?;

    Ok(())
}

fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf {
    if let Some(dir) = args.value_of("dir") {
        // Check if path is relative from current dir, or absolute...
        let p = Path::new(dir);
        if p.is_relative() {
            env::current_dir().unwrap().join(dir)
        } else {
            p.to_path_buf()
        }
    } else {
        env::current_dir().unwrap()
    }
}
<commit_msg>fix reviewer comments<commit_after>use clap::crate_version;

use std::env;
use std::path::{Path, PathBuf};

use clap::{App, AppSettings, ArgMatches, SubCommand};

use mdbook::errors::Result as Result3;
use mdbook::MDBook;

#[cfg(feature = "linkcheck")]
use failure::Error;
#[cfg(feature = "linkcheck")]
use mdbook::renderer::RenderContext;
#[cfg(feature = "linkcheck")]
use mdbook_linkcheck::{self, errors::BrokenLinks};

fn main() {
    let d_message = "-d, --dest-dir=[dest-dir]
'The output directory for your book{n}(Defaults to ./book when omitted)'";
    let dir_message = "[dir]
'A directory for your book{n}(Defaults to Current Directory when omitted)'";

    let matches = App::new("rustbook")
        .about("Build a book with mdBook")
        .author("Steve Klabnik <steve@steveklabnik.com>")
        .version(&*format!("v{}", crate_version!()))
        .setting(AppSettings::SubcommandRequired)
        .subcommand(
            SubCommand::with_name("build")
                .about("Build the book from the markdown files")
                .arg_from_usage(d_message)
                .arg_from_usage(dir_message),
        )
        .subcommand(
            SubCommand::with_name("linkcheck")
                .about("Run linkcheck with mdBook 3")
                .arg_from_usage(dir_message),
        )
        .get_matches();

    // Check which subcomamnd the user ran...
    match matches.subcommand() {
        ("build", Some(sub_matches)) => {
            if let Err(e) = build(sub_matches) {
                eprintln!("Error: {}", e);

                for cause in e.iter().skip(1) {
                    eprintln!("\tCaused By: {}", cause);
                }

                ::std::process::exit(101);
            }
        }
        ("linkcheck", Some(sub_matches)) => {
            #[cfg(feature = "linkcheck")]
            {
                if let Err(err) = linkcheck(sub_matches) {
                    eprintln!("Error: {}", err);

                    // HACK: ignore timeouts
                    let actually_broken = err
                        .downcast::<BrokenLinks>()
                        .map(|broken_links| {
                            broken_links
                                .links()
                                .iter()
                                .inspect(|cause| eprintln!("\tCaused By: {}", cause))
                                .fold(false, |already_broken, cause| {
                                    already_broken || !format!("{}", cause).contains("timed out")
                                })
                        })
                        .unwrap_or(false);

                    if actually_broken {
                        std::process::exit(101);
                    } else {
                        std::process::exit(0);
                    }
                }
            }

            #[cfg(not(feature = "linkcheck"))]
            {
                // This avoids the `unused_binding` lint.
                println!(
                    "mdbook-linkcheck is disabled, but arguments were passed: {:?}",
                    sub_matches
                );
            }
        }
        (_, _) => unreachable!(),
    };
}

#[cfg(feature = "linkcheck")]
pub fn linkcheck(args: &ArgMatches<'_>) -> Result<(), Error> {
    let book_dir = get_book_dir(args);
    let book = MDBook::load(&book_dir).unwrap();
    let cfg = book.config;
    let render_ctx = RenderContext::new(&book_dir, book.book, cfg, &book_dir);

    mdbook_linkcheck::check_links(&render_ctx)
}

// Build command implementation
pub fn build(args: &ArgMatches<'_>) -> Result3<()> {
    let book_dir = get_book_dir(args);
    let mut book = MDBook::load(&book_dir)?;

    // Set this to allow us to catch bugs in advance.
    book.config.build.create_missing = false;

    if let Some(dest_dir) = args.value_of("dest-dir") {
        book.config.build.build_dir = PathBuf::from(dest_dir);
    }

    book.build()?;

    Ok(())
}

fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf {
    if let Some(dir) = args.value_of("dir") {
        // Check if path is relative from current dir, or absolute...
        let p = Path::new(dir);
        if p.is_relative() {
            env::current_dir().unwrap().join(dir)
        } else {
            p.to_path_buf()
        }
    } else {
        env::current_dir().unwrap()
    }
}
<|endoftext|>


<commit_before>// Functionality that is shared between the cxx_build::bridge entry point and
// the cxxbridge CLI command.

mod alphasort;
mod builtin;
mod check;
pub(super) mod error;
mod file;
pub(super) mod fs;
mod ifndef;
pub(super) mod include;
pub(super) mod out;
mod write;

pub(super) use self::error::Error;
use self::error::{format_err, Result};
use self::file::File;
use self::include::Include;
use crate::syntax::report::Errors;
use crate::syntax::{self, Types};
use std::path::Path;

/// Options for C++ code generation.
///
/// We expect options to be added over time, so this is a non-exhaustive struct.
/// To instantiate one you need to crate a default value and mutate those fields
/// that you want to modify.
///
/// ```
/// # use cxx_gen::Opt;
/// #
/// let impl_annotations = r#"__attribute__((visibility("default")))"#.to_owned();
///
/// let mut opt = Opt::default();
/// opt.cxx_impl_annotations = Some(impl_annotations);
/// ```
#[non_exhaustive]
pub struct Opt {
    /// Any additional headers to #include. The cxxbridge tool does not parse or
    /// even require the given paths to exist; they simply go into the generated
    /// C++ code as #include lines.
    pub include: Vec<Include>,
    /// Optional annotation for implementations of C++ function wrappers that
    /// may be exposed to Rust. You may for example need to provide
    /// `__declspec(dllexport)` or `__attribute__((visibility("default")))` if
    /// Rust code from one shared object or executable depends on these C++
    /// functions in another.
    pub cxx_impl_annotations: Option<String>,

    pub(super) gen_header: bool,
    pub(super) gen_implementation: bool,
    pub(super) allow_dot_includes: bool,
}

/// Results of code generation.
#[derive(Default)]
pub struct GeneratedCode {
    /// The bytes of a C++ header file.
    pub header: Vec<u8>,
    /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.)
    pub implementation: Vec<u8>,
}

impl Default for Opt {
    fn default() -> Self {
        Opt {
            include: Vec::new(),
            cxx_impl_annotations: None,
            gen_header: true,
            gen_implementation: true,
            allow_dot_includes: true,
        }
    }
}

pub(super) fn generate_from_path(path: &Path, opt: &Opt) -> GeneratedCode {
    let source = match read_to_string(path) {
        Ok(source) => source,
        Err(err) => format_err(path, "", err),
    };
    match generate_from_string(&source, opt) {
        Ok(out) => out,
        Err(err) => format_err(path, &source, err),
    }
}

fn read_to_string(path: &Path) -> Result<String> {
    let bytes = if path == Path::new("-") {
        fs::read_stdin()
    } else {
        fs::read(path)
    }?;
    match String::from_utf8(bytes) {
        Ok(string) => Ok(string),
        Err(err) => Err(Error::Utf8(path.to_owned(), err.utf8_error())),
    }
}

fn generate_from_string(source: &str, opt: &Opt) -> Result<GeneratedCode> {
    let mut source = source;
    if source.starts_with("#!") && !source.starts_with("#![") {
        let shebang_end = source.find('\n').unwrap_or(source.len());
        source = &source[shebang_end..];
    }
    proc_macro2::fallback::force();
    let syntax: File = syn::parse_str(source)?;
    generate(syntax, opt)
}

pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
    if syntax.modules.is_empty() {
        return Err(Error::NoBridgeMod);
    }

    let ref mut apis = Vec::new();
    let ref mut errors = Errors::new();
    for bridge in syntax.modules {
        let ref namespace = bridge.namespace;
        let trusted = bridge.unsafety.is_some();
        apis.extend(syntax::parse_items(
            errors,
            bridge.content,
            trusted,
            namespace,
        ));
    }

    let ref types = Types::collect(errors, apis);
    check::precheck(errors, apis, opt);
    errors.propagate()?;
    check::typecheck(errors, apis, types);
    errors.propagate()?;

    // Some callers may wish to generate both header and implementation from the
    // same token stream to avoid parsing twice. Others only need to generate
    // one or the other.
    Ok(GeneratedCode {
        header: if opt.gen_header {
            write::gen(apis, types, opt, true)
        } else {
            Vec::new()
        },
        implementation: if opt.gen_implementation {
            write::gen(apis, types, opt, false)
        } else {
            Vec::new()
        },
    })
}
<commit_msg>Condense creation of GeneratedCode<commit_after>// Functionality that is shared between the cxx_build::bridge entry point and
// the cxxbridge CLI command.

mod alphasort;
mod builtin;
mod check;
pub(super) mod error;
mod file;
pub(super) mod fs;
mod ifndef;
pub(super) mod include;
pub(super) mod out;
mod write;

pub(super) use self::error::Error;
use self::error::{format_err, Result};
use self::file::File;
use self::include::Include;
use crate::syntax::report::Errors;
use crate::syntax::{self, Types};
use std::path::Path;

/// Options for C++ code generation.
///
/// We expect options to be added over time, so this is a non-exhaustive struct.
/// To instantiate one you need to crate a default value and mutate those fields
/// that you want to modify.
///
/// ```
/// # use cxx_gen::Opt;
/// #
/// let impl_annotations = r#"__attribute__((visibility("default")))"#.to_owned();
///
/// let mut opt = Opt::default();
/// opt.cxx_impl_annotations = Some(impl_annotations);
/// ```
#[non_exhaustive]
pub struct Opt {
    /// Any additional headers to #include. The cxxbridge tool does not parse or
    /// even require the given paths to exist; they simply go into the generated
    /// C++ code as #include lines.
    pub include: Vec<Include>,
    /// Optional annotation for implementations of C++ function wrappers that
    /// may be exposed to Rust. You may for example need to provide
    /// `__declspec(dllexport)` or `__attribute__((visibility("default")))` if
    /// Rust code from one shared object or executable depends on these C++
    /// functions in another.
    pub cxx_impl_annotations: Option<String>,

    pub(super) gen_header: bool,
    pub(super) gen_implementation: bool,
    pub(super) allow_dot_includes: bool,
}

/// Results of code generation.
#[derive(Default)]
pub struct GeneratedCode {
    /// The bytes of a C++ header file.
    pub header: Vec<u8>,
    /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.)
    pub implementation: Vec<u8>,
}

impl Default for Opt {
    fn default() -> Self {
        Opt {
            include: Vec::new(),
            cxx_impl_annotations: None,
            gen_header: true,
            gen_implementation: true,
            allow_dot_includes: true,
        }
    }
}

pub(super) fn generate_from_path(path: &Path, opt: &Opt) -> GeneratedCode {
    let source = match read_to_string(path) {
        Ok(source) => source,
        Err(err) => format_err(path, "", err),
    };
    match generate_from_string(&source, opt) {
        Ok(out) => out,
        Err(err) => format_err(path, &source, err),
    }
}

fn read_to_string(path: &Path) -> Result<String> {
    let bytes = if path == Path::new("-") {
        fs::read_stdin()
    } else {
        fs::read(path)
    }?;
    match String::from_utf8(bytes) {
        Ok(string) => Ok(string),
        Err(err) => Err(Error::Utf8(path.to_owned(), err.utf8_error())),
    }
}

fn generate_from_string(source: &str, opt: &Opt) -> Result<GeneratedCode> {
    let mut source = source;
    if source.starts_with("#!") && !source.starts_with("#![") {
        let shebang_end = source.find('\n').unwrap_or(source.len());
        source = &source[shebang_end..];
    }
    proc_macro2::fallback::force();
    let syntax: File = syn::parse_str(source)?;
    generate(syntax, opt)
}

pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
    if syntax.modules.is_empty() {
        return Err(Error::NoBridgeMod);
    }

    let ref mut apis = Vec::new();
    let ref mut errors = Errors::new();
    for bridge in syntax.modules {
        let ref namespace = bridge.namespace;
        let trusted = bridge.unsafety.is_some();
        apis.extend(syntax::parse_items(
            errors,
            bridge.content,
            trusted,
            namespace,
        ));
    }

    let ref types = Types::collect(errors, apis);
    check::precheck(errors, apis, opt);
    errors.propagate()?;
    check::typecheck(errors, apis, types);
    errors.propagate()?;

    // Some callers may wish to generate both header and implementation from the
    // same token stream to avoid parsing twice. Others only need to generate
    // one or the other.
    let (mut header, mut implementation) = Default::default();
    if opt.gen_header {
        header = write::gen(apis, types, opt, true);
    }
    if opt.gen_implementation {
        implementation = write::gen(apis, types, opt, false);
    }
    Ok(GeneratedCode {
        header,
        implementation,
    })
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io
use rustless;
use serde;
use serde_json;
use rustc_serialize::json;
use rustless::server::status;
use rustless::{Api, Nesting, Versioning};
use valico::json_dsl;
use valico::common::error as valico_error;
use super::query;
use model::v1::*;
use model;

fn render<T>(mut client: rustless::Client,
             obj: T)
             -> Result<rustless::Client, rustless::ErrorResponse>
    where T: serde::Serialize
{
    client.set_json_content_type();
    client.text(serde_json::to_string(&obj).unwrap())
}

pub fn root() -> rustless::Api {
    Api::build(|api| {
        api.get("", |endpoint| {
            endpoint.handle(|client, _params| {
                let desc = EndPoint { description: "autocomplete service".to_string() };
                render(client, desc)
            })
        });

        api.error_formatter(|error, _media| {
            let err = if error.is::<rustless::errors::Validation>() {
                let val_err = error.downcast::<rustless::errors::Validation>().unwrap();
                //TODO better message, we shouldn't use {:?} but access the `path` and `detail` of all errrors in val_err.reason
                CustomError {short: "validation error".to_string(), long: format!("invalid arguments {:?}", val_err.reason)}
            } else {
                CustomError {short: "bad_request".to_string(), long: format!("bad request, error: {}", error)}
            };
            let mut resp = rustless::Response::from(status::StatusCode::BadRequest, Box::new(serde_json::to_string(&err).unwrap()));
            resp.set_json_content_type();
            Some(resp)
        });
        api.mount(v1());
    })
}

pub fn v1() -> rustless::Api {
    Api::build(|api| {
        api.version("v1", Versioning::Path);

        api.get("", |endpoint| {
            endpoint.desc("api interface version v1");
            endpoint.handle(|client, _params| {
                render(client,
                       V1Reponse::Response { description: "api version 1".to_string() })
            })
        });
        api.mount(status());
        api.mount(autocomplete());
    })
}

pub fn status() -> rustless::Api {
    Api::build(|api| {
        api.get("status", |endpoint| {
            endpoint.handle(|client, _params| {
                let status = Status {
                    version: "14".to_string(),
                    status: "good".to_string(),
                };
                render(client, status)
            })
        });
    })
}

fn check_bound(val: &json::Json,
               path: &str,
               min: f64,
               max: f64,
               error_msg: &str)
               -> Result<(), valico_error::ValicoErrors> {
    if let json::Json::F64(lon) = *val {
        if min <= lon && lon <= max {
            Ok(())
        } else {
            Err(vec![Box::new(json_dsl::errors::WrongValue {
                         path: path.to_string(),
                         detail: Some(error_msg.to_string()),
                     })])
        }
    } else {
        panic!("should never happen, already checked");
    }
}

pub fn autocomplete() -> rustless::Namespace {
    rustless::Namespace::build("autocomplete", |ns| {
        ns.get("", |endpoint| {
            endpoint.params(|params| {
                params.req_typed("q", json_dsl::string());

                params.opt("lon", |lon| {
                    lon.coerce(json_dsl::f64());
                    lon.validate_with(|val, path| {
                        check_bound(val, path, -180f64, 180f64, "lon is not a valid longitude")
                    });
                });

                params.opt("lat", |lat| {
                    lat.coerce(json_dsl::f64());
                    lat.validate_with(|val, path| {
                        check_bound(val, path, -90f64, 900f64, "lat is not a valid latitude")
                    });
                });
                params.validate_with(|val, path| {
                    // if we have a lat we should have a lon (and the opposite)
                    if let json::Json::Object(ref obj) = *val {
                        let has_lon = obj.get("lon").is_some();
                        let has_lat = obj.get("lat").is_some();
                        if has_lon ^ has_lat {
                            Err(vec![Box::new(json_dsl::errors::WrongValue {
                                         path: path.to_string(),
                                         detail: Some("you need to provide a lon AND a lat if \
                                                       you provide one of them"
                                                          .to_string()),
                                     })])
                        } else {
                            Ok(())
                        }
                    } else {
                        panic!("should never happen, already checked");
                    }
                });
            });
            endpoint.handle(|client, params| {
                let q = params.find("q").unwrap().as_string().unwrap().to_string();
                let lon = params.find("lon").and_then(|p| p.as_f64());
                let lat = params.find("lat").and_then(|p| p.as_f64());
                // we have already checked that if there is a lon, lat is not None, so we can unwrap
                let coord = lon.and_then(|lon| Some(model::Coord{lon: lon, lat: lat.unwrap()}));
                let autocomplete = query::autocomplete(q, coord);
                render(client, autocomplete)
            })
        });
    })
}
<commit_msg>correction after review<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io
use rustless;
use serde;
use serde_json;
use rustc_serialize::json;
use rustless::server::status;
use rustless::{Api, Nesting, Versioning};
use valico::json_dsl;
use valico::common::error as valico_error;
use super::query;
use model::v1::*;
use model;

fn render<T>(mut client: rustless::Client,
             obj: T)
             -> Result<rustless::Client, rustless::ErrorResponse>
    where T: serde::Serialize
{
    client.set_json_content_type();
    client.text(serde_json::to_string(&obj).unwrap())
}

pub fn root() -> rustless::Api {
    Api::build(|api| {
        api.get("", |endpoint| {
            endpoint.handle(|client, _params| {
                let desc = EndPoint { description: "autocomplete service".to_string() };
                render(client, desc)
            })
        });

        api.error_formatter(|error, _media| {
            let err = if error.is::<rustless::errors::Validation>() {
                let val_err = error.downcast::<rustless::errors::Validation>().unwrap();
                //TODO better message, we shouldn't use {:?} but access the `path` and `detail` of all errrors in val_err.reason
                CustomError {short: "validation error".to_string(), long: format!("invalid arguments {:?}", val_err.reason)}
            } else {
                CustomError {short: "bad_request".to_string(), long: format!("bad request, error: {}", error)}
            };
            let mut resp = rustless::Response::from(status::StatusCode::BadRequest, Box::new(serde_json::to_string(&err).unwrap()));
            resp.set_json_content_type();
            Some(resp)
        });
        api.mount(v1());
    })
}

pub fn v1() -> rustless::Api {
    Api::build(|api| {
        api.version("v1", Versioning::Path);

        api.get("", |endpoint| {
            endpoint.desc("api interface version v1");
            endpoint.handle(|client, _params| {
                render(client,
                       V1Reponse::Response { description: "api version 1".to_string() })
            })
        });
        api.mount(status());
        api.mount(autocomplete());
    })
}

pub fn status() -> rustless::Api {
    Api::build(|api| {
        api.get("status", |endpoint| {
            endpoint.handle(|client, _params| {
                let status = Status {
                    version: "14".to_string(),
                    status: "good".to_string(),
                };
                render(client, status)
            })
        });
    })
}

fn check_bound(val: &json::Json,
               path: &str,
               min: f64,
               max: f64,
               error_msg: &str)
               -> Result<(), valico_error::ValicoErrors> {
    if let json::Json::F64(lon) = *val {
        if min <= lon && lon <= max {
            Ok(())
        } else {
            Err(vec![Box::new(json_dsl::errors::WrongValue {
                         path: path.to_string(),
                         detail: Some(error_msg.to_string()),
                     })])
        }
    } else {
        panic!("should never happen, already checked");
    }
}

pub fn autocomplete() -> rustless::Namespace {
    rustless::Namespace::build("autocomplete", |ns| {
        ns.get("", |endpoint| {
            endpoint.params(|params| {
                params.req_typed("q", json_dsl::string());

                params.opt("lon", |lon| {
                    lon.coerce(json_dsl::f64());
                    lon.validate_with(|val, path| {
                        check_bound(val, path, -180f64, 180f64, "lon is not a valid longitude")
                    });
                });

                params.opt("lat", |lat| {
                    lat.coerce(json_dsl::f64());
                    lat.validate_with(|val, path| {
                        check_bound(val, path, -90f64, 90f64, "lat is not a valid latitude")
                    });
                });
                params.validate_with(|val, path| {
                    // if we have a lat we should have a lon (and the opposite)
                    if let json::Json::Object(ref obj) = *val {
                        let has_lon = obj.get("lon").is_some();
                        let has_lat = obj.get("lat").is_some();
                        if has_lon ^ has_lat {
                            Err(vec![Box::new(json_dsl::errors::WrongValue {
                                         path: path.to_string(),
                                         detail: Some("you need to provide a lon AND a lat if \
                                                       you provide one of them"
                                                          .to_string()),
                                     })])
                        } else {
                            Ok(())
                        }
                    } else {
                        panic!("should never happen, already checked");
                    }
                });
            });
            endpoint.handle(|client, params| {
                let q = params.find("q").unwrap().as_string().unwrap().to_string();
                let lon = params.find("lon").and_then(|p| p.as_f64());
                let lat = params.find("lat").and_then(|p| p.as_f64());
                // we have already checked that if there is a lon, lat is not None, so we can unwrap
                let coord = lon.and_then(|lon| Some(model::Coord{lon: lon, lat: lat.unwrap()}));
                let autocomplete = query::autocomplete(q, coord);
                render(client, autocomplete)
            })
        });
    })
}
<|endoftext|>


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

//! Scoped thread-local storage
//!
//! This module provides the ability to generate *scoped* thread-local
//! variables. In this sense, scoped indicates that thread local storage
//! actually stores a reference to a value, and this reference is only placed
//! in storage for a scoped amount of time.
//!
//! There are no restrictions on what types can be placed into a scoped
//! variable, but all scoped variables are initialized to the equivalent of
//! null. Scoped thread local storage is useful when a value is present for a known
//! period of time and it is not required to relinquish ownership of the
//! contents.
//!
//! # Example
//!
//! ```
//! scoped_thread_local!(static FOO: uint);
//!
//! // Initially each scoped slot is empty.
//! assert!(!FOO.is_set());
//!
//! // When inserting a value, the value is only in place for the duration
//! // of the closure specified.
//! FOO.set(&1, || {
//!     FOO.with(|slot| {
//!         assert_eq!(*slot, 1);
//!     });
//! });
//! ```

#![macro_escape]

use prelude::*;

// macro hygiene sure would be nice, wouldn't it?
#[doc(hidden)] pub use self::imp::KeyInner;
#[doc(hidden)] pub use sys_common::thread_local::INIT as OS_INIT;

/// Type representing a thread local storage key corresponding to a reference
/// to the type parameter `T`.
///
/// Keys are statically allocated and can contain a reference to an instance of
/// type `T` scoped to a particular lifetime. Keys provides two methods, `set`
/// and `with`, both of which currently use closures to control the scope of
/// their contents.
pub struct Key<T> { #[doc(hidden)] pub inner: KeyInner<T> }

/// Declare a new scoped thread local storage key.
///
/// This macro declares a `static` item on which methods are used to get and
/// set the value stored within.
#[macro_export]
macro_rules! scoped_thread_local {
    (static $name:ident: $t:ty) => (
        __scoped_thread_local_inner!(static $name: $t)
    );
    (pub static $name:ident: $t:ty) => (
        __scoped_thread_local_inner!(pub static $name: $t)
    );
}

#[macro_export]
#[doc(hidden)]
macro_rules! __scoped_thread_local_inner {
    (static $name:ident: $t:ty) => (
        #[cfg_attr(not(any(windows, target_os = "android", target_os = "ios")),
                   thread_local)]
        static $name: ::std::thread_local::scoped::Key<$t> =
            __scoped_thread_local_inner!($t);
    );
    (pub static $name:ident: $t:ty) => (
        #[cfg_attr(not(any(windows, target_os = "android", target_os = "ios")),
                   thread_local)]
        pub static $name: ::std::thread_local::scoped::Key<$t> =
            __scoped_thread_local_inner!($t);
    );
    ($t:ty) => ({
        use std::thread_local::scoped::Key as __Key;

        #[cfg(not(any(windows, target_os = "android", target_os = "ios")))]
        const INIT: __Key<$t> = __Key {
            inner: ::std::thread_local::scoped::KeyInner {
                inner: ::std::cell::UnsafeCell { value: 0 as *mut _ },
            }
        };

        #[cfg(any(windows, target_os = "android", target_os = "ios"))]
        const INIT: __Key<$t> = __Key {
            inner: ::std::thread_local::scoped::KeyInner {
                inner: ::std::thread_local::scoped::OS_INIT,
                marker: ::std::kinds::marker::InvariantType,
            }
        };

        INIT
    })
}

impl<T> Key<T> {
    /// Insert a value into this scoped thread local storage slot for a
    /// duration of a closure.
    ///
    /// While `cb` is running, the value `t` will be returned by `get` unless
    /// this function is called recursively inside of `cb`.
    ///
    /// Upon return, this function will restore the previous value, if any
    /// was available.
    ///
    /// # Example
    ///
    /// ```
    /// scoped_thread_local!(static FOO: uint);
    ///
    /// FOO.set(&100, || {
    ///     let val = FOO.with(|v| *v);
    ///     assert_eq!(val, 100);
    ///
    ///     // set can be called recursively
    ///     FOO.set(&101, || {
    ///         // ...
    ///     });
    ///
    ///     // Recursive calls restore the previous value.
    ///     let val = FOO.with(|v| *v);
    ///     assert_eq!(val, 100);
    /// });
    /// ```
    pub fn set<R, F>(&'static self, t: &T, cb: F) -> R where
        F: FnOnce() -> R,
    {
        struct Reset<'a, T: 'a> {
            key: &'a KeyInner<T>,
            val: *mut T,
        }
        #[unsafe_destructor]
        impl<'a, T> Drop for Reset<'a, T> {
            fn drop(&mut self) {
                unsafe { self.key.set(self.val) }
            }
        }

        let prev = unsafe {
            let prev = self.inner.get();
            self.inner.set(t as *const T as *mut T);
            prev
        };

        let _reset = Reset { key: &self.inner, val: prev };
        cb()
    }

    /// Get a value out of this scoped variable.
    ///
    /// This function takes a closure which receives the value of this
    /// variable.
    ///
    /// # Panics
    ///
    /// This function will panic if `set` has not previously been called.
    ///
    /// # Example
    ///
    /// ```no_run
    /// scoped_thread_local!(static FOO: uint);
    ///
    /// FOO.with(|slot| {
    ///     // work with `slot`
    /// });
    /// ```
    pub fn with<R, F>(&'static self, cb: F) -> R where
        F: FnOnce(&T) -> R
    {
        unsafe {
            let ptr = self.inner.get();
            assert!(!ptr.is_null(), "cannot access a scoped thread local \
                                     variable without calling `set` first");
            cb(&*ptr)
        }
    }

    /// Test whether this TLS key has been `set` for the current thread.
    pub fn is_set(&'static self) -> bool {
        unsafe { !self.inner.get().is_null() }
    }
}

#[cfg(not(any(windows, target_os = "android", target_os = "ios")))]
mod imp {
    use std::cell::UnsafeCell;

    #[doc(hidden)]
    pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> }

    unsafe impl<T> ::kinds::Sync for KeyInner<T> { }

    #[doc(hidden)]
    impl<T> KeyInner<T> {
        #[doc(hidden)]
        pub unsafe fn set(&self, ptr: *mut T) { *self.inner.get() = ptr; }
        #[doc(hidden)]
        pub unsafe fn get(&self) -> *mut T { *self.inner.get() }
    }
}

#[cfg(any(windows, target_os = "android", target_os = "ios"))]
mod imp {
    use kinds::marker;
    use sys_common::thread_local::StaticKey as OsStaticKey;

    #[doc(hidden)]
    pub struct KeyInner<T> {
        pub inner: OsStaticKey,
        pub marker: marker::InvariantType<T>,
    }

    unsafe impl<T> ::kinds::Sync for KeyInner<T> { }

    #[doc(hidden)]
    impl<T> KeyInner<T> {
        #[doc(hidden)]
        pub unsafe fn set(&self, ptr: *mut T) { self.inner.set(ptr as *mut _) }
        #[doc(hidden)]
        pub unsafe fn get(&self) -> *mut T { self.inner.get() as *mut _ }
    }
}

#[cfg(test)]
mod tests {
    use cell::Cell;
    use prelude::*;

    #[test]
    fn smoke() {
        scoped_thread_local!(static BAR: uint);

        assert!(!BAR.is_set());
        BAR.set(&1, || {
            assert!(BAR.is_set());
            BAR.with(|slot| {
                assert_eq!(*slot, 1);
            });
        });
        assert!(!BAR.is_set());
    }

    #[test]
    fn cell_allowed() {
        scoped_thread_local!(static BAR: Cell<uint>);

        BAR.set(&Cell::new(1), || {
            BAR.with(|slot| {
                assert_eq!(slot.get(), 1);
            });
        });
    }
}
<commit_msg>rollup merge of #20262: arturoc/fix-scoped_thread_local<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Scoped thread-local storage
//!
//! This module provides the ability to generate *scoped* thread-local
//! variables. In this sense, scoped indicates that thread local storage
//! actually stores a reference to a value, and this reference is only placed
//! in storage for a scoped amount of time.
//!
//! There are no restrictions on what types can be placed into a scoped
//! variable, but all scoped variables are initialized to the equivalent of
//! null. Scoped thread local storage is useful when a value is present for a known
//! period of time and it is not required to relinquish ownership of the
//! contents.
//!
//! # Example
//!
//! ```
//! scoped_thread_local!(static FOO: uint);
//!
//! // Initially each scoped slot is empty.
//! assert!(!FOO.is_set());
//!
//! // When inserting a value, the value is only in place for the duration
//! // of the closure specified.
//! FOO.set(&1, || {
//!     FOO.with(|slot| {
//!         assert_eq!(*slot, 1);
//!     });
//! });
//! ```

#![macro_escape]

use prelude::*;

// macro hygiene sure would be nice, wouldn't it?
#[doc(hidden)] pub use self::imp::KeyInner;
#[doc(hidden)] pub use sys_common::thread_local::INIT as OS_INIT;

/// Type representing a thread local storage key corresponding to a reference
/// to the type parameter `T`.
///
/// Keys are statically allocated and can contain a reference to an instance of
/// type `T` scoped to a particular lifetime. Keys provides two methods, `set`
/// and `with`, both of which currently use closures to control the scope of
/// their contents.
pub struct Key<T> { #[doc(hidden)] pub inner: KeyInner<T> }

/// Declare a new scoped thread local storage key.
///
/// This macro declares a `static` item on which methods are used to get and
/// set the value stored within.
#[macro_export]
macro_rules! scoped_thread_local {
    (static $name:ident: $t:ty) => (
        __scoped_thread_local_inner!(static $name: $t);
    );
    (pub static $name:ident: $t:ty) => (
        __scoped_thread_local_inner!(pub static $name: $t);
    );
}

#[macro_export]
#[doc(hidden)]
macro_rules! __scoped_thread_local_inner {
    (static $name:ident: $t:ty) => (
        #[cfg_attr(not(any(windows, target_os = "android", target_os = "ios")),
                   thread_local)]
        static $name: ::std::thread_local::scoped::Key<$t> =
            __scoped_thread_local_inner!($t);
    );
    (pub static $name:ident: $t:ty) => (
        #[cfg_attr(not(any(windows, target_os = "android", target_os = "ios")),
                   thread_local)]
        pub static $name: ::std::thread_local::scoped::Key<$t> =
            __scoped_thread_local_inner!($t);
    );
    ($t:ty) => ({
        use std::thread_local::scoped::Key as __Key;

        #[cfg(not(any(windows, target_os = "android", target_os = "ios")))]
        const INIT: __Key<$t> = __Key {
            inner: ::std::thread_local::scoped::KeyInner {
                inner: ::std::cell::UnsafeCell { value: 0 as *mut _ },
            }
        };

        #[cfg(any(windows, target_os = "android", target_os = "ios"))]
        const INIT: __Key<$t> = __Key {
            inner: ::std::thread_local::scoped::KeyInner {
                inner: ::std::thread_local::scoped::OS_INIT,
                marker: ::std::kinds::marker::InvariantType,
            }
        };

        INIT
    })
}

impl<T> Key<T> {
    /// Insert a value into this scoped thread local storage slot for a
    /// duration of a closure.
    ///
    /// While `cb` is running, the value `t` will be returned by `get` unless
    /// this function is called recursively inside of `cb`.
    ///
    /// Upon return, this function will restore the previous value, if any
    /// was available.
    ///
    /// # Example
    ///
    /// ```
    /// scoped_thread_local!(static FOO: uint);
    ///
    /// FOO.set(&100, || {
    ///     let val = FOO.with(|v| *v);
    ///     assert_eq!(val, 100);
    ///
    ///     // set can be called recursively
    ///     FOO.set(&101, || {
    ///         // ...
    ///     });
    ///
    ///     // Recursive calls restore the previous value.
    ///     let val = FOO.with(|v| *v);
    ///     assert_eq!(val, 100);
    /// });
    /// ```
    pub fn set<R, F>(&'static self, t: &T, cb: F) -> R where
        F: FnOnce() -> R,
    {
        struct Reset<'a, T: 'a> {
            key: &'a KeyInner<T>,
            val: *mut T,
        }
        #[unsafe_destructor]
        impl<'a, T> Drop for Reset<'a, T> {
            fn drop(&mut self) {
                unsafe { self.key.set(self.val) }
            }
        }

        let prev = unsafe {
            let prev = self.inner.get();
            self.inner.set(t as *const T as *mut T);
            prev
        };

        let _reset = Reset { key: &self.inner, val: prev };
        cb()
    }

    /// Get a value out of this scoped variable.
    ///
    /// This function takes a closure which receives the value of this
    /// variable.
    ///
    /// # Panics
    ///
    /// This function will panic if `set` has not previously been called.
    ///
    /// # Example
    ///
    /// ```no_run
    /// scoped_thread_local!(static FOO: uint);
    ///
    /// FOO.with(|slot| {
    ///     // work with `slot`
    /// });
    /// ```
    pub fn with<R, F>(&'static self, cb: F) -> R where
        F: FnOnce(&T) -> R
    {
        unsafe {
            let ptr = self.inner.get();
            assert!(!ptr.is_null(), "cannot access a scoped thread local \
                                     variable without calling `set` first");
            cb(&*ptr)
        }
    }

    /// Test whether this TLS key has been `set` for the current thread.
    pub fn is_set(&'static self) -> bool {
        unsafe { !self.inner.get().is_null() }
    }
}

#[cfg(not(any(windows, target_os = "android", target_os = "ios")))]
mod imp {
    use std::cell::UnsafeCell;

    #[doc(hidden)]
    pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> }

    unsafe impl<T> ::kinds::Sync for KeyInner<T> { }

    #[doc(hidden)]
    impl<T> KeyInner<T> {
        #[doc(hidden)]
        pub unsafe fn set(&self, ptr: *mut T) { *self.inner.get() = ptr; }
        #[doc(hidden)]
        pub unsafe fn get(&self) -> *mut T { *self.inner.get() }
    }
}

#[cfg(any(windows, target_os = "android", target_os = "ios"))]
mod imp {
    use kinds::marker;
    use sys_common::thread_local::StaticKey as OsStaticKey;

    #[doc(hidden)]
    pub struct KeyInner<T> {
        pub inner: OsStaticKey,
        pub marker: marker::InvariantType<T>,
    }

    unsafe impl<T> ::kinds::Sync for KeyInner<T> { }

    #[doc(hidden)]
    impl<T> KeyInner<T> {
        #[doc(hidden)]
        pub unsafe fn set(&self, ptr: *mut T) { self.inner.set(ptr as *mut _) }
        #[doc(hidden)]
        pub unsafe fn get(&self) -> *mut T { self.inner.get() as *mut _ }
    }
}

#[cfg(test)]
mod tests {
    use cell::Cell;
    use prelude::*;

    scoped_thread_local!(static FOO: uint);

    #[test]
    fn smoke() {
        scoped_thread_local!(static BAR: uint);

        assert!(!BAR.is_set());
        BAR.set(&1, || {
            assert!(BAR.is_set());
            BAR.with(|slot| {
                assert_eq!(*slot, 1);
            });
        });
        assert!(!BAR.is_set());
    }

    #[test]
    fn cell_allowed() {
        scoped_thread_local!(static BAR: Cell<uint>);

        BAR.set(&Cell::new(1), || {
            BAR.with(|slot| {
                assert_eq!(slot.get(), 1);
            });
        });
    }

    #[test]
    fn scope_item_allowed() {
        assert!(!FOO.is_set());
        FOO.set(&1, || {
            assert!(FOO.is_set());
            FOO.with(|slot| {
                assert_eq!(*slot, 1);
            });
        });
        assert!(!FOO.is_set());
    }
}
<|endoftext|>


<commit_before>use openssl::ssl;
use std::io::net::ip::Port;
use std::io::net::tcp;
use std::io::net::pipe;
use std::io::{Stream, IoResult};

use {ConnectParams, SslMode, NoSsl, PreferSsl, RequireSsl, ConnectTarget};
use error::{ConnectError, PgConnectStreamError, NoSslSupport, SslError, SocketError};
use message;
use message::{SslRequest, WriteMessage};

const DEFAULT_PORT: Port = 5432;

pub enum MaybeSslStream<S> {
    Ssl(ssl::SslStream<S>),
    Normal(S),
}

impl<S: Stream> Reader for MaybeSslStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        match *self {
            MaybeSslStream::Ssl(ref mut s) => s.read(buf),
            MaybeSslStream::Normal(ref mut s) => s.read(buf),
        }
    }
}

impl<S: Stream> Writer for MaybeSslStream<S> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        match *self {
            MaybeSslStream::Ssl(ref mut s) => s.write(buf),
            MaybeSslStream::Normal(ref mut s) => s.write(buf),
        }
    }

    fn flush(&mut self) -> IoResult<()> {
        match *self {
            MaybeSslStream::Ssl(ref mut s) => s.flush(),
            MaybeSslStream::Normal(ref mut s) => s.flush(),
        }
    }
}

pub enum InternalStream {
    TcpStream(tcp::TcpStream),
    UnixStream(pipe::UnixStream),
}

impl Reader for InternalStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        match *self {
            TcpStream(ref mut s) => s.read(buf),
            UnixStream(ref mut s) => s.read(buf),
        }
    }
}

impl Writer for InternalStream {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        match *self {
            TcpStream(ref mut s) => s.write(buf),
            UnixStream(ref mut s) => s.write(buf),
        }
    }

    fn flush(&mut self) -> IoResult<()> {
        match *self {
            TcpStream(ref mut s) => s.flush(),
            UnixStream(ref mut s) => s.flush(),
        }
    }
}

fn open_socket(params: &ConnectParams)
               -> Result<InternalStream, ConnectError> {
    let port = params.port.unwrap_or(DEFAULT_PORT);
    let socket = match params.target {
        ConnectTarget::Tcp(ref host) =>
            tcp::TcpStream::connect(host[], port).map(TcpStream),
        ConnectTarget::Unix(ref path) => {
            let mut path = path.clone();
            path.push(format!(".s.PGSQL.{}", port));
            pipe::UnixStream::connect(&path).map(UnixStream)
        }
    };
    socket.map_err(SocketError)
}

pub fn initialize_stream(params: &ConnectParams, ssl: &SslMode)
                         -> Result<MaybeSslStream<InternalStream>, ConnectError> {
    let mut socket = try!(open_socket(params));

    let (ssl_required, ctx) = match *ssl {
        NoSsl => return Ok(MaybeSslStream::Normal(socket)),
        PreferSsl(ref ctx) => (false, ctx),
        RequireSsl(ref ctx) => (true, ctx)
    };

    try_pg_conn!(socket.write_message(&SslRequest { code: message::SSL_CODE }));
    try_pg_conn!(socket.flush());

    if try_pg_conn!(socket.read_u8()) == 'N' as u8 {
        if ssl_required {
            return Err(NoSslSupport);
        } else {
            return Ok(MaybeSslStream::Normal(socket));
        }
    }

    match ssl::SslStream::new(ctx, socket) {
        Ok(stream) => Ok(MaybeSslStream::Ssl(stream)),
        Err(err) => Err(SslError(err))
    }
}
<commit_msg>Fix the build<commit_after>use openssl::ssl;
use std::io::net::ip::Port;
use std::io::net::tcp;
use std::io::net::pipe;
use std::io::{Stream, IoResult};

use {ConnectParams, SslMode, NoSsl, PreferSsl, RequireSsl, ConnectTarget};
use error::{ConnectError, PgConnectStreamError, NoSslSupport, SslError, SocketError};
use message;
use message::{SslRequest, WriteMessage};

const DEFAULT_PORT: Port = 5432;

pub enum MaybeSslStream<S> {
    Ssl(ssl::SslStream<S>),
    Normal(S),
}

impl<S: Stream> Reader for MaybeSslStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        match *self {
            MaybeSslStream::Ssl(ref mut s) => s.read(buf),
            MaybeSslStream::Normal(ref mut s) => s.read(buf),
        }
    }
}

impl<S: Stream> Writer for MaybeSslStream<S> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        match *self {
            MaybeSslStream::Ssl(ref mut s) => s.write(buf),
            MaybeSslStream::Normal(ref mut s) => s.write(buf),
        }
    }

    fn flush(&mut self) -> IoResult<()> {
        match *self {
            MaybeSslStream::Ssl(ref mut s) => s.flush(),
            MaybeSslStream::Normal(ref mut s) => s.flush(),
        }
    }
}

pub enum InternalStream {
    TcpStream(tcp::TcpStream),
    UnixStream(pipe::UnixStream),
}

impl Reader for InternalStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        match *self {
            TcpStream(ref mut s) => s.read(buf),
            UnixStream(ref mut s) => s.read(buf),
        }
    }
}

impl Writer for InternalStream {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        match *self {
            TcpStream(ref mut s) => s.write(buf),
            UnixStream(ref mut s) => s.write(buf),
        }
    }

    fn flush(&mut self) -> IoResult<()> {
        match *self {
            TcpStream(ref mut s) => s.flush(),
            UnixStream(ref mut s) => s.flush(),
        }
    }
}

fn open_socket(params: &ConnectParams)
               -> Result<InternalStream, ConnectError> {
    let port = params.port.unwrap_or(DEFAULT_PORT);
    let socket = match params.target {
        ConnectTarget::Tcp(ref host) =>
            tcp::TcpStream::connect((host[], port)).map(TcpStream),
        ConnectTarget::Unix(ref path) => {
            let mut path = path.clone();
            path.push(format!(".s.PGSQL.{}", port));
            pipe::UnixStream::connect(&path).map(UnixStream)
        }
    };
    socket.map_err(SocketError)
}

pub fn initialize_stream(params: &ConnectParams, ssl: &SslMode)
                         -> Result<MaybeSslStream<InternalStream>, ConnectError> {
    let mut socket = try!(open_socket(params));

    let (ssl_required, ctx) = match *ssl {
        NoSsl => return Ok(MaybeSslStream::Normal(socket)),
        PreferSsl(ref ctx) => (false, ctx),
        RequireSsl(ref ctx) => (true, ctx)
    };

    try_pg_conn!(socket.write_message(&SslRequest { code: message::SSL_CODE }));
    try_pg_conn!(socket.flush());

    if try_pg_conn!(socket.read_u8()) == 'N' as u8 {
        if ssl_required {
            return Err(NoSslSupport);
        } else {
            return Ok(MaybeSslStream::Normal(socket));
        }
    }

    match ssl::SslStream::new(ctx, socket) {
        Ok(stream) => Ok(MaybeSslStream::Ssl(stream)),
        Err(err) => Err(SslError(err))
    }
}
<|endoftext|>


<commit_before>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, remove_file};
use std::io::{Read, Write, ErrorKind, Result};
use std::path::{PathBuf, Path};

fn test_metadata(bytes: &[u8], path: &Path) -> Result<()> {
    // Test that the file metadata is correct.
    let metadata = path.metadata()?;
    // `path` should point to a file.
    assert!(metadata.is_file());
    // The size of the file must be equal to the number of written bytes.
    assert_eq!(bytes.len() as u64, metadata.len());
    Ok(())
}

fn main() {
    let tmp = std::env::temp_dir();
    let filename = PathBuf::from("miri_test_fs.txt");
    let path = tmp.join(&filename);
    let bytes = b"Hello, World!\n";

    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();

    file.write(bytes).unwrap();
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Test that metadata of an absolute path is correct.
    test_metadata(bytes, &path).unwrap();
    // Test that metadata of a relative path is correct.
    std::env::set_current_dir(&tmp).unwrap();
    test_metadata(bytes, &filename).unwrap();

    // Creating a symbolic link should succeed
    let symlink_path = tmp.join("miri_test_fs_symlink.txt");
    std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
    // Test that the symbolic link has the same contents as the file.
    let mut symlink_file = File::open(&symlink_path).unwrap();
    let mut contents = Vec::new();
    symlink_file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that metadata of a symbolic link is correct.
    test_metadata(bytes, &symlink_path).unwrap();
    // Test that the metadata of a symbolic link is correct when not following it.
    assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink());
    // Removing symbolic link should succeed.
    remove_file(&symlink_path).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();

    // The two following tests also check that the `__errno_location()` shim is working properly.
    // Opening a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());
    // Removing a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, remove_file(&path).unwrap_err().kind());
    // Reading the metadata of a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, test_metadata(bytes, &path).unwrap_err().kind());
}
<commit_msg>Clean paths for robustness<commit_after>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, remove_file};
use std::io::{Read, Write, ErrorKind, Result};
use std::path::{PathBuf, Path};

fn test_metadata(bytes: &[u8], path: &Path) -> Result<()> {
    // Test that the file metadata is correct.
    let metadata = path.metadata()?;
    // `path` should point to a file.
    assert!(metadata.is_file());
    // The size of the file must be equal to the number of written bytes.
    assert_eq!(bytes.len() as u64, metadata.len());
    Ok(())
}

fn main() {
    let tmp = std::env::temp_dir();
    let filename = PathBuf::from("miri_test_fs.txt");
    let path = tmp.join(&filename);
    let symlink_path = tmp.join("miri_test_fs_symlink.txt");
    let bytes = b"Hello, World!\n";
    // Clean the paths for robustness.
    remove_file(&path).unwrap_or(());
    remove_file(&symlink_path).unwrap_or(());

    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();

    file.write(bytes).unwrap();
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Test that metadata of an absolute path is correct.
    test_metadata(bytes, &path).unwrap();
    // Test that metadata of a relative path is correct.
    std::env::set_current_dir(&tmp).unwrap();
    test_metadata(bytes, &filename).unwrap();

    // Creating a symbolic link should succeed.
    std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
    // Test that the symbolic link has the same contents as the file.
    let mut symlink_file = File::open(&symlink_path).unwrap();
    let mut contents = Vec::new();
    symlink_file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that metadata of a symbolic link is correct.
    test_metadata(bytes, &symlink_path).unwrap();
    // Test that the metadata of a symbolic link is correct when not following it.
    assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink());
    // Removing symbolic link should succeed.
    remove_file(&symlink_path).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();

    // The two following tests also check that the `__errno_location()` shim is working properly.
    // Opening a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());
    // Removing a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, remove_file(&path).unwrap_err().kind());
    // Reading the metadata of a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, test_metadata(bytes, &path).unwrap_err().kind());
}
<|endoftext|>


<commit_before>#[cfg(test)]
#[macro_export]
macro_rules! assert_eq_printed {
    ($expected:expr, $got:expr) => {
        let expected = &*$expected;
        let got = &*$got;
        if expected != got {
            panic!("
printed outputs differ!

expected:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

got:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
", expected, got);
        }
    }
}
<commit_msg>grep-printer: add macro docs, redux<commit_after>/// Like assert_eq, but nicer output for long strings.
#[cfg(test)]
#[macro_export]
macro_rules! assert_eq_printed {
    ($expected:expr, $got:expr) => {
        let expected = &*$expected;
        let got = &*$got;
        if expected != got {
            panic!("
printed outputs differ!

expected:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

got:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
", expected, got);
        }
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate gluon;

use gluon::vm::api::{Getable, VmType};
use gluon::vm::thread::{RootedThread, Thread};
use gluon::import::Import;
use gluon::Compiler;

#[allow(dead_code)]
pub fn load_script(vm: &Thread, filename: &str, input: &str) -> ::gluon::Result<()> {
    Compiler::new()
        .implicit_prelude(false)
        .load_script(vm, filename, input)
}

pub fn run_expr_<'vm, T>(vm: &'vm Thread, s: &str, implicit_prelude: bool) -> T
    where T: Getable<'vm> + VmType
{
    Compiler::new()
        .implicit_prelude(implicit_prelude)
        .run_expr(vm, "<top>", s)
        .unwrap_or_else(|err| panic!("{}", err)).0
}

pub fn run_expr<'vm, T>(vm: &'vm Thread, s: &str) -> T
    where T: Getable<'vm> + VmType
{
    run_expr_(vm, s, false)
}

/// Creates a VM for testing which has the correct paths to import the std library properly
pub fn make_vm() -> RootedThread {
    let vm = ::gluon::new_vm();
    let import = vm.get_macros().get("import");
    import.as_ref()
          .and_then(|import| import.downcast_ref::<Import>())
          .expect("Import macro")
          .add_path("..");
    vm
}

macro_rules! test_expr {
    (prelude $name: ident, $expr: expr, $value: expr) => {
        #[test]
        fn $name() {
            let _ = ::env_logger::init();
            let mut vm = make_vm();
            let value = run_expr_(&mut vm, $expr, true);
            assert_eq!(value, $value);

            // Help out the type inference by forcing that left and right are the same types
            fn equiv<T>(_: &T, _: &T) { }
            equiv(&value, &$value);
        }
    };
    (io $name: ident, $expr: expr, $value: expr) => {
        #[test]
        fn $name() {
            let _ = ::env_logger::init();
            let mut vm = make_vm();
            let (value, _) = Compiler::new()
                .implicit_prelude(false)
                .run_io_expr(&mut vm, "<top>", $expr)
                .unwrap_or_else(|err| panic!("{}", err));
            assert_eq!(value, $value);

            // Help out the type inference by forcing that left and right are the same types
            fn equiv<T>(_: &T, _: &T) { }
            equiv(&value, &$value);
        }
    };
    ($name: ident, $expr: expr, $value: expr) => {
        #[test]
        fn $name() {
            let _ = ::env_logger::init();
            let mut vm = make_vm();
            let value = run_expr(&mut vm, $expr);
            assert_eq!(value, $value);

            // Help out the type inference by forcing that left and right are the same types
            fn equiv<T>(_: &T, _: &T) { }
            equiv(&value, &$value);
        }
    };
    ($name: ident, $expr: expr) => {
        #[test]
        fn $name() {
            let _ = ::env_logger::init();
            let mut vm = make_vm();
            run_expr::<Generic<A>>(&mut vm, $expr);
        }
    }
}
<commit_msg>Run rustfmt<commit_after>extern crate env_logger;
extern crate gluon;

use gluon::vm::api::{Getable, VmType};
use gluon::vm::thread::{RootedThread, Thread};
use gluon::import::Import;
use gluon::Compiler;

#[allow(dead_code)]
pub fn load_script(vm: &Thread, filename: &str, input: &str) -> ::gluon::Result<()> {
    Compiler::new()
        .implicit_prelude(false)
        .load_script(vm, filename, input)
}

pub fn run_expr_<'vm, T>(vm: &'vm Thread, s: &str, implicit_prelude: bool) -> T
    where T: Getable<'vm> + VmType,
{
    Compiler::new()
        .implicit_prelude(implicit_prelude)
        .run_expr(vm, "<top>", s)
        .unwrap_or_else(|err| panic!("{}", err))
        .0
}

pub fn run_expr<'vm, T>(vm: &'vm Thread, s: &str) -> T
    where T: Getable<'vm> + VmType,
{
    run_expr_(vm, s, false)
}

/// Creates a VM for testing which has the correct paths to import the std library properly
pub fn make_vm() -> RootedThread {
    let vm = ::gluon::new_vm();
    let import = vm.get_macros().get("import");
    import.as_ref()
        .and_then(|import| import.downcast_ref::<Import>())
        .expect("Import macro")
        .add_path("..");
    vm
}

macro_rules! test_expr {
    (prelude $name: ident, $expr: expr, $value: expr) => {
        #[test]
        fn $name() {
            let _ = ::env_logger::init();
            let mut vm = make_vm();
            let value = run_expr_(&mut vm, $expr, true);
            assert_eq!(value, $value);

            // Help out the type inference by forcing that left and right are the same types
            fn equiv<T>(_: &T, _: &T) { }
            equiv(&value, &$value);
        }
    };
    (io $name: ident, $expr: expr, $value: expr) => {
        #[test]
        fn $name() {
            let _ = ::env_logger::init();
            let mut vm = make_vm();
            let (value, _) = Compiler::new()
                .implicit_prelude(false)
                .run_io_expr(&mut vm, "<top>", $expr)
                .unwrap_or_else(|err| panic!("{}", err));
            assert_eq!(value, $value);

            // Help out the type inference by forcing that left and right are the same types
            fn equiv<T>(_: &T, _: &T) { }
            equiv(&value, &$value);
        }
    };
    ($name: ident, $expr: expr, $value: expr) => {
        #[test]
        fn $name() {
            let _ = ::env_logger::init();
            let mut vm = make_vm();
            let value = run_expr(&mut vm, $expr);
            assert_eq!(value, $value);

            // Help out the type inference by forcing that left and right are the same types
            fn equiv<T>(_: &T, _: &T) { }
            equiv(&value, &$value);
        }
    };
    ($name: ident, $expr: expr) => {
        #[test]
        fn $name() {
            let _ = ::env_logger::init();
            let mut vm = make_vm();
            run_expr::<Generic<A>>(&mut vm, $expr);
        }
    }
}
<|endoftext|>


<commit_before>#![allow(
    clippy::diverging_sub_expression,
    clippy::let_and_return,
    clippy::let_underscore_drop,
    clippy::never_loop,
    clippy::unit_arg
)]

use anyhow::{anyhow, ensure, Chain, Error, Result};
use std::fmt::Debug;
use std::iter;
use std::marker::PhantomData;
use std::ops::Add;

struct S;

impl<T> Add<T> for S {
    type Output = bool;
    fn add(self, rhs: T) -> Self::Output {
        let _ = rhs;
        false
    }
}

trait Trait: Sized {
    fn t(self, i: i32) -> i32 {
        i
    }
}

impl<T> Trait for T {}

#[track_caller]
fn assert_err<T: Debug>(result: impl FnOnce() -> Result<T>, expected: &'static str) {
    let actual = result().unwrap_err().to_string();

    let mut accepted_alternatives = expected.split('\n');
    let expected = accepted_alternatives.next_back().unwrap();
    if accepted_alternatives.any(|alternative| actual == alternative) {
        return;
    }

    assert_eq!(actual, expected);
}

#[test]
fn test_recursion() {
    // Must not blow the default #[recursion_limit], which is 128.
    #[rustfmt::skip]
    let test = || Ok(ensure!(
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false
    ));

    test().unwrap_err();
}

#[test]
fn test_low_precedence_control_flow() {
    #[allow(unreachable_code)]
    let test = || {
        let val = loop {
            // Break has lower precedence than the comparison operators so the
            // expression here is `S + (break (1 == 1))`. It would be bad if the
            // ensure macro partitioned this input into `(S + break 1) == (1)`
            // because that means a different thing than what was written.
            ensure!(S + break 1 == 1);
        };
        Ok(val)
    };

    assert!(test().unwrap());
}

#[test]
fn test_low_precedence_binary_operator() {
    // Must not partition as `false == (true && false)`.
    let test = || Ok(ensure!(false == true && false));
    assert_err(test, "Condition failed: `false == true && false`");

    // But outside the root level, it is fine.
    let test = || Ok(ensure!(while false == true && false {} < ()));
    assert_err(
        test,
        "Condition failed: `while false == true && false { } < ()` (() vs ())",
    );
}

#[test]
fn test_closure() {
    // Must not partition as `(S + move) || (1 == 1)` by treating move as an
    // identifier, nor as `(S + move || 1) == (1)` by misinterpreting the
    // closure precedence.
    let test = || Ok(ensure!(S + move || 1 == 1));
    assert_err(test, "Condition failed: `S + (move || 1 == 1)`");

    let test = || Ok(ensure!(S + || 1 == 1));
    assert_err(test, "Condition failed: `S + (|| 1 == 1)`");

    // Must not partition as `S + ((move | ()) | 1) == 1` by treating those
    // pipes as bitwise-or.
    let test = || Ok(ensure!(S + move |()| 1 == 1));
    assert_err(test, "Condition failed: `S + (move |()| 1 == 1)`");

    let test = || Ok(ensure!(S + |()| 1 == 1));
    assert_err(test, "Condition failed: `S + (|()| 1 == 1)`");
}

#[test]
fn test_unary() {
    let mut x = &1;
    let test = || Ok(ensure!(*x == 2));
    assert_err(test, "Condition failed: `*x == 2` (1 vs 2)");

    let test = || Ok(ensure!(!x == 1));
    assert_err(test, "Condition failed: `!x == 1` (-2 vs 1)");

    let test = || Ok(ensure!(-x == 1));
    assert_err(test, "Condition failed: `-x == 1` (-1 vs 1)");

    let test = || Ok(ensure!(&x == &&2));
    assert_err(test, "Condition failed: `&x == &&2` (1 vs 2)");

    let test = || Ok(ensure!(&mut x == *&&mut &2));
    assert_err(test, "Condition failed: `&mut x == *&&mut &2` (1 vs 2)");
}

#[test]
fn test_if() {
    #[rustfmt::skip]
    let test = || Ok(ensure!(if false {}.t(1) == 2));
    assert_err(test, "Condition failed: `if false { }.t(1) == 2` (1 vs 2)");

    #[rustfmt::skip]
    let test = || Ok(ensure!(if false {} else {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `if false { } else { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(if false {} else if false {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `if false { } else if false { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(if let 1 = 2 {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `if let 1 = 2 { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(if let 1 | 2 = 2 {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `if let 1 | 2 = 2 { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(if let | 1 | 2 = 2 {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `if let 1 | 2 = 2 { }.t(1) == 2` (1 vs 2)",
    );
}

#[test]
fn test_loop() {
    #[rustfmt::skip]
    let test = || Ok(ensure!(1 + loop { break 1 } == 1));
    assert_err(
        test,
        // 1.54 puts a double space after loop
        "Condition failed: `1 + loop  { break 1  } == 1` (2 vs 1)\n\
         Condition failed: `1 + loop { break 1  } == 1` (2 vs 1)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(1 + 'a: loop { break 'a 1 } == 1));
    assert_err(
        test,
        // 1.54 puts a double space after loop
        "Condition failed: `1 + 'a: loop  { break 'a 1  } == 1` (2 vs 1)\n\
         Condition failed: `1 + 'a: loop { break 'a 1  } == 1` (2 vs 1)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(while false {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `while false { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(while let None = Some(1) {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `while let None = Some(1) { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(for _x in iter::once(0) {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `for _x in iter::once(0) { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(for | _x in iter::once(0) {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `for _x in iter::once(0) { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(for true | false in iter::empty() {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `for true | false in iter::empty() { }.t(1) == 2` (1 vs 2)",
    );
}

#[test]
fn test_match() {
    #[rustfmt::skip]
    let test = || Ok(ensure!(match 1 == 1 { true => 1, false => 0 } == 2));
    assert_err(
        test,
        "Condition failed: `match 1 == 1 { true => 1, false => 0, } == 2` (1 vs 2)",
    );
}

#[test]
fn test_atom() {
    let test = || Ok(ensure!([false, false].len() > 3));
    assert_err(
        test,
        "Condition failed: `[false, false].len() > 3` (2 vs 3)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!({ let x = 1; x } >= 3));
    assert_err(test, "Condition failed: `{ let x = 1; x } >= 3` (1 vs 3)");

    let test = || Ok(ensure!(S + async { 1 } == true));
    assert_err(
        test,
        "Condition failed: `S + async  { 1 } == true` (false vs true)",
    );

    let test = || Ok(ensure!(S + async move { 1 } == true));
    assert_err(
        test,
        "Condition failed: `S + async move  { 1 } == true` (false vs true)",
    );

    let test = || Ok(ensure!(S + unsafe { 1 } == true));
    assert_err(
        test,
        "Condition failed: `S + unsafe { 1 } == true` (false vs true)",
    );
}

#[test]
fn test_path() {
    let test = || Ok(ensure!(crate::S.t(1) == 2));
    assert_err(test, "Condition failed: `crate::S.t(1) == 2` (1 vs 2)");

    let test = || Ok(ensure!(::anyhow::Error::root_cause.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `::anyhow::Error::root_cause.t(1) == 2` (1 vs 2)",
    );

    let test = || Ok(ensure!(Error::msg::<&str>.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `Error::msg::<&str>.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(Error::msg::<&str,>.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `Error::msg::<&str>.t(1) == 2` (1 vs 2)",
    );

    let test = || Ok(ensure!(Error::msg::<<str as ToOwned>::Owned>.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `Error::msg::<<str as ToOwned>::Owned>.t(1) == 2` (1 vs 2)",
    );

    let test = || Ok(ensure!(Chain::<'static>::new.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `Chain::<'static>::new.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(Chain::<'static,>::new.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `Chain::<'static>::new.t(1) == 2` (1 vs 2)",
    );
}

#[test]
fn test_macro() {
    let test = || Ok(ensure!(anyhow!("...").to_string().len() <= 1));
    assert_err(
        test,
        "Condition failed: `anyhow!(\"...\").to_string().len() <= 1` (3 vs 1)",
    );

    let test = || Ok(ensure!(vec![1].len() < 1));
    assert_err(test, "Condition failed: `vec![1].len() < 1` (1 vs 1)");

    let test = || Ok(ensure!(stringify! {} != ""));
    assert_err(
        test,
        "Condition failed: `stringify! { } != \"\"` (\"\" vs \"\")",
    );
}

#[test]
fn test_trailer() {
    let test = || Ok(ensure!((|| 1)() == 2));
    assert_err(test, "Condition failed: `(|| 1)() == 2` (1 vs 2)");

    let test = || Ok(ensure!(b"hmm"[1] == b'c'));
    assert_err(test, "Condition failed: `b\"hmm\"[1] == b'c'` (109 vs 99)");

    let test = || Ok(ensure!(PhantomData::<u8> {} != PhantomData));
    assert_err(
        test,
        "Condition failed: `PhantomData::<u8>{} != PhantomData` (PhantomData vs PhantomData)",
    );

    let result = Ok::<_, Error>(1);
    let test = || Ok(ensure!(result? == 2));
    assert_err(test, "Condition failed: `result? == 2` (1 vs 2)");

    let test = || Ok(ensure!((2, 3).1 == 2));
    assert_err(test, "Condition failed: `(2, 3).1 == 2` (3 vs 2)");

    let err = anyhow!("");
    let test = || Ok(ensure!(err.is::<&str>() == false));
    assert_err(
        test,
        "Condition failed: `err.is::<&str>() == false` (true vs false)",
    );

    let test = || Ok(ensure!(err.is::<<str as ToOwned>::Owned>() == true));
    assert_err(
        test,
        "Condition failed: `err.is::<<str as ToOwned>::Owned>() == true` (false vs true)",
    );
}
<commit_msg>Add test of long debug<commit_after>#![allow(
    clippy::diverging_sub_expression,
    clippy::let_and_return,
    clippy::let_underscore_drop,
    clippy::never_loop,
    clippy::unit_arg
)]

use anyhow::{anyhow, ensure, Chain, Error, Result};
use std::fmt::Debug;
use std::iter;
use std::marker::PhantomData;
use std::ops::Add;

struct S;

impl<T> Add<T> for S {
    type Output = bool;
    fn add(self, rhs: T) -> Self::Output {
        let _ = rhs;
        false
    }
}

trait Trait: Sized {
    fn t(self, i: i32) -> i32 {
        i
    }
}

impl<T> Trait for T {}

#[track_caller]
fn assert_err<T: Debug>(result: impl FnOnce() -> Result<T>, expected: &'static str) {
    let actual = result().unwrap_err().to_string();

    let mut accepted_alternatives = expected.split('\n');
    let expected = accepted_alternatives.next_back().unwrap();
    if accepted_alternatives.any(|alternative| actual == alternative) {
        return;
    }

    assert_eq!(actual, expected);
}

#[test]
fn test_recursion() {
    // Must not blow the default #[recursion_limit], which is 128.
    #[rustfmt::skip]
    let test = || Ok(ensure!(
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false |
        false | false | false | false | false | false | false | false | false
    ));

    test().unwrap_err();
}

#[test]
fn test_low_precedence_control_flow() {
    #[allow(unreachable_code)]
    let test = || {
        let val = loop {
            // Break has lower precedence than the comparison operators so the
            // expression here is `S + (break (1 == 1))`. It would be bad if the
            // ensure macro partitioned this input into `(S + break 1) == (1)`
            // because that means a different thing than what was written.
            ensure!(S + break 1 == 1);
        };
        Ok(val)
    };

    assert!(test().unwrap());
}

#[test]
fn test_low_precedence_binary_operator() {
    // Must not partition as `false == (true && false)`.
    let test = || Ok(ensure!(false == true && false));
    assert_err(test, "Condition failed: `false == true && false`");

    // But outside the root level, it is fine.
    let test = || Ok(ensure!(while false == true && false {} < ()));
    assert_err(
        test,
        "Condition failed: `while false == true && false { } < ()` (() vs ())",
    );
}

#[test]
fn test_closure() {
    // Must not partition as `(S + move) || (1 == 1)` by treating move as an
    // identifier, nor as `(S + move || 1) == (1)` by misinterpreting the
    // closure precedence.
    let test = || Ok(ensure!(S + move || 1 == 1));
    assert_err(test, "Condition failed: `S + (move || 1 == 1)`");

    let test = || Ok(ensure!(S + || 1 == 1));
    assert_err(test, "Condition failed: `S + (|| 1 == 1)`");

    // Must not partition as `S + ((move | ()) | 1) == 1` by treating those
    // pipes as bitwise-or.
    let test = || Ok(ensure!(S + move |()| 1 == 1));
    assert_err(test, "Condition failed: `S + (move |()| 1 == 1)`");

    let test = || Ok(ensure!(S + |()| 1 == 1));
    assert_err(test, "Condition failed: `S + (|()| 1 == 1)`");
}

#[test]
fn test_unary() {
    let mut x = &1;
    let test = || Ok(ensure!(*x == 2));
    assert_err(test, "Condition failed: `*x == 2` (1 vs 2)");

    let test = || Ok(ensure!(!x == 1));
    assert_err(test, "Condition failed: `!x == 1` (-2 vs 1)");

    let test = || Ok(ensure!(-x == 1));
    assert_err(test, "Condition failed: `-x == 1` (-1 vs 1)");

    let test = || Ok(ensure!(&x == &&2));
    assert_err(test, "Condition failed: `&x == &&2` (1 vs 2)");

    let test = || Ok(ensure!(&mut x == *&&mut &2));
    assert_err(test, "Condition failed: `&mut x == *&&mut &2` (1 vs 2)");
}

#[test]
fn test_if() {
    #[rustfmt::skip]
    let test = || Ok(ensure!(if false {}.t(1) == 2));
    assert_err(test, "Condition failed: `if false { }.t(1) == 2` (1 vs 2)");

    #[rustfmt::skip]
    let test = || Ok(ensure!(if false {} else {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `if false { } else { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(if false {} else if false {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `if false { } else if false { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(if let 1 = 2 {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `if let 1 = 2 { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(if let 1 | 2 = 2 {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `if let 1 | 2 = 2 { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(if let | 1 | 2 = 2 {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `if let 1 | 2 = 2 { }.t(1) == 2` (1 vs 2)",
    );
}

#[test]
fn test_loop() {
    #[rustfmt::skip]
    let test = || Ok(ensure!(1 + loop { break 1 } == 1));
    assert_err(
        test,
        // 1.54 puts a double space after loop
        "Condition failed: `1 + loop  { break 1  } == 1` (2 vs 1)\n\
         Condition failed: `1 + loop { break 1  } == 1` (2 vs 1)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(1 + 'a: loop { break 'a 1 } == 1));
    assert_err(
        test,
        // 1.54 puts a double space after loop
        "Condition failed: `1 + 'a: loop  { break 'a 1  } == 1` (2 vs 1)\n\
         Condition failed: `1 + 'a: loop { break 'a 1  } == 1` (2 vs 1)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(while false {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `while false { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(while let None = Some(1) {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `while let None = Some(1) { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(for _x in iter::once(0) {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `for _x in iter::once(0) { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(for | _x in iter::once(0) {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `for _x in iter::once(0) { }.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(for true | false in iter::empty() {}.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `for true | false in iter::empty() { }.t(1) == 2` (1 vs 2)",
    );
}

#[test]
fn test_match() {
    #[rustfmt::skip]
    let test = || Ok(ensure!(match 1 == 1 { true => 1, false => 0 } == 2));
    assert_err(
        test,
        "Condition failed: `match 1 == 1 { true => 1, false => 0, } == 2` (1 vs 2)",
    );
}

#[test]
fn test_atom() {
    let test = || Ok(ensure!([false, false].len() > 3));
    assert_err(
        test,
        "Condition failed: `[false, false].len() > 3` (2 vs 3)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!({ let x = 1; x } >= 3));
    assert_err(test, "Condition failed: `{ let x = 1; x } >= 3` (1 vs 3)");

    let test = || Ok(ensure!(S + async { 1 } == true));
    assert_err(
        test,
        "Condition failed: `S + async  { 1 } == true` (false vs true)",
    );

    let test = || Ok(ensure!(S + async move { 1 } == true));
    assert_err(
        test,
        "Condition failed: `S + async move  { 1 } == true` (false vs true)",
    );

    let test = || Ok(ensure!(S + unsafe { 1 } == true));
    assert_err(
        test,
        "Condition failed: `S + unsafe { 1 } == true` (false vs true)",
    );
}

#[test]
fn test_path() {
    let test = || Ok(ensure!(crate::S.t(1) == 2));
    assert_err(test, "Condition failed: `crate::S.t(1) == 2` (1 vs 2)");

    let test = || Ok(ensure!(::anyhow::Error::root_cause.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `::anyhow::Error::root_cause.t(1) == 2` (1 vs 2)",
    );

    let test = || Ok(ensure!(Error::msg::<&str>.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `Error::msg::<&str>.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(Error::msg::<&str,>.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `Error::msg::<&str>.t(1) == 2` (1 vs 2)",
    );

    let test = || Ok(ensure!(Error::msg::<<str as ToOwned>::Owned>.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `Error::msg::<<str as ToOwned>::Owned>.t(1) == 2` (1 vs 2)",
    );

    let test = || Ok(ensure!(Chain::<'static>::new.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `Chain::<'static>::new.t(1) == 2` (1 vs 2)",
    );

    #[rustfmt::skip]
    let test = || Ok(ensure!(Chain::<'static,>::new.t(1) == 2));
    assert_err(
        test,
        "Condition failed: `Chain::<'static>::new.t(1) == 2` (1 vs 2)",
    );
}

#[test]
fn test_macro() {
    let test = || Ok(ensure!(anyhow!("...").to_string().len() <= 1));
    assert_err(
        test,
        "Condition failed: `anyhow!(\"...\").to_string().len() <= 1` (3 vs 1)",
    );

    let test = || Ok(ensure!(vec![1].len() < 1));
    assert_err(test, "Condition failed: `vec![1].len() < 1` (1 vs 1)");

    let test = || Ok(ensure!(stringify! {} != ""));
    assert_err(
        test,
        "Condition failed: `stringify! { } != \"\"` (\"\" vs \"\")",
    );
}

#[test]
fn test_trailer() {
    let test = || Ok(ensure!((|| 1)() == 2));
    assert_err(test, "Condition failed: `(|| 1)() == 2` (1 vs 2)");

    let test = || Ok(ensure!(b"hmm"[1] == b'c'));
    assert_err(test, "Condition failed: `b\"hmm\"[1] == b'c'` (109 vs 99)");

    let test = || Ok(ensure!(PhantomData::<u8> {} != PhantomData));
    assert_err(
        test,
        "Condition failed: `PhantomData::<u8>{} != PhantomData` (PhantomData vs PhantomData)",
    );

    let result = Ok::<_, Error>(1);
    let test = || Ok(ensure!(result? == 2));
    assert_err(test, "Condition failed: `result? == 2` (1 vs 2)");

    let test = || Ok(ensure!((2, 3).1 == 2));
    assert_err(test, "Condition failed: `(2, 3).1 == 2` (3 vs 2)");

    let err = anyhow!("");
    let test = || Ok(ensure!(err.is::<&str>() == false));
    assert_err(
        test,
        "Condition failed: `err.is::<&str>() == false` (true vs false)",
    );

    let test = || Ok(ensure!(err.is::<<str as ToOwned>::Owned>() == true));
    assert_err(
        test,
        "Condition failed: `err.is::<<str as ToOwned>::Owned>() == true` (false vs true)",
    );
}

#[test]
fn test_too_long() {
    let test = || Ok(ensure!("" == "x".repeat(10)));
    assert_err(
        test,
        "Condition failed: `\"\" == \"x\".repeat(10)` (\"\" vs \"xxxxxxxxxx\")",
    );

    let test = || Ok(ensure!("" == "x".repeat(80)));
    assert_err(test, "Condition failed: `\"\" == \"x\".repeat(80)`");
}
<|endoftext|>


<commit_before>use event::{
    Event,
    Update,
    UpdateArgs,
};
use ai_behavior::{
    Action,
    State,
    Sequence,
    Success,
    Wait,
    WhenAll,
    While,
};

/// Some test actions.
#[deriving(Clone)]
pub enum TestActions {
    /// Increment accumulator.
    Inc,
    /// Decrement accumulator.
    Dec,
}

// A test state machine that can increment and decrement.
fn exec(mut acc: u32, dt: f64, state: &mut State<TestActions, ()>) -> u32 {
    let e: Event = Update(UpdateArgs { dt: dt });
    state.event(&e, |_, dt, action, _| {
        match *action {
            Inc => { acc += 1; (Success, dt) },
            Dec => { acc -= 1; (Success, dt) },
        }
    });
    acc
}

// Each action that terminates immediately
// consumes a time of 0.0 seconds.
// This makes it possible to execute one action
// after another without delay or waiting for next update.
#[test]
fn print_2() {
    let a: u32 = 0;
    let seq = Sequence(vec![Action(Inc), Action(Inc)]);
    let mut state = State::new(seq);
    let a = exec(a, 0.0, &mut state);
    assert_eq!(a, 2);
}

// If you wait the exact amount before to execute an action,
// it will execute. This behavior makes it easy to predict
// when an action will run.
#[test]
fn wait_sec() {
    let a: u32 = 0;
    let seq = Sequence(vec![Wait(1.0), Action(Inc)]);
    let mut state = State::new(seq);
    let a = exec(a, 1.0, &mut state);
    assert_eq!(a, 1);
}

// When we execute half the time and then the other half,
// then the action should be executed.
#[test]
fn wait_half_sec() {
    let a: u32 = 0;
    let seq = Sequence(vec![Wait(1.0), Action(Inc)]);
    let mut state = State::new(seq);
    let a = exec(a, 0.5, &mut state);
    assert_eq!(a, 0);
    let a = exec(a, 0.5, &mut state);
    assert_eq!(a, 1);
}

// A sequence of one event is like a bare event.
#[test]
fn sequence_of_one_event() {
    let a: u32 = 0;
    let seq = Sequence(vec![Action(Inc)]);
    let mut state = State::new(seq);
    let a = exec(a, 1.0, &mut state);
    assert_eq!(a, 1);
}

// A sequence of wait events is the same as one wait event.
#[test]
fn wait_two_waits() {
    let a: u32 = 0;
    let seq = Sequence(vec![Wait(0.5), Wait(0.5), Action(Inc)]);
    let mut state = State::new(seq);
    let a = exec(a, 1.0, &mut state);
    assert_eq!(a, 1);
}

// Increase counter ten times.
#[test]
fn loop_ten_times() {
    let a: u32 = 0;
    let rep = While(box Wait(50.0), vec![Wait(0.5), Action(Inc), Wait(0.5)]);
    let mut state = State::new(rep);
    let a = exec(a, 10.0, &mut state);
    assert_eq!(a, 10);
}

#[test]
fn when_all_wait() {
    let a: u32 = 0;
    let all = Sequence(vec![
            // Wait in parallel.
            WhenAll(vec![Wait(0.5), Wait(1.0)]),
            Action(Inc)
        ]);
    let mut state = State::new(all);
    let a = exec(a, 0.5, &mut state);
    assert_eq!(a, 0);
    let a = exec(a, 0.5, &mut state);
    assert_eq!(a, 1);
}
<commit_msg>Updating tests for enum namespacing<commit_after>use event::Event::{
    Update,
};
use event::{Event, UpdateArgs};
use ai_behavior::{
    Action,
    State,
    Sequence,
    Success,
    Wait,
    WhenAll,
    While,
};

use test_events::TestActions::{
    Inc,
    Dec,
};

/// Some test actions.
#[deriving(Clone)]
pub enum TestActions {
    /// Increment accumulator.
    Inc,
    /// Decrement accumulator.
    Dec,
}

// A test state machine that can increment and decrement.
fn exec(mut acc: u32, dt: f64, state: &mut State<TestActions, ()>) -> u32 {
    let e: Event = Update(UpdateArgs { dt: dt });
    state.event(&e, |_, dt, action, _| {
        match *action {
            Inc => { acc += 1; (Success, dt) },
            Dec => { acc -= 1; (Success, dt) },
        }
    });
    acc
}

// Each action that terminates immediately
// consumes a time of 0.0 seconds.
// This makes it possible to execute one action
// after another without delay or waiting for next update.
#[test]
fn print_2() {
    let a: u32 = 0;
    let seq = Sequence(vec![Action(Inc), Action(Inc)]);
    let mut state = State::new(seq);
    let a = exec(a, 0.0, &mut state);
    assert_eq!(a, 2);
}

// If you wait the exact amount before to execute an action,
// it will execute. This behavior makes it easy to predict
// when an action will run.
#[test]
fn wait_sec() {
    let a: u32 = 0;
    let seq = Sequence(vec![Wait(1.0), Action(Inc)]);
    let mut state = State::new(seq);
    let a = exec(a, 1.0, &mut state);
    assert_eq!(a, 1);
}

// When we execute half the time and then the other half,
// then the action should be executed.
#[test]
fn wait_half_sec() {
    let a: u32 = 0;
    let seq = Sequence(vec![Wait(1.0), Action(Inc)]);
    let mut state = State::new(seq);
    let a = exec(a, 0.5, &mut state);
    assert_eq!(a, 0);
    let a = exec(a, 0.5, &mut state);
    assert_eq!(a, 1);
}

// A sequence of one event is like a bare event.
#[test]
fn sequence_of_one_event() {
    let a: u32 = 0;
    let seq = Sequence(vec![Action(Inc)]);
    let mut state = State::new(seq);
    let a = exec(a, 1.0, &mut state);
    assert_eq!(a, 1);
}

// A sequence of wait events is the same as one wait event.
#[test]
fn wait_two_waits() {
    let a: u32 = 0;
    let seq = Sequence(vec![Wait(0.5), Wait(0.5), Action(Inc)]);
    let mut state = State::new(seq);
    let a = exec(a, 1.0, &mut state);
    assert_eq!(a, 1);
}

// Increase counter ten times.
#[test]
fn loop_ten_times() {
    let a: u32 = 0;
    let rep = While(box Wait(50.0), vec![Wait(0.5), Action(Inc), Wait(0.5)]);
    let mut state = State::new(rep);
    let a = exec(a, 10.0, &mut state);
    assert_eq!(a, 10);
}

#[test]
fn when_all_wait() {
    let a: u32 = 0;
    let all = Sequence(vec![
            // Wait in parallel.
            WhenAll(vec![Wait(0.5), Wait(1.0)]),
            Action(Inc)
        ]);
    let mut state = State::new(all);
    let a = exec(a, 0.5, &mut state);
    assert_eq!(a, 0);
    let a = exec(a, 0.5, &mut state);
    assert_eq!(a, 1);
}
<|endoftext|>


<commit_before>use anyhow::Result;
use pueue_lib::network::message::*;

use crate::helper::*;

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
/// Ensure that clean only removes finished tasks
async fn test_normal_clean() -> Result<()> {
    let (settings, _tempdir, _pid) = threaded_setup()?;
    let shared = &settings.shared;

    // We'll add some tasks.
    // Task 0-2 will be immediately handled by the daemon, the other three tasks are queued for
    // now. However, we'll manipulate them in such a way, that we'll end up with this mapping:
    // 0 -> failed
    // 1 -> success
    // 2 -> running
    // 3 -> paused
    // 4 -> queued
    // 5 -> stashed
    for command in vec!["failing", "ls", "sleep 60", "sleep 60", "ls", "ls"] {
        assert_success(fixtures::add_task(shared, command, false).await?);
    }
    // Wait for task2 to start. This implies task[0,1] being finished.
    wait_for_task_condition(shared, 2, |task| task.is_running()).await?;

    // Explicitely start task3, wait for it to start and directly pause it.
    start_tasks(shared, TaskSelection::TaskIds(vec![3])).await?;
    wait_for_task_condition(shared, 3, |task| task.is_running()).await?;

    pause_tasks(&shared, TaskSelection::TaskIds(vec![3])).await?;

    // Stash task 5
    let pause_message = Message::Stash(vec![5]);
    send_message(shared, pause_message).await?;

    let remove_message = Message::Remove(vec![0, 1, 2, 3, 4, 5]);
    send_message(shared, remove_message).await?;

    // Ensure that every task that isn't currently running can be removed
    let state = get_state(shared).await?;
    assert!(!state.tasks.contains_key(&0));
    assert!(!state.tasks.contains_key(&1));
    assert!(state.tasks.contains_key(&2));
    assert!(state.tasks.contains_key(&3));
    assert!(!state.tasks.contains_key(&4));
    assert!(!state.tasks.contains_key(&5));

    Ok(())
}
<commit_msg>Fix copy-paste error in test<commit_after>use anyhow::Result;
use pueue_lib::network::message::*;

use crate::helper::*;

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
/// Ensure that only removable tasks can be removed.
async fn test_normal_remove() -> Result<()> {
    let (settings, _tempdir, _pid) = threaded_setup()?;
    let shared = &settings.shared;

    // We'll add some tasks.
    // Task 0-2 will be immediately handled by the daemon, the other three tasks are queued for
    // now. However, we'll manipulate them in such a way, that we'll end up with this mapping:
    // 0 -> failed
    // 1 -> success
    // 2 -> running
    // 3 -> paused
    // 4 -> queued
    // 5 -> stashed
    for command in vec!["failing", "ls", "sleep 60", "sleep 60", "ls", "ls"] {
        assert_success(fixtures::add_task(shared, command, false).await?);
    }
    // Wait for task2 to start. This implies task[0,1] being finished.
    wait_for_task_condition(shared, 2, |task| task.is_running()).await?;

    // Explicitely start task3, wait for it to start and directly pause it.
    start_tasks(shared, TaskSelection::TaskIds(vec![3])).await?;
    wait_for_task_condition(shared, 3, |task| task.is_running()).await?;

    pause_tasks(&shared, TaskSelection::TaskIds(vec![3])).await?;

    // Stash task 5
    let pause_message = Message::Stash(vec![5]);
    send_message(shared, pause_message).await?;

    let remove_message = Message::Remove(vec![0, 1, 2, 3, 4, 5]);
    send_message(shared, remove_message).await?;

    // Ensure that every task that isn't currently running can be removed
    let state = get_state(shared).await?;
    assert!(!state.tasks.contains_key(&0));
    assert!(!state.tasks.contains_key(&1));
    assert!(state.tasks.contains_key(&2));
    assert!(state.tasks.contains_key(&3));
    assert!(!state.tasks.contains_key(&4));
    assert!(!state.tasks.contains_key(&5));

    Ok(())
}
<|endoftext|>