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

use serde::{de, Serialize};
use std::{
    fmt::{Display, Formatter},
    str::FromStr,
};

/// This file implements length and character set limited string types needed
/// for DiemID as defined by DIP-10: https://github.com/diem/dip/blob/main/dips/dip-10.md

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DiemId {
    // A reusable identifier that represents either the source or destination
    // end-user of a payment transaction. It is unique to per user at VASP level
    user_identifier: DiemIdUserIdentifier,
    // A unique string that is mapped to a VASP
    vasp_domain_identifier: DiemIdVaspDomainIdentifier,
}

impl DiemId {
    pub fn new(
        user_identifier: DiemIdUserIdentifier,
        vasp_domain_identifier: DiemIdVaspDomainIdentifier,
    ) -> Self {
        Self {
            user_identifier,
            vasp_domain_identifier,
        }
    }

    fn new_from_raw(
        user_identifier: &str,
        vasp_domain_identifier: &str,
    ) -> Result<Self, DiemIdParseError> {
        Ok(DiemId::new(
            DiemIdUserIdentifier::new(user_identifier)?,
            DiemIdVaspDomainIdentifier::new(vasp_domain_identifier)?,
        ))
    }

    pub fn user_identifier(&self) -> &DiemIdUserIdentifier {
        &self.user_identifier
    }

    pub fn vasp_domain_identifier(&self) -> &DiemIdVaspDomainIdentifier {
        &self.vasp_domain_identifier
    }
}

impl Display for DiemId {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(
            f,
            "{}@{}",
            self.user_identifier.as_str(),
            self.vasp_domain_identifier.as_str()
        )
    }
}

impl FromStr for DiemId {
    type Err = DiemIdParseError;

    fn from_str(s: &str) -> Result<Self, DiemIdParseError> {
        let index = s.find('@').ok_or_else(|| DiemIdParseError::new("DiemId does not have @".to_string()))?;
        let split = s.split_at(index);
        // let vec = split.collect::<Vec<&str>>();
        DiemId::new_from_raw(split.0, split.1)
    }
}

impl std::error::Error for DiemIdParseError {}

#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct DiemIdUserIdentifier(Box<str>);

impl DiemIdUserIdentifier {
    pub fn new(s: &str) -> Result<Self, DiemIdParseError> {
        if s.len() > 64 || s.is_empty() {
            return Err(DiemIdParseError::new(
                "Invalid length for user identifier".to_string(),
            ));
        }

        let mut chars = s.chars();
        match chars.next() {
            Some('a'..='z') | Some('A'..='Z') | Some('0'..='9') => {}
            Some(_) => {
                return Err(DiemIdParseError::new(
                    "Invalid user identifier input".to_string(),
                ))
            }
            None => {
                return Err(DiemIdParseError::new(
                    "Invalid user identifier input".to_string(),
                ))
            }
        }
        for c in chars {
            match c {
                'a'..='z' | 'A'..='Z' | '0'..='9' | '.' => {}
                _ => return Err(DiemIdParseError::new(format!("Invalid character {}", c))),
            }
        }
        Ok(DiemIdUserIdentifier(s.into()))
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl<'de> de::Deserialize<'de> for DiemIdUserIdentifier {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        use serde::de::Error;

        let s = <String>::deserialize(deserializer)?;
        DiemIdUserIdentifier::new(&s).map_err(D::Error::custom)
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct DiemIdVaspDomainIdentifier(Box<str>);

impl DiemIdVaspDomainIdentifier {
    pub fn new(s: &str) -> Result<Self, DiemIdParseError> {
        if s.len() > 63 || s.is_empty() {
            return Err(DiemIdParseError::new(
                "Invalid length for vasp domain identifier".to_string(),
            ));
        }

        let mut chars = s.chars();
        match chars.next() {
            Some('a'..='z') | Some('A'..='Z') | Some('0'..='9') => {}
            Some(_) => {
                return Err(DiemIdParseError::new(
                    "Invalid vasp domain input".to_string(),
                ))
            }
            None => {
                return Err(DiemIdParseError::new(
                    "Invalid vasp domain input".to_string(),
                ))
            }
        }
        for c in chars {
            match c {
                'a'..='z' | 'A'..='Z' | '0'..='9' | '.' => {}
                _ => return Err(DiemIdParseError::new(format!("Invalid character {}", c))),
            }
        }
        Ok(DiemIdVaspDomainIdentifier(s.into()))
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl<'de> de::Deserialize<'de> for DiemIdVaspDomainIdentifier {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        use serde::de::Error;

        let s = <String>::deserialize(deserializer)?;
        DiemIdVaspDomainIdentifier::new(&s).map_err(D::Error::custom)
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DiemIdParseError {
    message: String,
}

impl DiemIdParseError {
    fn new(message: String) -> DiemIdParseError {
        DiemIdParseError { message }
    }
}

impl Display for DiemIdParseError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "Unable to parse DiemId: {}", self.message)
    }
}

#[test]
fn test_invalid_user_identifier() {
    // Test valid domain
    let raw_identifier = "abcd1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test having 64 characters is valid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test using "-" character is invalid
    let raw_identifier = "abcd!!!1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert_eq!(
        identifier.unwrap_err(),
        DiemIdParseError {
            message: "Invalid character !".to_string()
        },
    );
    // Test having 64 characters is invalid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff12345";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert_eq!(
        identifier.unwrap_err(),
        DiemIdParseError {
            message: "Invalid length for user identifier".to_string()
        },
    );
}

#[test]
fn test_invalid_vasp_domain_identifier() {
    // Test valid domain
    let raw_identifier = "diem";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test having 63 characters is valid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff123";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test using "-" character is invalid
    let raw_identifier = "diem-domain";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert_eq!(
        identifier.unwrap_err(),
        DiemIdParseError {
            message: "Invalid character -".to_string()
        },
    );
    // Test having 64 characters is invalid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggg";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert_eq!(
        identifier.unwrap_err(),
        DiemIdParseError {
            message: "Invalid length for vasp domain identifier".to_string()
        },
    );
}

#[test]
fn test_get_diem_id_string_from_components() {
    let user_identifier = DiemIdUserIdentifier::new(&"username").unwrap();
    let vasp_domain_identifier = DiemIdVaspDomainIdentifier::new(&"diem").unwrap();
    let diem_id = DiemId::new(user_identifier, vasp_domain_identifier);
    let full_id = diem_id.to_string();
    assert_eq!(full_id, "username@diem");
}

#[test]
fn test_get_diem_id_from_identifier_string() {
    let diem_id_str = "username@diem";
    let diem_id = DiemId::from_str(diem_id_str).unwrap();
    assert_eq!(diem_id.user_identifier().as_str(), "username");
    assert_eq!(diem_id.vasp_domain_identifier().as_str(), "diem");
}
<commit_msg>Change split logic<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use serde::{de, Serialize};
use std::{
    fmt::{Display, Formatter},
    str::FromStr,
};

/// This file implements length and character set limited string types needed
/// for DiemID as defined by DIP-10: https://github.com/diem/dip/blob/main/dips/dip-10.md

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DiemId {
    // A reusable identifier that represents either the source or destination
    // end-user of a payment transaction. It is unique to per user at VASP level
    user_identifier: DiemIdUserIdentifier,
    // A unique string that is mapped to a VASP
    vasp_domain_identifier: DiemIdVaspDomainIdentifier,
}

impl DiemId {
    pub fn new(
        user_identifier: DiemIdUserIdentifier,
        vasp_domain_identifier: DiemIdVaspDomainIdentifier,
    ) -> Self {
        Self {
            user_identifier,
            vasp_domain_identifier,
        }
    }

    fn new_from_raw(
        user_identifier: &str,
        vasp_domain_identifier: &str,
    ) -> Result<Self, DiemIdParseError> {
        Ok(DiemId::new(
            DiemIdUserIdentifier::new(user_identifier)?,
            DiemIdVaspDomainIdentifier::new(vasp_domain_identifier)?,
        ))
    }

    pub fn user_identifier(&self) -> &DiemIdUserIdentifier {
        &self.user_identifier
    }

    pub fn vasp_domain_identifier(&self) -> &DiemIdVaspDomainIdentifier {
        &self.vasp_domain_identifier
    }
}

impl Display for DiemId {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(
            f,
            "{}@{}",
            self.user_identifier.as_str(),
            self.vasp_domain_identifier.as_str()
        )
    }
}

impl FromStr for DiemId {
    type Err = DiemIdParseError;

    fn from_str(s: &str) -> Result<Self, DiemIdParseError> {
        let index = s
            .find('@')
            .ok_or_else(|| DiemIdParseError::new("DiemId does not have @".to_string()))?;
        let split = s.split_at(index);
        DiemId::new_from_raw(split.0, (split.1).trim_start_matches('@'))
    }
}

impl std::error::Error for DiemIdParseError {}

#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct DiemIdUserIdentifier(Box<str>);

impl DiemIdUserIdentifier {
    pub fn new(s: &str) -> Result<Self, DiemIdParseError> {
        if s.len() > 64 || s.is_empty() {
            return Err(DiemIdParseError::new(
                "Invalid length for user identifier".to_string(),
            ));
        }

        let mut chars = s.chars();
        match chars.next() {
            Some('a'..='z') | Some('A'..='Z') | Some('0'..='9') => {}
            Some(_) => {
                return Err(DiemIdParseError::new(
                    "Invalid user identifier input".to_string(),
                ))
            }
            None => {
                return Err(DiemIdParseError::new(
                    "Invalid user identifier input".to_string(),
                ))
            }
        }
        for c in chars {
            match c {
                'a'..='z' | 'A'..='Z' | '0'..='9' | '.' => {}
                _ => return Err(DiemIdParseError::new(format!("Invalid character {}", c))),
            }
        }
        Ok(DiemIdUserIdentifier(s.into()))
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl<'de> de::Deserialize<'de> for DiemIdUserIdentifier {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        use serde::de::Error;

        let s = <String>::deserialize(deserializer)?;
        DiemIdUserIdentifier::new(&s).map_err(D::Error::custom)
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct DiemIdVaspDomainIdentifier(Box<str>);

impl DiemIdVaspDomainIdentifier {
    pub fn new(s: &str) -> Result<Self, DiemIdParseError> {
        if s.len() > 63 || s.is_empty() {
            return Err(DiemIdParseError::new(
                "Invalid length for vasp domain identifier".to_string(),
            ));
        }

        let mut chars = s.chars();
        match chars.next() {
            Some('a'..='z') | Some('A'..='Z') | Some('0'..='9') => {}
            Some(_) => {
                return Err(DiemIdParseError::new(
                    "Invalid vasp domain input".to_string(),
                ))
            }
            None => {
                return Err(DiemIdParseError::new(
                    "Invalid vasp domain input".to_string(),
                ))
            }
        }
        for c in chars {
            match c {
                'a'..='z' | 'A'..='Z' | '0'..='9' | '.' => {}
                _ => return Err(DiemIdParseError::new(format!("Invalid character {}", c))),
            }
        }
        Ok(DiemIdVaspDomainIdentifier(s.into()))
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl<'de> de::Deserialize<'de> for DiemIdVaspDomainIdentifier {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        use serde::de::Error;

        let s = <String>::deserialize(deserializer)?;
        DiemIdVaspDomainIdentifier::new(&s).map_err(D::Error::custom)
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DiemIdParseError {
    message: String,
}

impl DiemIdParseError {
    fn new(message: String) -> DiemIdParseError {
        DiemIdParseError { message }
    }
}

impl Display for DiemIdParseError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "Unable to parse DiemId: {}", self.message)
    }
}

#[test]
fn test_invalid_user_identifier() {
    // Test valid domain
    let raw_identifier = "abcd1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test having 64 characters is valid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test using "-" character is invalid
    let raw_identifier = "abcd!!!1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert_eq!(
        identifier.unwrap_err(),
        DiemIdParseError {
            message: "Invalid character !".to_string()
        },
    );
    // Test having 64 characters is invalid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff12345";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert_eq!(
        identifier.unwrap_err(),
        DiemIdParseError {
            message: "Invalid length for user identifier".to_string()
        },
    );
}

#[test]
fn test_invalid_vasp_domain_identifier() {
    // Test valid domain
    let raw_identifier = "diem";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test having 63 characters is valid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff123";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test using "-" character is invalid
    let raw_identifier = "diem-domain";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert_eq!(
        identifier.unwrap_err(),
        DiemIdParseError {
            message: "Invalid character -".to_string()
        },
    );
    // Test having 64 characters is invalid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggg";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert_eq!(
        identifier.unwrap_err(),
        DiemIdParseError {
            message: "Invalid length for vasp domain identifier".to_string()
        },
    );
}

#[test]
fn test_get_diem_id_string_from_components() {
    let user_identifier = DiemIdUserIdentifier::new(&"username").unwrap();
    let vasp_domain_identifier = DiemIdVaspDomainIdentifier::new(&"diem").unwrap();
    let diem_id = DiemId::new(user_identifier, vasp_domain_identifier);
    let full_id = diem_id.to_string();
    assert_eq!(full_id, "username@diem");
}

#[test]
fn test_get_diem_id_from_identifier_string() {
    let diem_id_str = "username@diem";
    let diem_id = DiemId::from_str(diem_id_str).unwrap();
    assert_eq!(diem_id.user_identifier().as_str(), "username");
    assert_eq!(diem_id.vasp_domain_identifier().as_str(), "diem");

    let diem_id_str = "username@diem.com";
    let diem_id = DiemId::from_str(diem_id_str).unwrap();
    assert_eq!(diem_id.user_identifier().as_str(), "username");
    assert_eq!(diem_id.vasp_domain_identifier().as_str(), "diem.com");

    let diem_id_str = "username@diem@com";
    let diem_id = DiemId::from_str(diem_id_str);
    assert_eq!(
        diem_id.unwrap_err(),
        DiemIdParseError {
            message: "Invalid character @".to_string()
        },
    );
}
<|endoftext|>


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

use serde::{Deserialize, Serialize};
use std::fmt;

#[derive(Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub struct Module {
    code: Vec<u8>,
}

impl Module {
    pub fn new(code: Vec<u8>) -> Module {
        Module { code }
    }

    pub fn code(&self) -> &[u8] {
        &self.code
    }

    pub fn into_inner(self) -> Vec<u8> {
        self.code
    }
}

impl fmt::Debug for Module {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Module")
            .field("code", &hex::encode(&self.code))
            .finish()
    }
}
<commit_msg>Removing into_inner from types/src/transaction/module.rs<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use serde::{Deserialize, Serialize};
use std::fmt;

#[derive(Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub struct Module {
    code: Vec<u8>,
}

impl Module {
    pub fn new(code: Vec<u8>) -> Module {
        Module { code }
    }

    pub fn code(&self) -> &[u8] {
        &self.code
    }
}

impl fmt::Debug for Module {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Module")
            .field("code", &hex::encode(&self.code))
            .finish()
    }
}
<|endoftext|>


<commit_before>fn main() { }
<commit_msg>Add stack example<commit_after>extern crate adt;

use adt::{
    Stack,
    VecStack
};

fn main() {
    // Initialize a VecStack stack.
    let mut stack: VecStack<int> = VecStack::new();

    // Push some elements onto the stack.
    stack.push(1);
    stack.push(2);
    stack.push(3);

    // Pop some elements off the stack.
    println!("{}", stack.pop());

    // Peek some elements from the stack.
    println!("{}", stack.peek());
}
<|endoftext|>


<commit_before>extern crate cursive;

use cursive::views::{Dialog, TextView};
use cursive::{theme, Cursive};

fn main() {
    let mut siv = Cursive::default();
    // You can load a theme from a file at runtime for fast development.
    siv.load_theme_file("assets/style.toml").unwrap();

    // Or you can directly load it from a string for easy deployment.
    siv.load_toml(include_str!("../assets/style.toml")).unwrap();

    siv.add_layer(
        Dialog::around(TextView::new(
            "This application uses a \
             custom theme!",
        )).title("Themed dialog")
            .button("Quit", |s| s.quit()),
    );

    siv.run();
}
<commit_msg>Remove unused import<commit_after>extern crate cursive;

use cursive::views::{Dialog, TextView};
use cursive::Cursive;

fn main() {
    let mut siv = Cursive::default();
    // You can load a theme from a file at runtime for fast development.
    siv.load_theme_file("assets/style.toml").unwrap();

    // Or you can directly load it from a string for easy deployment.
    siv.load_toml(include_str!("../assets/style.toml")).unwrap();

    siv.add_layer(
        Dialog::around(TextView::new(
            "This application uses a \
             custom theme!",
        )).title("Themed dialog")
            .button("Quit", |s| s.quit()),
    );

    siv.run();
}
<|endoftext|>


<commit_before>// Copyright 2017 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.

// @has intra_links/index.html
// @has - '//a/@href' '../intra_links/struct.ThisType.html'
// @has - '//a/@href' '../intra_links/enum.ThisEnum.html'
// @has - '//a/@href' '../intra_links/trait.ThisTrait.html'
// @has - '//a/@href' '../intra_links/type.ThisAlias.html'
// @has - '//a/@href' '../intra_links/union.ThisUnion.html'
// @has - '//a/@href' '../intra_links/fn.this_function.html'
// @has - '//a/@href' '../intra_links/constant.THIS_CONST.html'
// @has - '//a/@href' '../intra_links/static.THIS_STATIC.html'
// @has - '//a/@href' '../intra_links/macro.this_macro.html'
// @has - '//a/@href' '../intra_links/trait.SoAmbiguous.html'
// @has - '//a/@href' '../intra_links/fn.SoAmbiguous.html'
//! In this crate we would like to link to:
//!
//! * [`ThisType`](ThisType)
//! * [`ThisEnum`](ThisEnum)
//! * [`ThisTrait`](ThisTrait)
//! * [`ThisAlias`](ThisAlias)
//! * [`ThisUnion`](ThisUnion)
//! * [`this_function`](this_function())
//! * [`THIS_CONST`](const@THIS_CONST)
//! * [`THIS_STATIC`](static@THIS_STATIC)
//! * [`this_macro`](this_macro!)
//!
//! In addition, there's some specifics we want to look at. There's [a trait called
//! SoAmbiguous][ambig-trait], but there's also [a function called SoAmbiguous][ambig-fn] too!
//! Whatever shall we do?
//!
//! [ambig-trait]: trait@SoAmbiguous
//! [ambig-fn]: SoAmbiguous()

#[macro_export]
macro_rules! this_macro {
    () => {};
}

pub struct ThisType;
pub enum ThisEnum { ThisVariant, }
pub trait ThisTrait {}
pub type ThisAlias = Result<(), ()>;
pub union ThisUnion { this_field: usize, }

pub fn this_function() {}
pub const THIS_CONST: usize = 5usize;
pub static THIS_STATIC: usize = 5usize;

pub trait SoAmbiguous {}

#[allow(bad_style)]
pub fn SoAmbiguous() {}
<commit_msg>Add tests<commit_after>// Copyright 2017 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.

// @has intra_links/index.html
// @has - '//a/@href' '../intra_links/struct.ThisType.html'
// @has - '//a/@href' '../intra_links/struct.ThisType.html#method.this_method'
// @has - '//a/@href' '../intra_links/enum.ThisEnum.html'
// @has - '//a/@href' '../intra_links/enum.ThisEnum.html#ThisVariant.v'
// @has - '//a/@href' '../intra_links/trait.ThisTrait.html'
// @has - '//a/@href' '../intra_links/trait.ThisTrait.html#tymethod.this_associated_method'
// @has - '//a/@href' '../intra_links/trait.ThisTrait.html#associatedtype.ThisAssociatedType'
// @has - '//a/@href' '../intra_links/trait.ThisTrait.html#associatedconstant.THIS_ASSOCIATED_CONST'
// @has - '//a/@href' '../intra_links/trait.ThisTrait.html'
// @has - '//a/@href' '../intra_links/type.ThisAlias.html'
// @has - '//a/@href' '../intra_links/union.ThisUnion.html'
// @has - '//a/@href' '../intra_links/fn.this_function.html'
// @has - '//a/@href' '../intra_links/constant.THIS_CONST.html'
// @has - '//a/@href' '../intra_links/static.THIS_STATIC.html'
// @has - '//a/@href' '../intra_links/macro.this_macro.html'
// @has - '//a/@href' '../intra_links/trait.SoAmbiguous.html'
// @has - '//a/@href' '../intra_links/fn.SoAmbiguous.html'
//! In this crate we would like to link to:
//!
//! * [`ThisType`](ThisType)
//! * [`ThisType::this_method`](ThisType::this_method)
//! * [`ThisEnum`](ThisEnum)
//! * [`ThisEnum::ThisVariant`](ThisEnum::ThisVariant)
//! * [`ThisTrait`](ThisTrait)
//! * [`ThisTrait::this_associated_method`](ThisTrait::this_associated_method)
//! * [`ThisTrait::ThisAssociatedType`](ThisTrait::ThisAssociatedType)
//! * [`ThisTrait::THIS_ASSOCIATED_CONST`](ThisTrait::THIS_ASSOCIATED_CONST)
//! * [`ThisAlias`](ThisAlias)
//! * [`ThisUnion`](ThisUnion)
//! * [`this_function`](this_function())
//! * [`THIS_CONST`](const@THIS_CONST)
//! * [`THIS_STATIC`](static@THIS_STATIC)
//! * [`this_macro`](this_macro!)
//!
//! In addition, there's some specifics we want to look at. There's [a trait called
//! SoAmbiguous][ambig-trait], but there's also [a function called SoAmbiguous][ambig-fn] too!
//! Whatever shall we do?
//!
//! [ambig-trait]: trait@SoAmbiguous
//! [ambig-fn]: SoAmbiguous()

#[macro_export]
macro_rules! this_macro {
    () => {};
}

pub struct ThisType;

impl ThisType {
    pub fn this_method() {}
}
pub enum ThisEnum { ThisVariant, }
pub trait ThisTrait {
    type ThisAssociatedType;
    const THIS_ASSOCIATED_CONST: u8;
    fn this_associated_method();
}
pub type ThisAlias = Result<(), ()>;
pub union ThisUnion { this_field: usize, }

pub fn this_function() {}
pub const THIS_CONST: usize = 5usize;
pub static THIS_STATIC: usize = 5usize;

pub trait SoAmbiguous {}

#[allow(bad_style)]
pub fn SoAmbiguous() {}
<|endoftext|>


<commit_before>// run-pass

// aux-build:helper.rs
// no-prefer-dynamic

#![feature(allocator_api)]
#![feature(slice_ptr_get)]

extern crate helper;

use std::alloc::{self, AllocRef, Global, Layout, System};
use std::sync::atomic::{AtomicUsize, Ordering};

static HITS: AtomicUsize = AtomicUsize::new(0);

struct A;

unsafe impl alloc::GlobalAlloc for A {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        HITS.fetch_add(1, Ordering::SeqCst);
        AllocRef::alloc(&System, layout).unwrap().as_mut_ptr()
    }

    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        HITS.fetch_add(1, Ordering::SeqCst);
        System.dealloc(ptr, layout)
    }
}

#[global_allocator]
static GLOBAL: A = A;

fn main() {
    println!("hello!");

    let n = HITS.load(Ordering::SeqCst);
    assert!(n > 0);
    unsafe {
        let layout = Layout::from_size_align(4, 2).unwrap();

        let memory = Global.alloc(layout.clone()).unwrap();
        helper::work_with(&memory);
        assert_eq!(HITS.load(Ordering::SeqCst), n + 1);
        Global.dealloc(memory.as_non_null_ptr(), layout);
        assert_eq!(HITS.load(Ordering::SeqCst), n + 2);

        let s = String::with_capacity(10);
        helper::work_with(&s);
        assert_eq!(HITS.load(Ordering::SeqCst), n + 3);
        drop(s);
        assert_eq!(HITS.load(Ordering::SeqCst), n + 4);

        let memory = System.alloc(layout.clone()).unwrap();
        assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
        helper::work_with(&memory);
        System.dealloc(memory.as_non_null_ptr(), layout);
        assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
    }
}
<commit_msg>fixing the custom.rs<commit_after>// run-pass

// aux-build:helper.rs
// no-prefer-dynamic

#![feature(allocator_api)]
#![feature(slice_ptr_get)]

extern crate helper;

use std::alloc::{self, AllocRef, Global, Layout, System};
use std::sync::atomic::{AtomicUsize, Ordering};

static HITS: AtomicUsize = AtomicUsize::new(0);

struct A;

unsafe impl alloc::GlobalAlloc for A {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        HITS.fetch_add(1, Ordering::SeqCst);
        AllocRef::alloc(&System, layout).unwrap().as_mut_ptr()
    }

    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        HITS.fetch_add(1, Ordering::SeqCst);
        AllocRef::dealloc(&System, ptr, layout)
    }
}

#[global_allocator]
static GLOBAL: A = A;

fn main() {
    println!("hello!");

    let n = HITS.load(Ordering::SeqCst);
    assert!(n > 0);
    unsafe {
        let layout = Layout::from_size_align(4, 2).unwrap();

        let memory = Global.alloc(layout.clone()).unwrap();
        helper::work_with(&memory);
        assert_eq!(HITS.load(Ordering::SeqCst), n + 1);
        Global.dealloc(memory.as_non_null_ptr(), layout);
        assert_eq!(HITS.load(Ordering::SeqCst), n + 2);

        let s = String::with_capacity(10);
        helper::work_with(&s);
        assert_eq!(HITS.load(Ordering::SeqCst), n + 3);
        drop(s);
        assert_eq!(HITS.load(Ordering::SeqCst), n + 4);

        let memory = System.alloc(layout.clone()).unwrap();
        assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
        helper::work_with(&memory);
        System.dealloc(memory.as_non_null_ptr(), layout);
        assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
    }
}
<|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 super::objects::{MimirObject, Admin};
use chrono;
use regex;
use hyper;
use hyper::status::StatusCode;
use rs_es::error::EsError;
use rs_es;
use rs_es::EsResponse;
use serde_json;
use rs_es::operations::search::ScanResult;

use super::objects::{AliasOperations, AliasOperation, AliasParameter};
use rs_es::units::Duration;

const SYNONYMS: [&'static str; 17] = ["cc,centre commercial",
                                      "hotel de ville,mairie",
                                      "gare sncf,gare",
                                      "chu,chr,hopital",
                                      "ld,lieu-dit",
                                      "st,saint",
                                      "ste,sainte",
                                      "bvd,bld,bd,boulevard",
                                      "pt,pont",
                                      "rle,ruelle",
                                      "rte,route",
                                      "vla,villa",
                                      "grand-champ,grandchamp",
                                      "fac,faculte,ufr,universite",
                                      "embarcadere,gare maritime",
                                      "cpam,securite sociale",
                                      "anpe,pole emploi"];

// Rubber is an wrapper around elasticsearch API
pub struct Rubber {
    es_client: rs_es::Client,
    // some operation are not implemented in rs_es, we need to use a raw http client
    http_client: hyper::client::Client,
}

/// return the index associated to the given type and dataset
/// this will be an alias over another real index
fn get_main_type_and_dataset_index(doc_type: &str, dataset: &str) -> String {
    format!("munin_{}_{}", doc_type, dataset)
}

/// return the index associated to the given type
/// this will be an alias over another real index
fn get_main_type_index(doc_type: &str) -> String {
    format!("munin_{}", doc_type)
}

impl Rubber {
    // build a rubber with a connection string (http://host:port/)
    pub fn new(cnx: &str) -> Rubber {
        let re = regex::Regex::new(r"(?:https?://)?(?P<host>.+?):(?P<port>\d+)").unwrap();
        let cap = re.captures(cnx).unwrap();
        let host = cap.name("host").unwrap().as_str();
        let port = cap.name("port").unwrap().as_str().parse::<u32>().unwrap();
        info!("elastic search host {:?} port {:?}", host, port);

        Rubber {
            es_client: rs_es::Client::new(&host, port),
            http_client: hyper::client::Client::new(),
        }
    }

    pub fn get(&self, path: &str) -> Result<hyper::client::response::Response, EsError> {
        // Note: a bit duplicate on rs_es because some ES operations are not implemented
        debug!("doing a get on {}", path);
        let url = self.es_client.full_url(path);
        let result = try!(self.http_client
            .get(&url)
            .send());
        rs_es::do_req(result)
    }
    fn put(&self, path: &str, body: &str) -> Result<hyper::client::response::Response, EsError> {
        // Note: a bit duplicate on rs_es because some ES operations are not implemented
        debug!("doing a put on {} with {}", path, body);
        let url = self.es_client.full_url(path);
        let result = try!(self.http_client
            .put(&url)
            .body(body)
            .send());
        rs_es::do_req(result)
    }
    fn post(&self, path: &str, body: &str) -> Result<hyper::client::response::Response, EsError> {
        // Note: a bit duplicate on rs_es because some ES operations are not implemented
        debug!("doing a post on {} with {}", path, body);
        let url = self.es_client.full_url(path);
        let result = try!(self.http_client
            .post(&url)
            .body(body)
            .send());
        rs_es::do_req(result)
    }

    pub fn make_index(&self, doc_type: &str, dataset: &str) -> Result<String, String> {
        let current_time = chrono::UTC::now().format("%Y%m%d_%H%M%S_%f");
        let index_name = format!("munin_{}_{}_{}", doc_type, dataset, current_time);
        info!("creating index {}", index_name);
        self.create_index(&index_name.to_string()).map(|_| index_name)
    }

    fn create_index(&self, name: &String) -> Result<(), String> {
        debug!("creating index");
        // Note: in rs_es it can be done with MappingOperation but for the moment I think
        // storing the mapping in json is more convenient
        let analysis = include_str!("../../../json/settings.json");

        let mut analysis_json_value = try!(serde_json::from_str::<serde_json::Value>(&analysis)
            .map_err(|err| format!("{}", err)));

        let synonyms: Vec<_> = SYNONYMS.iter()
            .map(|s| serde_json::Value::String(s.to_string()))
            .collect();

        *analysis_json_value.pointer_mut("/settings/analysis/filter/synonym_filter/synonyms")
            .unwrap() = serde_json::Value::Array(synonyms);

        self.put(name, &analysis_json_value.to_string())
            .map_err(|e| {
                info!("Error while creating new index {}", name);
                e.to_string()
            })
            .and_then(|res| if res.status == StatusCode::Ok {
                Ok(())
            } else {
                Err(format!("cannot create index: {:?}", res))
            })
    }

    // get the last indexes for this doc_type/dataset
    // Note: to be resilient to ghost ES indexes, we return all indexes for this doc_type/dataset
    // but the new index
    fn get_last_index(&self,
                      new_index: &str,
                      doc_type: &str,
                      dataset: &str)
                      -> Result<Vec<String>, String> {
        let base_index = get_main_type_and_dataset_index(doc_type, dataset);
        self.get(&format!("{}*/_aliases", base_index))
            .map_err(|e| e.to_string())
            .and_then(|res| match res.status {
                StatusCode::Ok => {
                    let value: serde_json::Value = try!(res.read_response()
                        .map_err(|e| e.to_string()));
                    Ok(value.as_object()
                        .map(|aliases| {
                            aliases.keys()
                                // new_index is not an old index
                                .filter(|i| i.as_str() != new_index)
                                .cloned()
                                .collect()
                        })
                        .unwrap_or_else(|| {
                            info!("no previous index to delete for type {} and dataset {}",
                                  doc_type,
                                  dataset);
                            vec![]
                        }))
                }
                StatusCode::NotFound => {
                    info!("impossible to find alias {}, no last index to remove",
                          base_index);
                    Ok(vec![])
                }
                _ => Err(format!("invalid elasticsearch response: {:?}", res)),
            })
    }

    /// publish the index as the new index for this doc_type and this dataset
    /// move the index alias of the doc_type and the dataset to point to this indexes
    /// and remove the old index
    pub fn publish_index(&mut self,
                         doc_type: &str,
                         dataset: &str,
                         index: String,
                         is_geo_data: bool)
                         -> Result<(), String> {
        debug!("publishing index");
        let last_indexes = try!(self.get_last_index(&index, doc_type, dataset));

        let dataset_index = get_main_type_and_dataset_index(doc_type, dataset);
        try!(self.alias(&dataset_index, &vec![index.clone()], &last_indexes));

        let type_index = get_main_type_index(doc_type);
        try!(self.alias(&type_index, &vec![dataset_index.clone()], &last_indexes));

        if is_geo_data {
            try!(self.alias("munin_geo_data", &vec![type_index.to_string()], &vec![]));
            try!(self.alias("munin", &vec!["munin_geo_data".to_string()], &vec![]));
        } else {
            try!(self.alias("munin", &vec![type_index.to_string()], &vec![]));
        }
        for i in last_indexes {
            try!(self.delete_index(&i));
        }
        Ok(())
    }

    pub fn is_existing_index(&self, name: &String) -> Result<bool, String> {
        self.get(&name)
            .map_err(|e| e.to_string())
            .map(|res| res.status == StatusCode::Ok)
    }

    /// add a list of new indexes to the alias
    /// remove a list of indexes from the alias
    fn alias(&self, alias: &str, add: &Vec<String>, remove: &Vec<String>) -> Result<(), String> {
        info!("for {}, adding alias {:?}, removing {:?}",
              alias,
              add,
              remove);
        let add_operations = add.iter().map(|x| {
            AliasOperation {
                remove: None,
                add: Some(AliasParameter {
                    index: x.clone(),
                    alias: alias.to_string(),
                }),
            }
        });
        let remove_operations = remove.iter().map(|x| {
            AliasOperation {
                add: None,
                remove: Some(AliasParameter {
                    index: x.clone(),
                    alias: alias.to_string(),
                }),
            }
        });
        let operations =
            AliasOperations { actions: add_operations.chain(remove_operations).collect() };
        let json = serde_json::to_string(&operations).unwrap();
        self.post("_aliases", &json)
            .map_err(|e| e.to_string())
            .and_then(|res| if res.status == StatusCode::Ok {
                Ok(())
            } else {
                error!("failed to change aliases for {}, es response: {:?}",
                       alias,
                       res);
                Err(format!("failed to post aliases for {}: {:?}", alias, res).to_string())
            })
    }

    pub fn delete_index(&mut self, index: &String) -> Result<(), String> {
        debug!("deleting index {}", &index);
        let res = self.es_client
            .delete_index(&index)
            .map(|res| res.acknowledged)
            .unwrap_or(false);
        if !res {
            Err(format!("Error deleting index {}", &index).into())
        } else {
            Ok(())
        }
    }

    pub fn bulk_index<T, I>(&mut self,
                            index: &String,
                            iter: I)
                            -> Result<usize, rs_es::error::EsError>
        where T: MimirObject,
              I: Iterator<Item = T>
    {
        use rs_es::operations::bulk::Action;
        let mut nb = 0;
        let chunk_size = 1000;
        // fold is used for creating the action and optionally set the id of the object
        let mut actions = iter.map(|v| {
            v.es_id()
                .into_iter()
                .fold(Action::index(v), |action, id| action.with_id(id))
        });
        loop {
            let chunk = actions.by_ref().take(chunk_size).collect::<Vec<_>>();
            nb += chunk.len();
            try!(self.es_client
                .bulk(&chunk)
                .with_index(&index)
                .with_doc_type(T::doc_type())
                .send());

            if chunk.len() < chunk_size {
                break;
            }
        }

        Ok(nb)
    }

    /// add all the element of 'iter' into elasticsearch
    ///
    /// To have zero downtime:
    /// first all the elements are added in a temporary index and when all has been indexed
    /// the index is published and the old index is removed
    pub fn index<T, I>(&mut self, dataset: &str, iter: I) -> Result<usize, String>
        where T: MimirObject,
              I: Iterator<Item = T>
    {
        // TODO better error handling
        let index = try!(self.make_index(T::doc_type(), dataset));
        let nb_elements = try!(self.bulk_index(&index, iter).map_err(|e| e.to_string()));
        try!(self.publish_index(T::doc_type(), dataset, index, T::is_geo_data()));
        Ok(nb_elements)
    }

    pub fn get_admins_from_dataset(&mut self,
                                   dataset: &str)
                                   -> Result<Vec<Admin>, rs_es::error::EsError> {
        self.get_admins_from_index(&get_main_type_and_dataset_index(Admin::doc_type(), dataset))
    }

    pub fn get_all_admins(&mut self) -> Result<Vec<Admin>, rs_es::error::EsError> {
        self.get_admins_from_index(&get_main_type_index(Admin::doc_type()))
    }

    fn get_admins_from_index(&mut self, index: &str) -> Result<Vec<Admin>, rs_es::error::EsError> {
        let mut result: Vec<Admin> = vec![];
        let mut scan: ScanResult<Admin> = try!(self.es_client
            .search_query()
            .with_indexes(&[&index])
            .with_size(1000)
            .with_types(&[&Admin::doc_type()])
            .scan(&Duration::minutes(1)));
        loop {
            let page = try!(scan.scroll(&mut self.es_client, &Duration::minutes(1)));
            if page.hits.hits.len() == 0 {
                break;
            }
            result.extend(page.hits.hits.into_iter().filter_map(|hit| hit.source).map(|ad| *ad));
        }
        try!(scan.close(&mut self.es_client));
        Ok(result)
    }
}

#[test]
pub fn test_valid_url() {
    Rubber::new("http://localhost:9200");
    Rubber::new("localhost:9200");
}

#[test]
#[should_panic]
pub fn test_invalid_url() {
    Rubber::new("http://bob");
}

#[test]
#[should_panic]
pub fn test_invalid_url_no_port() {
    Rubber::new("localhost");
}
<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 super::objects::{MimirObject, Admin};
use chrono;
use regex;
use hyper;
use hyper::status::StatusCode;
use rs_es::error::EsError;
use rs_es;
use rs_es::EsResponse;
use serde_json;
use rs_es::operations::search::ScanResult;

use super::objects::{AliasOperations, AliasOperation, AliasParameter};
use rs_es::units::Duration;

const SYNONYMS: [&'static str; 17] = ["cc,centre commercial",
                                      "hotel de ville,mairie",
                                      "gare sncf,gare",
                                      "chu,chr,hopital",
                                      "ld,lieu-dit",
                                      "st,saint",
                                      "ste,sainte",
                                      "bvd,bld,bd,boulevard",
                                      "pt,pont",
                                      "rle,ruelle",
                                      "rte,route",
                                      "vla,villa",
                                      "grand-champ,grandchamp",
                                      "fac,faculte,ufr,universite",
                                      "embarcadere,gare maritime",
                                      "cpam,securite sociale",
                                      "anpe,pole emploi"];

// Rubber is an wrapper around elasticsearch API
pub struct Rubber {
    es_client: rs_es::Client,
    // some operation are not implemented in rs_es, we need to use a raw http client
    http_client: hyper::client::Client,
}

/// return the index associated to the given type and dataset
/// this will be an alias over another real index
fn get_main_type_and_dataset_index(doc_type: &str, dataset: &str) -> String {
    format!("munin_{}_{}", doc_type, dataset)
}

/// return the index associated to the given type
/// this will be an alias over another real index
fn get_main_type_index(doc_type: &str) -> String {
    format!("munin_{}", doc_type)
}

impl Rubber {
    // build a rubber with a connection string (http://host:port/)
    pub fn new(cnx: &str) -> Rubber {
        let re = regex::Regex::new(r"(?:https?://)?(?P<host>.+?):(?P<port>\d+)").unwrap();
        let cap = re.captures(cnx).unwrap();
        let host = cap.name("host").unwrap().as_str();
        let port = cap.name("port").unwrap().as_str().parse::<u32>().unwrap();
        info!("elastic search host {:?} port {:?}", host, port);

        Rubber {
            es_client: rs_es::Client::new(&host, port),
            http_client: hyper::client::Client::new(),
        }
    }

    pub fn get(&self, path: &str) -> Result<hyper::client::response::Response, EsError> {
        // Note: a bit duplicate on rs_es because some ES operations are not implemented
        debug!("doing a get on {}", path);
        let url = self.es_client.full_url(path);
        let result = try!(self.http_client
            .get(&url)
            .send());
        rs_es::do_req(result)
    }
    fn put(&self, path: &str, body: &str) -> Result<hyper::client::response::Response, EsError> {
        // Note: a bit duplicate on rs_es because some ES operations are not implemented
        debug!("doing a put on {} with {}", path, body);
        let url = self.es_client.full_url(path);
        let result = try!(self.http_client
            .put(&url)
            .body(body)
            .send());
        rs_es::do_req(result)
    }
    fn post(&self, path: &str, body: &str) -> Result<hyper::client::response::Response, EsError> {
        // Note: a bit duplicate on rs_es because some ES operations are not implemented
        debug!("doing a post on {} with {}", path, body);
        let url = self.es_client.full_url(path);
        let result = try!(self.http_client
            .post(&url)
            .body(body)
            .send());
        rs_es::do_req(result)
    }

    pub fn make_index(&self, doc_type: &str, dataset: &str) -> Result<String, String> {
        let current_time = chrono::UTC::now().format("%Y%m%d_%H%M%S_%f");
        let index_name = format!("munin_{}_{}_{}", doc_type, dataset, current_time);
        info!("creating index {}", index_name);
        self.create_index(&index_name.to_string()).map(|_| index_name)
    }

    fn create_index(&self, name: &String) -> Result<(), String> {
        debug!("creating index");
        // Note: in rs_es it can be done with MappingOperation but for the moment I think
        // storing the mapping in json is more convenient
        let analysis = include_str!("../../../json/settings.json");

        let mut analysis_json_value = try!(serde_json::from_str::<serde_json::Value>(&analysis)
            .map_err(|err| format!("{}", err)));

        let synonyms: Vec<_> = SYNONYMS.iter()
            .map(|s| serde_json::Value::String(s.to_string()))
            .collect();

        *analysis_json_value.pointer_mut("/settings/analysis/filter/synonym_filter/synonyms")
            .unwrap() = serde_json::Value::Array(synonyms);

        self.put(name, &analysis_json_value.to_string())
            .map_err(|e| {
                info!("Error while creating new index {}", name);
                e.to_string()
            })
            .and_then(|res| if res.status == StatusCode::Ok {
                Ok(())
            } else {
                Err(format!("cannot create index: {:?}", res))
            })
    }

    // get the last indexes for this doc_type/dataset
    // Note: to be resilient to ghost ES indexes, we return all indexes for this doc_type/dataset
    // but the new index
    fn get_last_index(&self,
                      new_index: &str,
                      doc_type: &str,
                      dataset: &str)
                      -> Result<Vec<String>, String> {
        let base_index = get_main_type_and_dataset_index(doc_type, dataset);
        self.get(&format!("{}*/_aliases", base_index))
            .map_err(|e| e.to_string())
            .and_then(|res| match res.status {
                StatusCode::Ok => {
                    let value: serde_json::Value = try!(res.read_response()
                        .map_err(|e| e.to_string()));
                    Ok(value.as_object()
                        .map(|aliases| {
                            aliases.keys()
                                // we don't want to remove the newly created index
                                .filter(|i| i.as_str() != new_index)
                                .cloned()
                                .collect()
                        })
                        .unwrap_or_else(|| {
                            info!("no previous index to delete for type {} and dataset {}",
                                  doc_type,
                                  dataset);
                            vec![]
                        }))
                }
                StatusCode::NotFound => {
                    info!("impossible to find alias {}, no last index to remove",
                          base_index);
                    Ok(vec![])
                }
                _ => Err(format!("invalid elasticsearch response: {:?}", res)),
            })
    }

    /// publish the index as the new index for this doc_type and this dataset
    /// move the index alias of the doc_type and the dataset to point to this indexes
    /// and remove the old index
    pub fn publish_index(&mut self,
                         doc_type: &str,
                         dataset: &str,
                         index: String,
                         is_geo_data: bool)
                         -> Result<(), String> {
        debug!("publishing index");
        let last_indexes = try!(self.get_last_index(&index, doc_type, dataset));

        let dataset_index = get_main_type_and_dataset_index(doc_type, dataset);
        try!(self.alias(&dataset_index, &vec![index.clone()], &last_indexes));

        let type_index = get_main_type_index(doc_type);
        try!(self.alias(&type_index, &vec![dataset_index.clone()], &last_indexes));

        if is_geo_data {
            try!(self.alias("munin_geo_data", &vec![type_index.to_string()], &vec![]));
            try!(self.alias("munin", &vec!["munin_geo_data".to_string()], &vec![]));
        } else {
            try!(self.alias("munin", &vec![type_index.to_string()], &vec![]));
        }
        for i in last_indexes {
            try!(self.delete_index(&i));
        }
        Ok(())
    }

    pub fn is_existing_index(&self, name: &String) -> Result<bool, String> {
        self.get(&name)
            .map_err(|e| e.to_string())
            .map(|res| res.status == StatusCode::Ok)
    }

    /// add a list of new indexes to the alias
    /// remove a list of indexes from the alias
    fn alias(&self, alias: &str, add: &Vec<String>, remove: &Vec<String>) -> Result<(), String> {
        info!("for {}, adding alias {:?}, removing {:?}",
              alias,
              add,
              remove);
        let add_operations = add.iter().map(|x| {
            AliasOperation {
                remove: None,
                add: Some(AliasParameter {
                    index: x.clone(),
                    alias: alias.to_string(),
                }),
            }
        });
        let remove_operations = remove.iter().map(|x| {
            AliasOperation {
                add: None,
                remove: Some(AliasParameter {
                    index: x.clone(),
                    alias: alias.to_string(),
                }),
            }
        });
        let operations =
            AliasOperations { actions: add_operations.chain(remove_operations).collect() };
        let json = serde_json::to_string(&operations).unwrap();
        self.post("_aliases", &json)
            .map_err(|e| e.to_string())
            .and_then(|res| if res.status == StatusCode::Ok {
                Ok(())
            } else {
                error!("failed to change aliases for {}, es response: {:?}",
                       alias,
                       res);
                Err(format!("failed to post aliases for {}: {:?}", alias, res).to_string())
            })
    }

    pub fn delete_index(&mut self, index: &String) -> Result<(), String> {
        debug!("deleting index {}", &index);
        let res = self.es_client
            .delete_index(&index)
            .map(|res| res.acknowledged)
            .unwrap_or(false);
        if !res {
            Err(format!("Error deleting index {}", &index).into())
        } else {
            Ok(())
        }
    }

    pub fn bulk_index<T, I>(&mut self,
                            index: &String,
                            iter: I)
                            -> Result<usize, rs_es::error::EsError>
        where T: MimirObject,
              I: Iterator<Item = T>
    {
        use rs_es::operations::bulk::Action;
        let mut nb = 0;
        let chunk_size = 1000;
        // fold is used for creating the action and optionally set the id of the object
        let mut actions = iter.map(|v| {
            v.es_id()
                .into_iter()
                .fold(Action::index(v), |action, id| action.with_id(id))
        });
        loop {
            let chunk = actions.by_ref().take(chunk_size).collect::<Vec<_>>();
            nb += chunk.len();
            try!(self.es_client
                .bulk(&chunk)
                .with_index(&index)
                .with_doc_type(T::doc_type())
                .send());

            if chunk.len() < chunk_size {
                break;
            }
        }

        Ok(nb)
    }

    /// add all the element of 'iter' into elasticsearch
    ///
    /// To have zero downtime:
    /// first all the elements are added in a temporary index and when all has been indexed
    /// the index is published and the old index is removed
    pub fn index<T, I>(&mut self, dataset: &str, iter: I) -> Result<usize, String>
        where T: MimirObject,
              I: Iterator<Item = T>
    {
        // TODO better error handling
        let index = try!(self.make_index(T::doc_type(), dataset));
        let nb_elements = try!(self.bulk_index(&index, iter).map_err(|e| e.to_string()));
        try!(self.publish_index(T::doc_type(), dataset, index, T::is_geo_data()));
        Ok(nb_elements)
    }

    pub fn get_admins_from_dataset(&mut self,
                                   dataset: &str)
                                   -> Result<Vec<Admin>, rs_es::error::EsError> {
        self.get_admins_from_index(&get_main_type_and_dataset_index(Admin::doc_type(), dataset))
    }

    pub fn get_all_admins(&mut self) -> Result<Vec<Admin>, rs_es::error::EsError> {
        self.get_admins_from_index(&get_main_type_index(Admin::doc_type()))
    }

    fn get_admins_from_index(&mut self, index: &str) -> Result<Vec<Admin>, rs_es::error::EsError> {
        let mut result: Vec<Admin> = vec![];
        let mut scan: ScanResult<Admin> = try!(self.es_client
            .search_query()
            .with_indexes(&[&index])
            .with_size(1000)
            .with_types(&[&Admin::doc_type()])
            .scan(&Duration::minutes(1)));
        loop {
            let page = try!(scan.scroll(&mut self.es_client, &Duration::minutes(1)));
            if page.hits.hits.len() == 0 {
                break;
            }
            result.extend(page.hits.hits.into_iter().filter_map(|hit| hit.source).map(|ad| *ad));
        }
        try!(scan.close(&mut self.es_client));
        Ok(result)
    }
}

#[test]
pub fn test_valid_url() {
    Rubber::new("http://localhost:9200");
    Rubber::new("localhost:9200");
}

#[test]
#[should_panic]
pub fn test_invalid_url() {
    Rubber::new("http://bob");
}

#[test]
#[should_panic]
pub fn test_invalid_url_no_port() {
    Rubber::new("localhost");
}
<|endoftext|>


<commit_before>extern crate flac;
extern crate crypto;

use crypto::digest::Digest;
use crypto::md5::Md5;
use flac::Stream;
use std::cmp;

fn to_bytes(value: i32, buffer: &mut [u8]) {
  buffer[0] = value as u8;
  buffer[1] = (value >> 8) as u8;
  buffer[2] = (value >> 16) as u8;
  buffer[3] = (value >> 24) as u8;
}

fn get_offset(sample_size: usize) -> usize {
  let bits_per_sample = cmp::max(sample_size, 8);

  bits_per_sample / 8
}

#[test]
fn test_decoded_md5_sum() {
  let filenames = [
    "tests/assets/input-pictures.flac",
    "tests/assets/input-SCPAP.flac",
    "tests/assets/input-SVAUP.flac",
  ];

  let mut stream  = Stream::from_file(filename).unwrap();
  let mut buffer  = [0; 4];
  let mut md5     = Md5::new();
  let mut md5_sum = [0; 16];

  let info   = stream.info();
  let offset = get_offset(info.bits_per_sample as usize);

  for sample in stream.iter() {
    to_bytes(sample, &mut buffer);

    md5.input(&buffer[0..offset]);
  }

  md5.result(&mut md5_sum);

  assert_eq!(md5_sum, info.md5_sum);
}
<commit_msg>Change to block based sections<commit_after>extern crate flac;
extern crate crypto;

use crypto::digest::Digest;
use crypto::md5::Md5;
use flac::Stream;
use std::cmp;

fn to_bytes(value: i32, buffer: &mut [u8]) {
  buffer[0] = value as u8;
  buffer[1] = (value >> 8) as u8;
  buffer[2] = (value >> 16) as u8;
  buffer[3] = (value >> 24) as u8;
}

fn get_offset(sample_size: usize) -> usize {
  let bits_per_sample = cmp::max(sample_size, 8);

  bits_per_sample / 8
}

#[test]
fn test_decoded_md5_sum() {
  let filenames = [
    "tests/assets/input-pictures.flac",
    "tests/assets/input-SCPAP.flac",
    "tests/assets/input-SVAUP.flac",
  ];

  let mut buffer  = [0; 4];
  let mut md5     = Md5::new();
  let mut md5_sum = [0; 16];

  {
    let mut stream = Stream::from_file(filenames[0]).unwrap();

    let info   = stream.info();
    let offset = get_offset(info.bits_per_sample as usize);

    for sample in stream.iter() {
      to_bytes(sample, &mut buffer);

      md5.input(&buffer[0..offset]);
    }

    md5.result(&mut md5_sum);

    assert_eq!(md5_sum, info.md5_sum);
  }
}
<|endoftext|>


<commit_before>extern crate rsoundio;

use std::os::raw::c_int;

#[test]
fn test_outstream() {
    println!("test: OutStream");
    let sio = rsoundio::SoundIo::new();
    assert!(sio.connect().is_none());
    // assert!(sio.connect_backend(rsoundio::ffi::SioBackend::Alsa).is_none());
    println!("current backend: {}", sio.current_backend().unwrap());
    sio.flush_events();
    let dev_idx = sio.default_output_device_index().unwrap();
    let dev = sio.get_output_device(dev_idx).unwrap();
    println!("device: {}, ref_count: {}", dev, dev.ref_count());
    let mut stream = dev.create_outstream().unwrap();
    assert!(stream.open().is_none());
    let fmt = stream.current_format().unwrap();
    println!("current format: {}", fmt);
    let cb = |out: rsoundio::OutStream, min: i32, max: i32| {
        println!("Closure: {}, {}", min, max);
    };
    let boxed_cb = Box::new(cb);
    stream.register_write_callback(boxed_cb);
    assert!(stream.start().is_none());
    loop {
        sio.wait_events();
    }
    assert!(stream.clear_buffer().is_none());
    assert!(stream.pause(true).is_none());
    assert!(stream.pause(false).is_none());
    println!("latency: {}", stream.get_latency().unwrap());
    stream.destroy();
}

unsafe extern "C" fn write_callback(raw_out: *mut rsoundio::ffi::SoundIoOutStream,
                                    min_frame_count: c_int,
                                    max_frame_count: c_int) {
    let out = rsoundio::OutStream::new(raw_out);
    let sr = out.get_sample_rate();
    let layout = out.get_layout();
    let channels = layout.channel_count();
    // osc stuff:
    let mut f = 8_000.0f32;
    // let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
    let mut sample = 0.0f32;

    let mut raw_areas: *mut rsoundio::ffi::SoundIoChannelArea = ::std::ptr::null_mut();
    let mut frames_left = max_frame_count;
    let mut block_size = frames_left;
    while frames_left > 0 {
        if let Some(err) = out.begin_write(&mut raw_areas, &mut block_size) {
            panic!("{}", err);
        }
        if block_size <= 0 {
            break;
        }

        let areas = unsafe { ::std::slice::from_raw_parts_mut(raw_areas, channels as usize) };
        let mut dir = 1.0;
        for idx in 0..block_size {
            if f >= 8_000.0 || f <= 60.0 {
                dir *= -1.0
            };
            f += dir * 1.0;
            let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
            sample = (phi * (idx as f32)).sin();
            assert!(sample.abs() < 1.001);
            for ch_idx in 0..channels {
                let addr = (areas[ch_idx as usize].ptr as usize +
                            areas[ch_idx as usize].step as usize *
                            idx as usize) as *mut f32;
                unsafe { *addr = sample };
            }
        }
        assert!(out.end_write().is_none());
        frames_left -= block_size;
    }
}
<commit_msg>Test new callback registrations<commit_after>extern crate rsoundio;

use std::os::raw::c_int;

#[test]
fn test_outstream() {
    println!("test: OutStream");
    let sio = rsoundio::SoundIo::new();
    assert!(sio.connect().is_none());
    // assert!(sio.connect_backend(rsoundio::ffi::SioBackend::Alsa).is_none());
    println!("current backend: {}", sio.current_backend().unwrap());
    sio.flush_events();
    let dev_idx = sio.default_output_device_index().unwrap();
    let dev = sio.get_output_device(dev_idx).unwrap();
    println!("device: {}, ref_count: {}", dev, dev.ref_count());
    let mut stream = dev.create_outstream().unwrap();
    assert!(stream.open().is_none());
    let fmt = stream.current_format().unwrap();
    println!("current format: {}", fmt);
    let cb = |out: rsoundio::OutStream, min: i32, max: i32| {
        println!("Closure: {}, {}", min, max);
    };
    let boxed_cb = Box::new(cb);
    stream.register_write_callback(boxed_cb);
    let ucb = | out: rsoundio::OutStream | {
        println!("Underflow!")
    };
    stream.register_underflow_callback(Box::new(ucb));
    let ecb = | out: rsoundio::OutStream, err: rsoundio::ffi::SioError| {
        println!("Error: {}", err)
    };
    stream.register_error_callback(Box::new(ecb));
    assert!(stream.start().is_none());
    loop {
        sio.wait_events();
    }
    assert!(stream.clear_buffer().is_none());
    assert!(stream.pause(true).is_none());
    assert!(stream.pause(false).is_none());
    println!("latency: {}", stream.get_latency().unwrap());
    stream.destroy();
}

unsafe extern "C" fn write_callback(raw_out: *mut rsoundio::ffi::SoundIoOutStream,
                                    min_frame_count: c_int,
                                    max_frame_count: c_int) {
    let out = rsoundio::OutStream::new(raw_out);
    let sr = out.get_sample_rate();
    let layout = out.get_layout();
    let channels = layout.channel_count();
    // osc stuff:
    let mut f = 8_000.0f32;
    // let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
    let mut sample = 0.0f32;

    let mut raw_areas: *mut rsoundio::ffi::SoundIoChannelArea = ::std::ptr::null_mut();
    let mut frames_left = max_frame_count;
    let mut block_size = frames_left;
    while frames_left > 0 {
        if let Some(err) = out.begin_write(&mut raw_areas, &mut block_size) {
            panic!("{}", err);
        }
        if block_size <= 0 {
            break;
        }

        let areas = unsafe { ::std::slice::from_raw_parts_mut(raw_areas, channels as usize) };
        let mut dir = 1.0;
        for idx in 0..block_size {
            if f >= 8_000.0 || f <= 60.0 {
                dir *= -1.0
            };
            f += dir * 1.0;
            let phi = 2.0 * f * ::std::f32::consts::PI / (sr as f32);
            sample = (phi * (idx as f32)).sin();
            assert!(sample.abs() < 1.001);
            for ch_idx in 0..channels {
                let addr = (areas[ch_idx as usize].ptr as usize +
                            areas[ch_idx as usize].step as usize *
                            idx as usize) as *mut f32;
                unsafe { *addr = sample };
            }
        }
        assert!(out.end_write().is_none());
        frames_left -= block_size;
    }
}
<|endoftext|>


<commit_before>extern crate sovrin;

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

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;

#[macro_use]
mod utils;

use utils::wallet::WalletUtils;
use utils::signus::SignusUtils;
use utils::test::TestUtils;

use sovrin::api::ErrorCode;

mod high_cases {
    use super::*;

    mod register_wallet_type {
        use super::*;

        #[test]
        fn sovrin_register_wallet_type_works() {
            TestUtils::cleanup_storage();

            WalletUtils::register_wallet_type("inmem").unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod create_wallet {
        use super::*;

        #[test]
        fn sovrin_create_wallet_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works";
            let wallet_name = "sovrin_create_wallet_works";
            let xtype = "default";

            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_create_wallet_works_for_plugged() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works";
            let wallet_name = "sovrin_create_wallet_works";
            let xtype = "inmem";

            WalletUtils::register_wallet_type("inmem").unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_create_wallet_works_for_unknown_type() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works_for_unknown_type";
            let wallet_name = "sovrin_create_wallet_works_for_unknown_type";
            let xtype = "type";

            let res = WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None);
            assert_eq!(res.unwrap_err(), ErrorCode::WalletUnknownTypeError);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_create_wallet_works_for_empty_type() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works_for_empty_type";
            let wallet_name = "sovrin_create_wallet_works_for_empty_type";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_create_wallet_works_for_config() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works";
            let wallet_name = "sovrin_create_wallet_works";
            let xtype = "default";
            let config = r#"{"freshness_time":1000}"#;

            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), Some(config)).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod delete_wallet {
        use super::*;

        #[test]
        fn sovrin_delete_wallet_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_delete_wallet_works";
            let wallet_name = "sovrin_delete_wallet_works";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            WalletUtils::delete_wallet(wallet_name).unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_delete_wallet_works_for_plugged() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_delete_wallet_works_for_plugged";
            let wallet_name = "sovrin_delete_wallet_works_for_plugged";
            let xtype = "inmem";

            WalletUtils::register_wallet_type(xtype).unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None).unwrap();
            WalletUtils::delete_wallet(wallet_name).unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod open_wallet {
        use super::*;

        #[test]
        fn sovrin_open_wallet_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_open_wallet_works";
            let wallet_name = "sovrin_open_wallet_works";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            WalletUtils::open_wallet(wallet_name, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_open_wallet_works_for_config() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_open_wallet_works_for_config";
            let wallet_name = "sovrin_open_wallet_works_for_config";
            let config = r#"{"freshness_time":1000}"#;

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            WalletUtils::open_wallet(wallet_name, Some(config)).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod close_wallet {
        use super::*;

        #[test]
        fn sovrin_close_wallet_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_close_wallet_works";
            let wallet_name = "sovrin_close_wallet_works";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();

            let wallet_handle = WalletUtils::open_wallet(wallet_name, None).unwrap();
            WalletUtils::close_wallet(wallet_handle).unwrap();
            WalletUtils::open_wallet(wallet_name, None).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod set_seqno_wallet {
        use super::*;

        #[test]
        fn sovrin_wallet_set_seqno_works() {
            TestUtils::cleanup_storage();

            let wallet_handle = WalletUtils::create_and_open_wallet("sovrin_wallet_set_seqno_works", None).unwrap();

            let (did, _, _) = SignusUtils::create_my_did(wallet_handle, "{}").unwrap();

            WalletUtils::wallet_set_seq_no_for_value(wallet_handle, &did, 1).unwrap();

            TestUtils::cleanup_storage();
        }
    }
}

mod medium_cases {
    use super::*;

    mod create_wallet {
        use super::*;

        #[test]
        fn sovrin_create_wallet_works_for_duplicate_name() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works_for_duplicate_name";
            let wallet_name = "sovrin_create_wallet_works_for_duplicate_name";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            let res = WalletUtils::create_wallet(pool_name, wallet_name, None, None);
            assert_eq!(res.unwrap_err(), ErrorCode::WalletAlreadyExistsError);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_create_wallet_works_for_empty_name() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works_for_empty_name";
            let wallet_name = "";

            let res = WalletUtils::create_wallet(pool_name, wallet_name, None, None);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonInvalidParam3);

            TestUtils::cleanup_storage();
        }
    }

    mod delete_wallet {
        use super::*;

        #[test]
        fn sovrin_delete_wallet_works_for_invalid_wallet_name() {
            TestUtils::cleanup_storage();

            let res = WalletUtils::delete_wallet("sovrin_delete_wallet_works_for_invalid_wallet_name");
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_delete_wallet_works_for_twice() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_delete_wallet_works_for_deleted_wallet";
            let wallet_name = "sovrin_delete_wallet_works_for_deleted_wallet";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            WalletUtils::delete_wallet(wallet_name).unwrap();
            let res = WalletUtils::delete_wallet(wallet_name);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }
    }

    mod open_wallet {
        use super::*;

        #[test]
        fn sovrin_open_wallet_works_for_not_created_wallet() {
            TestUtils::cleanup_storage();

            let res = WalletUtils::open_wallet("sovrin_open_wallet_works_for_not_created_wallet", None);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }

        #[test]
        #[ignore] //TODO Check is not implemented
        fn sovrin_open_wallet_works_for_twice() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works";
            let wallet_name = "sovrin_open_wallet_works_for_twice";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();

            WalletUtils::open_wallet(wallet_name, None).unwrap();
            let res = WalletUtils::open_wallet(wallet_name, None);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_open_wallet_works_for_two_wallets() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_open_wallet_works_for_two_wallets";
            let wallet_name_1 = "sovrin_open_wallet_works_for_two_wallets1";
            let wallet_name_2 = "sovrin_open_wallet_works_for_two_wallets2";

            WalletUtils::create_wallet(pool_name, wallet_name_1, None, None).unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name_2, None, None).unwrap();
            WalletUtils::open_wallet(wallet_name_1, None).unwrap();
            WalletUtils::open_wallet(wallet_name_2, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_open_wallet_works_for_invalid_config() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_open_wallet_works_for_invalid_config";
            let wallet_name = "sovrin_open_wallet_works_for_invalid_config";
            let config = r#"{"field":"value"}"#;

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            let res = WalletUtils::open_wallet(wallet_name, Some(config));
            assert_eq!(res.unwrap_err(), ErrorCode::CommonInvalidStructure);

            TestUtils::cleanup_storage();
        }
    }

    mod close_wallet {
        use super::*;

        #[test]
        fn sovrin_close_wallet_works_for_invalid_handle() {
            TestUtils::cleanup_storage();

            let res = WalletUtils::close_wallet(1);
            assert_eq!(res.unwrap_err(), ErrorCode::WalletInvalidHandle);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_close_wallet_works_for_twice() {
            TestUtils::cleanup_storage();

            let wallet_handle = WalletUtils::create_and_open_wallet("sovrin_close_wallet_works_for_twice", None).unwrap();

            WalletUtils::close_wallet(wallet_handle).unwrap();
            let res = WalletUtils::close_wallet(wallet_handle);
            assert_eq!(res.unwrap_err(), ErrorCode::WalletInvalidHandle);

            TestUtils::cleanup_storage();
        }
    }

    mod set_seqno {
        use super::*;

        #[test]
        fn sovrin_wallet_set_seqno_works_for_not_exists_key() {
            TestUtils::cleanup_storage();

            let wallet_handle = WalletUtils::create_and_open_wallet("sovrin_wallet_set_seqno_works_for_not_exists_key", None).unwrap();

            //TODO may be we must return WalletNotFound in case if key not exists in wallet
            WalletUtils::wallet_set_seq_no_for_value(wallet_handle, "key", 1).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_wallet_set_seqno_works_for_invalid_wallet() {
            TestUtils::cleanup_storage();

            let wallet_handle = WalletUtils::create_and_open_wallet("sovrin_wallet_set_seqno_works_for_invalid_wallet", None).unwrap();

            let invalid_wallet_handle = wallet_handle + 1;
            let res = WalletUtils::wallet_set_seq_no_for_value(invalid_wallet_handle, "key", 1);
            assert_eq!(res.unwrap_err(), ErrorCode::WalletInvalidHandle);

            TestUtils::cleanup_storage();
        }
    }
}
<commit_msg>* Implemented high level integration test cases for sovrin_register_wallet_type<commit_after>extern crate sovrin;

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

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;

#[macro_use]
mod utils;

use utils::inmem_wallet::InmemWallet;
use utils::wallet::WalletUtils;
use utils::signus::SignusUtils;
use utils::test::TestUtils;

use sovrin::api::ErrorCode;

mod high_cases {
    use super::*;

    mod register_wallet_type {
        use super::*;

        #[test]
        fn sovrin_register_wallet_type_works() {
            TestUtils::cleanup_storage();
            InmemWallet::cleanup();

            WalletUtils::register_wallet_type("inmem").unwrap();

            TestUtils::cleanup_storage();
            InmemWallet::cleanup();
        }
    }

    mod create_wallet {
        use super::*;

        #[test]
        fn sovrin_create_wallet_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works";
            let wallet_name = "sovrin_create_wallet_works";
            let xtype = "default";

            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_create_wallet_works_for_plugged() {
            TestUtils::cleanup_storage();
            InmemWallet::cleanup();

            let pool_name = "sovrin_create_wallet_works";
            let wallet_name = "sovrin_create_wallet_works";
            let xtype = "inmem";

            WalletUtils::register_wallet_type("inmem").unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None).unwrap();

            TestUtils::cleanup_storage();
            InmemWallet::cleanup();
        }

        #[test]
        fn sovrin_create_wallet_works_for_unknown_type() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works_for_unknown_type";
            let wallet_name = "sovrin_create_wallet_works_for_unknown_type";
            let xtype = "type";

            let res = WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None);
            assert_eq!(res.unwrap_err(), ErrorCode::WalletUnknownTypeError);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_create_wallet_works_for_empty_type() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works_for_empty_type";
            let wallet_name = "sovrin_create_wallet_works_for_empty_type";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_create_wallet_works_for_config() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works";
            let wallet_name = "sovrin_create_wallet_works";
            let xtype = "default";
            let config = r#"{"freshness_time":1000}"#;

            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), Some(config)).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod delete_wallet {
        use super::*;

        #[test]
        fn sovrin_delete_wallet_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_delete_wallet_works";
            let wallet_name = "sovrin_delete_wallet_works";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            WalletUtils::delete_wallet(wallet_name).unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_delete_wallet_works_for_plugged() {
            TestUtils::cleanup_storage();
            InmemWallet::cleanup();

            let pool_name = "sovrin_delete_wallet_works_for_plugged";
            let wallet_name = "sovrin_delete_wallet_works_for_plugged";
            let xtype = "inmem";

            WalletUtils::register_wallet_type(xtype).unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None).unwrap();
            WalletUtils::delete_wallet(wallet_name).unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None).unwrap();

            TestUtils::cleanup_storage();
            InmemWallet::cleanup();
        }
    }

    mod open_wallet {
        use super::*;

        #[test]
        fn sovrin_open_wallet_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_open_wallet_works";
            let wallet_name = "sovrin_open_wallet_works";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            WalletUtils::open_wallet(wallet_name, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_open_wallet_works_for_plugged() {
            TestUtils::cleanup_storage();
            InmemWallet::cleanup();

            let pool_name = "sovrin_open_wallet_works_for_plugged";
            let wallet_name = "sovrin_open_wallet_works_for_plugged";
            let xtype = "inmem";

            WalletUtils::register_wallet_type(xtype).unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None).unwrap();
            WalletUtils::open_wallet(wallet_name, None).unwrap();

            TestUtils::cleanup_storage();
            InmemWallet::cleanup();
        }

        #[test]
        fn sovrin_open_wallet_works_for_config() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_open_wallet_works_for_config";
            let wallet_name = "sovrin_open_wallet_works_for_config";
            let config = r#"{"freshness_time":1000}"#;

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            WalletUtils::open_wallet(wallet_name, Some(config)).unwrap();

            TestUtils::cleanup_storage();
        }
    }

    mod close_wallet {
        use super::*;

        #[test]
        fn sovrin_close_wallet_works() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_close_wallet_works";
            let wallet_name = "sovrin_close_wallet_works";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();

            let wallet_handle = WalletUtils::open_wallet(wallet_name, None).unwrap();
            WalletUtils::close_wallet(wallet_handle).unwrap();
            WalletUtils::open_wallet(wallet_name, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_close_wallet_works_for_plugged() {
            TestUtils::cleanup_storage();
            InmemWallet::cleanup();

            let pool_name = "sovrin_close_wallet_works_for_plugged";
            let wallet_name = "sovrin_close_wallet_works_for_plugged";
            let xtype = "inmem";

            WalletUtils::register_wallet_type(xtype).unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name, Some(xtype), None).unwrap();

            let wallet_handle = WalletUtils::open_wallet(wallet_name, None).unwrap();
            WalletUtils::close_wallet(wallet_handle).unwrap();
            WalletUtils::open_wallet(wallet_name, None).unwrap();

            TestUtils::cleanup_storage();
            InmemWallet::cleanup();
        }
    }

    mod set_seqno_wallet {
        use super::*;

        #[test]
        fn sovrin_wallet_set_seqno_works() {
            TestUtils::cleanup_storage();

            let wallet_handle = WalletUtils::create_and_open_wallet("sovrin_wallet_set_seqno_works", None).unwrap();

            let (did, _, _) = SignusUtils::create_my_did(wallet_handle, "{}").unwrap();

            WalletUtils::wallet_set_seq_no_for_value(wallet_handle, &did, 1).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_wallet_set_seqno_works_for_plugged() {
            TestUtils::cleanup_storage();
            InmemWallet::cleanup();

            WalletUtils::register_wallet_type(xtype).unwrap();
            let wallet_handle = WalletUtils::create_and_open_wallet("sovrin_wallet_set_seqno_works_for_plugged", Some("inmem")).unwrap();

            let (did, _, _) = SignusUtils::create_my_did(wallet_handle, "{}").unwrap();

            WalletUtils::wallet_set_seq_no_for_value(wallet_handle, &did, 1).unwrap();

            TestUtils::cleanup_storage();
            InmemWallet::cleanup();
        }
    }
}

mod medium_cases {
    use super::*;

    mod create_wallet {
        use super::*;

        #[test]
        fn sovrin_create_wallet_works_for_duplicate_name() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works_for_duplicate_name";
            let wallet_name = "sovrin_create_wallet_works_for_duplicate_name";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            let res = WalletUtils::create_wallet(pool_name, wallet_name, None, None);
            assert_eq!(res.unwrap_err(), ErrorCode::WalletAlreadyExistsError);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_create_wallet_works_for_empty_name() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works_for_empty_name";
            let wallet_name = "";

            let res = WalletUtils::create_wallet(pool_name, wallet_name, None, None);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonInvalidParam3);

            TestUtils::cleanup_storage();
        }
    }

    mod delete_wallet {
        use super::*;

        #[test]
        fn sovrin_delete_wallet_works_for_invalid_wallet_name() {
            TestUtils::cleanup_storage();

            let res = WalletUtils::delete_wallet("sovrin_delete_wallet_works_for_invalid_wallet_name");
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_delete_wallet_works_for_twice() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_delete_wallet_works_for_deleted_wallet";
            let wallet_name = "sovrin_delete_wallet_works_for_deleted_wallet";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            WalletUtils::delete_wallet(wallet_name).unwrap();
            let res = WalletUtils::delete_wallet(wallet_name);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }
    }

    mod open_wallet {
        use super::*;

        #[test]
        fn sovrin_open_wallet_works_for_not_created_wallet() {
            TestUtils::cleanup_storage();

            let res = WalletUtils::open_wallet("sovrin_open_wallet_works_for_not_created_wallet", None);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }

        #[test]
        #[ignore] //TODO Check is not implemented
        fn sovrin_open_wallet_works_for_twice() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_create_wallet_works";
            let wallet_name = "sovrin_open_wallet_works_for_twice";

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();

            WalletUtils::open_wallet(wallet_name, None).unwrap();
            let res = WalletUtils::open_wallet(wallet_name, None);
            assert_eq!(res.unwrap_err(), ErrorCode::CommonIOError);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_open_wallet_works_for_two_wallets() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_open_wallet_works_for_two_wallets";
            let wallet_name_1 = "sovrin_open_wallet_works_for_two_wallets1";
            let wallet_name_2 = "sovrin_open_wallet_works_for_two_wallets2";

            WalletUtils::create_wallet(pool_name, wallet_name_1, None, None).unwrap();
            WalletUtils::create_wallet(pool_name, wallet_name_2, None, None).unwrap();
            WalletUtils::open_wallet(wallet_name_1, None).unwrap();
            WalletUtils::open_wallet(wallet_name_2, None).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_open_wallet_works_for_invalid_config() {
            TestUtils::cleanup_storage();

            let pool_name = "sovrin_open_wallet_works_for_invalid_config";
            let wallet_name = "sovrin_open_wallet_works_for_invalid_config";
            let config = r#"{"field":"value"}"#;

            WalletUtils::create_wallet(pool_name, wallet_name, None, None).unwrap();
            let res = WalletUtils::open_wallet(wallet_name, Some(config));
            assert_eq!(res.unwrap_err(), ErrorCode::CommonInvalidStructure);

            TestUtils::cleanup_storage();
        }
    }

    mod close_wallet {
        use super::*;

        #[test]
        fn sovrin_close_wallet_works_for_invalid_handle() {
            TestUtils::cleanup_storage();

            let res = WalletUtils::close_wallet(1);
            assert_eq!(res.unwrap_err(), ErrorCode::WalletInvalidHandle);

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_close_wallet_works_for_twice() {
            TestUtils::cleanup_storage();

            let wallet_handle = WalletUtils::create_and_open_wallet("sovrin_close_wallet_works_for_twice", None).unwrap();

            WalletUtils::close_wallet(wallet_handle).unwrap();
            let res = WalletUtils::close_wallet(wallet_handle);
            assert_eq!(res.unwrap_err(), ErrorCode::WalletInvalidHandle);

            TestUtils::cleanup_storage();
        }
    }

    mod set_seqno {
        use super::*;

        #[test]
        fn sovrin_wallet_set_seqno_works_for_not_exists_key() {
            TestUtils::cleanup_storage();

            let wallet_handle = WalletUtils::create_and_open_wallet("sovrin_wallet_set_seqno_works_for_not_exists_key", None).unwrap();

            //TODO may be we must return WalletNotFound in case if key not exists in wallet
            WalletUtils::wallet_set_seq_no_for_value(wallet_handle, "key", 1).unwrap();

            TestUtils::cleanup_storage();
        }

        #[test]
        fn sovrin_wallet_set_seqno_works_for_invalid_wallet() {
            TestUtils::cleanup_storage();

            let wallet_handle = WalletUtils::create_and_open_wallet("sovrin_wallet_set_seqno_works_for_invalid_wallet", None).unwrap();

            let invalid_wallet_handle = wallet_handle + 1;
            let res = WalletUtils::wallet_set_seq_no_for_value(invalid_wallet_handle, "key", 1);
            assert_eq!(res.unwrap_err(), ErrorCode::WalletInvalidHandle);

            TestUtils::cleanup_storage();
        }
    }
}
<|endoftext|>