<commit_before>
#[macro_use]
extern crate nom;

use nom::{IResult,not_line_ending, space, alphanumeric, multispace};

use std::str;
use std::collections::HashMap;

named!(category<&str>, map_res!(
    terminated!(
        delimited!(tag!("["), take_until!("]"), tag!("]")),
        opt!(multispace)
    ),
    str::from_utf8
));

named!(key_value    <&[u8],(&str,&str)>,
  chain!(
    key: map_res!(alphanumeric, std::str::from_utf8) ~
         space?                            ~
         tag!("=")                         ~
         space?                            ~
    val: map_res!(
           take_until_either!("\n;"),
           str::from_utf8
         )                                 ~
         space?                            ~
         chain!(
           tag!(";")        ~
           not_line_ending  ,
           ||{}
         ) ?                               ~
         multispace?                       ,
    ||{(key, val)}
  )
);

named!(keys_and_values_aggregator<&[u8], Vec<(&str,&str)> >, many0!(key_value));

fn keys_and_values(input:&[u8]) -> IResult<&[u8], HashMap<&str, &str> > {
  let mut h: HashMap<&str, &str> = HashMap::new();

  match keys_and_values_aggregator(input) {
    IResult::Done(i,tuple_vec) => {
      for &(k,v) in &tuple_vec {
        h.insert(k, v);
      }
      IResult::Done(i, h)
    },
    IResult::Incomplete(a)     => IResult::Incomplete(a),
    IResult::Error(a)          => IResult::Error(a)
  }
}

named!(category_and_keys<&[u8],(&str,HashMap<&str,&str>)>,
  chain!(
    category: category    ~
    keys: keys_and_values ,
    move ||{(category, keys)}
  )
);

named!(categories_aggregator<&[u8], Vec<(&str, HashMap<&str,&str>)> >, many0!(category_and_keys));

fn categories(input: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str> > > {
  let mut h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();

  match categories_aggregator(input) {
    IResult::Done(i,tuple_vec) => {
      for &(k,ref v) in &tuple_vec {
        h.insert(k, v.clone());
      }
      IResult::Done(i, h)
    },
    IResult::Incomplete(a)     => IResult::Incomplete(a),
    IResult::Error(a)          => IResult::Error(a)
  }
}

#[test]
fn parse_category_test() {
  let ini_file = &b"[category]

parameter=value
key = value2"[..];

  let ini_without_category = &b"parameter=value
key = value2"[..];

  let res = category(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_category, "category"));
}

#[test]
fn parse_key_value_test() {
  let ini_file = &b"parameter=value
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_key_value_with_space_test() {
  let ini_file = &b"parameter = value
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_key_value_with_comment_test() {
  let ini_file = &b"parameter=value;abc
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_multiple_keys_and_values_test() {
  let ini_file = &b"parameter=value;abc

key = value2

[category]"[..];

  let ini_without_key_value = &b"[category]"[..];

  let res = keys_and_values(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected: HashMap<&str, &str> = HashMap::new();
  expected.insert("parameter", "value");
  expected.insert("key", "value2");
  assert_eq!(res, IResult::Done(ini_without_key_value, expected));
}

#[test]
fn parse_category_then_multiple_keys_and_values_test() {
  //FIXME: there can be an empty line or a comment line after a category
  let ini_file = &b"[abcd]
parameter=value;abc

key = value2

[category]"[..];

  let ini_after_parser = &b"[category]"[..];

  let res = category_and_keys(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected_h: HashMap<&str, &str> = HashMap::new();
  expected_h.insert("parameter", "value");
  expected_h.insert("key", "value2");
  assert_eq!(res, IResult::Done(ini_after_parser, ("abcd", expected_h)));
}

#[test]
fn parse_multiple_categories_test() {
  let ini_file = &b"[abcd]

parameter=value;abc

key = value2

[category]
parameter3=value3
key4 = value4
"[..];

  let ini_after_parser = &b""[..];

  let res = categories(ini_file);
  //println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected_1: HashMap<&str, &str> = HashMap::new();
  expected_1.insert("parameter", "value");
  expected_1.insert("key", "value2");
  let mut expected_2: HashMap<&str, &str> = HashMap::new();
  expected_2.insert("parameter3", "value3");
  expected_2.insert("key4", "value4");
  let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
  expected_h.insert("abcd",     expected_1);
  expected_h.insert("category", expected_2);
  assert_eq!(res, IResult::Done(ini_after_parser, expected_h));
}
<commit_msg>tests/ini: don't use chain!<commit_after>
#[macro_use]
extern crate nom;

use nom::{IResult,not_line_ending, space, alphanumeric, multispace};

use std::str;
use std::collections::HashMap;

named!(category<&str>, map_res!(
    terminated!(
        delimited!(tag!("["), take_until!("]"), tag!("]")),
        opt!(multispace)
    ),
    str::from_utf8
));

named!(key_value    <&[u8],(&str,&str)>,
  do_parse!(
    key: map_res!(alphanumeric, std::str::from_utf8) >>
         opt!(space)                                 >>
         tag!("=")                                   >>
         opt!(space)                                 >>
    val: map_res!(
           take_until_either!("\n;"),
           str::from_utf8
         )                                           >>
         opt!(space)                                 >>
         opt!(do_parse!(
           tag!(";")                                 >>
           not_line_ending                           >>
           ()
         ))                                          >>
         opt!(multispace)                            >>
    (key, val)
  )
);

named!(keys_and_values_aggregator<&[u8], Vec<(&str,&str)> >, many0!(key_value));

fn keys_and_values(input:&[u8]) -> IResult<&[u8], HashMap<&str, &str> > {
  let mut h: HashMap<&str, &str> = HashMap::new();

  match keys_and_values_aggregator(input) {
    IResult::Done(i,tuple_vec) => {
      for &(k,v) in &tuple_vec {
        h.insert(k, v);
      }
      IResult::Done(i, h)
    },
    IResult::Incomplete(a)     => IResult::Incomplete(a),
    IResult::Error(a)          => IResult::Error(a)
  }
}

named!(category_and_keys<&[u8],(&str,HashMap<&str,&str>)>,
  do_parse!(
    category: category    >>
    keys: keys_and_values >>
    (category, keys)
  )
);

named!(categories_aggregator<&[u8], Vec<(&str, HashMap<&str,&str>)> >, many0!(category_and_keys));

fn categories(input: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str> > > {
  let mut h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();

  match categories_aggregator(input) {
    IResult::Done(i,tuple_vec) => {
      for &(k,ref v) in &tuple_vec {
        h.insert(k, v.clone());
      }
      IResult::Done(i, h)
    },
    IResult::Incomplete(a)     => IResult::Incomplete(a),
    IResult::Error(a)          => IResult::Error(a)
  }
}

#[test]
fn parse_category_test() {
  let ini_file = &b"[category]

parameter=value
key = value2"[..];

  let ini_without_category = &b"parameter=value
key = value2"[..];

  let res = category(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_category, "category"));
}

#[test]
fn parse_key_value_test() {
  let ini_file = &b"parameter=value
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_key_value_with_space_test() {
  let ini_file = &b"parameter = value
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_key_value_with_comment_test() {
  let ini_file = &b"parameter=value;abc
key = value2"[..];

  let ini_without_key_value = &b"key = value2"[..];

  let res = key_value(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
    _ => println!("error")
  }

  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
}

#[test]
fn parse_multiple_keys_and_values_test() {
  let ini_file = &b"parameter=value;abc

key = value2

[category]"[..];

  let ini_without_key_value = &b"[category]"[..];

  let res = keys_and_values(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected: HashMap<&str, &str> = HashMap::new();
  expected.insert("parameter", "value");
  expected.insert("key", "value2");
  assert_eq!(res, IResult::Done(ini_without_key_value, expected));
}

#[test]
fn parse_category_then_multiple_keys_and_values_test() {
  //FIXME: there can be an empty line or a comment line after a category
  let ini_file = &b"[abcd]
parameter=value;abc

key = value2

[category]"[..];

  let ini_after_parser = &b"[category]"[..];

  let res = category_and_keys(ini_file);
  println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected_h: HashMap<&str, &str> = HashMap::new();
  expected_h.insert("parameter", "value");
  expected_h.insert("key", "value2");
  assert_eq!(res, IResult::Done(ini_after_parser, ("abcd", expected_h)));
}

#[test]
fn parse_multiple_categories_test() {
  let ini_file = &b"[abcd]

parameter=value;abc

key = value2

[category]
parameter3=value3
key4 = value4
"[..];

  let ini_after_parser = &b""[..];

  let res = categories(ini_file);
  //println!("{:?}", res);
  match res {
    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
    _ => println!("error")
  }

  let mut expected_1: HashMap<&str, &str> = HashMap::new();
  expected_1.insert("parameter", "value");
  expected_1.insert("key", "value2");
  let mut expected_2: HashMap<&str, &str> = HashMap::new();
  expected_2.insert("parameter3", "value3");
  expected_2.insert("key4", "value4");
  let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
  expected_h.insert("abcd",     expected_1);
  expected_h.insert("category", expected_2);
  assert_eq!(res, IResult::Done(ini_after_parser, expected_h));
}
<|endoftext|>


<commit_before>extern crate metl;
extern crate cocoa;

use cocoa::base::{BOOL, nil};
use cocoa::foundation::NSString;
use metl::{CompileOptions, Device, LanguageVersion, SpecificLanguageVersion, FeatureSet};
use metl::LibraryErrorType;
use metl::{FromRaw, FromRawError, IntoRaw};
use metl::sys::{MTLCompileOptions, MTLLanguageVersion};

#[test]
fn get_device() {
    let device = Device::system_default_device();
    assert!(device.is_ok());
}

#[test]
fn get_all_devices() {
    let all_devices = Device::enumerate_all_system_devices();
    assert!(!all_devices.is_empty());
    for device in all_devices {
        assert!(device.is_ok());
    }
}

#[test]
fn get_device_name() {
    let device = Device::system_default_device().unwrap();
    assert!(!device.name().into_owned().is_empty());
}

#[cfg(target_os = "macos")]
#[test]
fn device_supports_base_features() {
    let base_osx_feature_set = FeatureSet::OsxGpuFamily1_v1;
    let device = Device::system_default_device().unwrap();
    assert!(device.supports_feature_set(base_osx_feature_set));
}

#[test]
fn set_get_command_queue_label() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();

    const DUMMY_COMMAND_QUEUE_NAME: &'static str = "foo";
    command_queue.set_label(&DUMMY_COMMAND_QUEUE_NAME);

    assert_eq!(command_queue.label(),
               DUMMY_COMMAND_QUEUE_NAME);
}

#[test]
fn insert_debug_capture_boundary_on_command_queue() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();
    command_queue.insert_debug_capture_boundary();

    // if nothing panics/fails here, everything is okay
}

#[test]
fn device_from_to_raw() {
    let device = Device::system_default_device().unwrap();
    let raw = device.into_raw();
    let device = Device::from_raw(raw);
    assert!(device.is_ok());
}

#[test]
fn device_from_wrong_type() {
    let some_string = unsafe { NSString::alloc(nil).init_str("Hello") };
    let device_result = Device::from_raw(some_string);
    match device_result {
        Result::Err(FromRawError::WrongPointerType) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn device_from_nullptr() {
    let device_result = Device::from_raw(nil);
    match device_result {
        Result::Err(FromRawError::NilPointer) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn compile_opts_creation_is_correct() {
    let fast_math_enabled = true;
    let options = CompileOptions::default()
                      .fast_math_enabled(fast_math_enabled)
                      .language_version(LanguageVersion::Specific(SpecificLanguageVersion::Version_1_0))
                      .with_macro("Foo", 54)
                      .with_macro("Bar", 32.0)
                      .with_macro("Baz", "Hi")
                      .mtl_compile_options();

    unsafe {
        assert_eq!(fast_math_enabled as BOOL, options.fastMathEnabled());
        assert_eq!(options.languageVersion(),
                   MTLLanguageVersion::MTLLanguageVersion1_0);
    }
}

#[test]
fn create_invalid_shader() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"abcdefghijklmnopqrstuvwxyz";
    match device.new_library_with_source(&BAD_SHADER, &Default::default()) {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(error) => {
            if let LibraryErrorType::SourceError = error.error_type {
                assert!(true);
            } else {
                panic!("Incorrect error type");
            }
        }
    }
}

#[test]
fn device_create_library_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    // Shader source taken from http://metalbyexample.com/up-and-running-2/
    const SHADER: &'static str = r"
        using namespace metal;

        struct ColoredVertex
        {
            float4 position [[position]];
            float4 color;
        };

        vertex ColoredVertex vertex_main(constant float4 *position [[buffer(0)]],
                                         constant float4 *color [[buffer(1)]],
                                         uint vid [[vertex_id]])
        {
            ColoredVertex vert;
            vert.position = position[vid];
            vert.color = color[vid];
            return vert;
        }

        fragment float4 fragment_main(ColoredVertex vert [[stage_in]])
        {
            return vert.color;
        }
    ";
    let library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}
<commit_msg>Add new test stub for testing shader struct reflection<commit_after>extern crate metl;
extern crate cocoa;

use cocoa::base::{BOOL, nil};
use cocoa::foundation::NSString;
use metl::{CompileOptions, Device, LanguageVersion, SpecificLanguageVersion, FeatureSet};
use metl::LibraryErrorType;
use metl::{FromRaw, FromRawError, IntoRaw};
use metl::sys::{MTLCompileOptions, MTLLanguageVersion};

#[test]
fn get_device() {
    let device = Device::system_default_device();
    assert!(device.is_ok());
}

#[test]
fn get_all_devices() {
    let all_devices = Device::enumerate_all_system_devices();
    assert!(!all_devices.is_empty());
    for device in all_devices {
        assert!(device.is_ok());
    }
}

#[test]
fn get_device_name() {
    let device = Device::system_default_device().unwrap();
    assert!(!device.name().into_owned().is_empty());
}

#[cfg(target_os = "macos")]
#[test]
fn device_supports_base_features() {
    let base_osx_feature_set = FeatureSet::OsxGpuFamily1_v1;
    let device = Device::system_default_device().unwrap();
    assert!(device.supports_feature_set(base_osx_feature_set));
}

#[test]
fn set_get_command_queue_label() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();

    const DUMMY_COMMAND_QUEUE_NAME: &'static str = "foo";
    command_queue.set_label(&DUMMY_COMMAND_QUEUE_NAME);

    assert_eq!(command_queue.label(),
               DUMMY_COMMAND_QUEUE_NAME);
}

#[test]
fn insert_debug_capture_boundary_on_command_queue() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();
    command_queue.insert_debug_capture_boundary();

    // if nothing panics/fails here, everything is okay
}

#[test]
fn device_from_to_raw() {
    let device = Device::system_default_device().unwrap();
    let raw = device.into_raw();
    let device = Device::from_raw(raw);
    assert!(device.is_ok());
}

#[test]
fn device_from_wrong_type() {
    let some_string = unsafe { NSString::alloc(nil).init_str("Hello") };
    let device_result = Device::from_raw(some_string);
    match device_result {
        Result::Err(FromRawError::WrongPointerType) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn device_from_nullptr() {
    let device_result = Device::from_raw(nil);
    match device_result {
        Result::Err(FromRawError::NilPointer) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn compile_opts_creation_is_correct() {
    let fast_math_enabled = true;
    let options = CompileOptions::default()
                      .fast_math_enabled(fast_math_enabled)
                      .language_version(LanguageVersion::Specific(SpecificLanguageVersion::Version_1_0))
                      .with_macro("Foo", 54)
                      .with_macro("Bar", 32.0)
                      .with_macro("Baz", "Hi")
                      .mtl_compile_options();

    unsafe {
        assert_eq!(fast_math_enabled as BOOL, options.fastMathEnabled());
        assert_eq!(options.languageVersion(),
                   MTLLanguageVersion::MTLLanguageVersion1_0);
    }
}

#[test]
fn create_invalid_shader() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"abcdefghijklmnopqrstuvwxyz";
    match device.new_library_with_source(&BAD_SHADER, &Default::default()) {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(error) => {
            if let LibraryErrorType::SourceError = error.error_type {
                assert!(true);
            } else {
                panic!("Incorrect error type");
            }
        }
    }
}

#[test]
fn device_create_library_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    // Shader source taken from http://metalbyexample.com/up-and-running-2/
    const SHADER: &'static str = r"
        using namespace metal;

        struct ColoredVertex
        {
            float4 position [[position]];
            float4 color;
        };

        vertex ColoredVertex vertex_main(constant float4 *position [[buffer(0)]],
                                         constant float4 *color [[buffer(1)]],
                                         uint vid [[vertex_id]])
        {
            ColoredVertex vert;
            vert.position = position[vid];
            vert.color = color[vid];
            return vert;
        }

        fragment float4 fragment_main(ColoredVertex vert [[stage_in]])
        {
            return vert.color;
        }
    ";
    let library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}

#[test]
#[ignore]
fn shader_get_struct_info() {
    use metl::{StructType, StructMember};
    let mut device = Device::system_default_device().unwrap();
    const SHADER: &'static str = r"
        using namespace metal;

        struct OtherStruct {
            float4 color;
        };

        struct SomeStruct {
            int some_field;
            bool another_field;
            OtherStruct nested;
        };

        void function(SomeStruct struct) { }
    ";

    unimplemented!();
}
<|endoftext|>


<commit_before>extern crate data_encoding;

macro_rules! test {
    (fn $b: ident; $($s: stmt);*;) => {
        #[test]
        fn $b() {
            use data_encoding::$b::*;
            #[allow(unused_imports)]
            use data_encoding::decode::Error::*;
            fn test(x: &[u8], y: &[u8]) {
                assert_eq!(&encode(x).into_bytes() as &[u8], y);
                assert_eq!(&decode(y).unwrap() as &[u8], x);
            }
            $($s);*
        }
    };
}

test!{
    fn base2;
    test(b"", b"");
    test(b"f", b"01100110");
    test(b"fo", b"0110011001101111");
    test(b"foo", b"011001100110111101101111");
}

test!{
    fn base4;
    test(b"", b"");
    test(b"f", b"1212");
    test(b"fo", b"12121233");
    test(b"foo", b"121212331233");
    test(b"foob", b"1212123312331202");
    test(b"fooba", b"12121233123312021201");
    test(b"foobar", b"121212331233120212011302");
}

test!{
    fn base8;
    test(b"", b"");
    test(b"f", b"314=====");
    test(b"fo", b"314674==");
    test(b"foo", b"31467557");
    test(b"foob", b"31467557304=====");
    test(b"fooba", b"31467557304604==");
    test(b"foobar", b"3146755730460562");
}

test!{
    fn base16;
    test(b"", b"");
    test(b"f", b"66");
    test(b"fo", b"666F");
    test(b"foo", b"666F6F");
    test(b"foob", b"666F6F62");
    test(b"fooba", b"666F6F6261");
    test(b"foobar", b"666F6F626172");
}

test!{
    fn base32;
    test(b"", b"");
    test(b"f", b"MY======");
    test(b"fo", b"MZXQ====");
    test(b"foo", b"MZXW6===");
    test(b"foob", b"MZXW6YQ=");
    test(b"fooba", b"MZXW6YTB");
    test(b"foobar", b"MZXW6YTBOI======");
    assert_eq!(decode(b"ABC"), Err(BadLength));
    assert_eq!(decode(b"MB======"), Err(BadPadding));
    assert_eq!(decode(b"MA===AAA"), Err(BadCharacter(5)));
    assert_eq!(decode(b"MAA====="), Err(BadCharacter(3)));
    assert_eq!(decode(b"MAABBB=="), Err(BadCharacter(6)));
}

test!{
    fn base32hex;
    test(b"", b"");
    test(b"f", b"CO======");
    test(b"fo", b"CPNG====");
    test(b"foo", b"CPNMU===");
    test(b"foob", b"CPNMUOG=");
    test(b"fooba", b"CPNMUOJ1");
    test(b"foobar", b"CPNMUOJ1E8======");
}

test!{
    fn base64;
    test(b"", b"");
    test(b"f", b"Zg==");
    test(b"fo", b"Zm8=");
    test(b"foo", b"Zm9v");
    test(b"foob", b"Zm9vYg==");
    test(b"fooba", b"Zm9vYmE=");
    test(b"foobar", b"Zm9vYmFy");
}

#[test]
fn exhaustive() {
    use data_encoding::base64::{encode_mut, decode_mut};
    let mut t = 0u32;
    // TODO: Also test on [0u8; 4] ++ [b'A'; 4] to not only test
    // block_last but also block. It will give more code coverage.
    let mut x = [0u8; 4];
    let mut y = [0u8; 3];
    let mut z = [0u8; 4];
    'iter: loop {
        if let Ok(n) = decode_mut(&x, &mut y) {
            t += 1;
            encode_mut(&y[0..n], &mut z);
            assert_eq!(x, z);
        }
        let mut i = 0;
        // We are only interested in all ascii and one non-ascii.
        while x[i] == 128 {
            x[i] = 0;
            i += 1;
            if i == 4 { break 'iter; }
        }
        x[i] += 1;
    }
    assert_eq!(t, 0x1010100u32);
}
<commit_msg>tests/lib.rs: Remove todo<commit_after>extern crate data_encoding;

macro_rules! test {
    (fn $b: ident; $($s: stmt);*;) => {
        #[test]
        fn $b() {
            use data_encoding::$b::*;
            #[allow(unused_imports)]
            use data_encoding::decode::Error::*;
            fn test(x: &[u8], y: &[u8]) {
                assert_eq!(&encode(x).into_bytes() as &[u8], y);
                assert_eq!(&decode(y).unwrap() as &[u8], x);
            }
            $($s);*
        }
    };
}

test!{
    fn base2;
    test(b"", b"");
    test(b"f", b"01100110");
    test(b"fo", b"0110011001101111");
    test(b"foo", b"011001100110111101101111");
}

test!{
    fn base4;
    test(b"", b"");
    test(b"f", b"1212");
    test(b"fo", b"12121233");
    test(b"foo", b"121212331233");
    test(b"foob", b"1212123312331202");
    test(b"fooba", b"12121233123312021201");
    test(b"foobar", b"121212331233120212011302");
}

test!{
    fn base8;
    test(b"", b"");
    test(b"f", b"314=====");
    test(b"fo", b"314674==");
    test(b"foo", b"31467557");
    test(b"foob", b"31467557304=====");
    test(b"fooba", b"31467557304604==");
    test(b"foobar", b"3146755730460562");
}

test!{
    fn base16;
    test(b"", b"");
    test(b"f", b"66");
    test(b"fo", b"666F");
    test(b"foo", b"666F6F");
    test(b"foob", b"666F6F62");
    test(b"fooba", b"666F6F6261");
    test(b"foobar", b"666F6F626172");
}

test!{
    fn base32;
    test(b"", b"");
    test(b"f", b"MY======");
    test(b"fo", b"MZXQ====");
    test(b"foo", b"MZXW6===");
    test(b"foob", b"MZXW6YQ=");
    test(b"fooba", b"MZXW6YTB");
    test(b"foobar", b"MZXW6YTBOI======");
    assert_eq!(decode(b"ABC"), Err(BadLength));
    assert_eq!(decode(b"MB======"), Err(BadPadding));
    assert_eq!(decode(b"MA===AAA"), Err(BadCharacter(5)));
    assert_eq!(decode(b"MAA====="), Err(BadCharacter(3)));
    assert_eq!(decode(b"MAABBB=="), Err(BadCharacter(6)));
}

test!{
    fn base32hex;
    test(b"", b"");
    test(b"f", b"CO======");
    test(b"fo", b"CPNG====");
    test(b"foo", b"CPNMU===");
    test(b"foob", b"CPNMUOG=");
    test(b"fooba", b"CPNMUOJ1");
    test(b"foobar", b"CPNMUOJ1E8======");
}

test!{
    fn base64;
    test(b"", b"");
    test(b"f", b"Zg==");
    test(b"fo", b"Zm8=");
    test(b"foo", b"Zm9v");
    test(b"foob", b"Zm9vYg==");
    test(b"fooba", b"Zm9vYmE=");
    test(b"foobar", b"Zm9vYmFy");
}

#[test]
fn exhaustive() {
    use data_encoding::base64::{encode_mut, decode_mut};
    let mut t = 0u32;
    let mut x = [0u8; 4];
    let mut y = [0u8; 3];
    let mut z = [0u8; 4];
    'iter: loop {
        if let Ok(n) = decode_mut(&x, &mut y) {
            t += 1;
            encode_mut(&y[0..n], &mut z);
            assert_eq!(x, z);
        }
        let mut i = 0;
        // We are only interested in all ascii and one non-ascii.
        while x[i] == 128 {
            x[i] = 0;
            i += 1;
            if i == 4 { break 'iter; }
        }
        x[i] += 1;
    }
    assert_eq!(t, 0x1010100_u32);
}
<|endoftext|>


<commit_before>extern crate random_choice;

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;
    use random_choice::RandomChoice;

    #[test]
    fn test_random_choice_f64() {
        let capacity: usize = 500;
        let mut samples: Vec<usize> = Vec::with_capacity(capacity);
        let mut weights: Vec<f64> = Vec::with_capacity(capacity);

        for i in 0..capacity {
            samples.push(i);
            weights.push(i as f64);
        }

        let number_choices = 10000;
        let choices = RandomChoice::random_choice_f64(&samples, &weights, number_choices);

        assert!(choices.len() == number_choices);

        let mut weight_counter = BTreeMap::new();

        for choice in choices {
            let counter = weight_counter.entry(choice).or_insert(0);
            *counter += 1;
        }

        let mut last_value: usize = 0;

        for (_, value) in &weight_counter {
            assert!((last_value as i32 - (*value) as i32).abs() <= 2);
            last_value = *value;
            //println!("({}, {})", key, value);
        }
    }

    #[test]
    fn test_random_choice_f32() {
        let capacity: usize = 1000;
        let mut samples: Vec<usize> = Vec::with_capacity(capacity);
        let mut weights: Vec<f32> = Vec::with_capacity(capacity);

        for i in 0..capacity {
            samples.push(i);
            weights.push(i as f32);
        }

        let number_choices = 10000;
        let choices = RandomChoice::random_choice_f32(&samples, &weights, number_choices);

        assert!(choices.len() == number_choices);

        let mut weight_counter = BTreeMap::new();

        for choice in choices {
            let counter = weight_counter.entry(choice).or_insert(0);
            *counter += 1;
        }

        let mut last_value: usize = 0;

        for (_, value) in &weight_counter {
            assert!((last_value as i32 - (*value) as i32).abs() <= 2);
            last_value = *value;
            //println!("({}, {})", key, value);
        }
    }

    #[test]
    fn test_random_choice_zero_elements_f64() {
        let capacity: usize = 1000;
        let mut samples: Vec<usize> = Vec::with_capacity(capacity);
        let mut weights: Vec<f64> = Vec::with_capacity(capacity);

        for i in 0..capacity {
            samples.push(i + 1);
            weights.push((i + 1usize) as f64);
        }

        let choices = RandomChoice::random_choice_f64(&samples, &weights, 0 as usize);

        assert!(choices.len() == 0);
    }

    #[test]
    fn test_random_choice_in_place_f64() {
        let mut samples = vec!["hi", "this", "is", "a", "test!"];
        let weights: Vec<f64> = vec![1.0, 1.0, 1.0, 1.0, 1.0];

        RandomChoice::random_choice_in_place_f64(&mut samples, &weights);

        for sample in samples {
            print!("{}, ", sample);
        }
    }

}<commit_msg>test modified in order to provoke Index Out of Bounds<commit_after>extern crate random_choice;

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;
    use random_choice::RandomChoice;

    #[test]
    fn test_random_choice_f64() {
        let capacity: usize = 500;
        let mut samples: Vec<usize> = Vec::with_capacity(capacity);
        let mut weights: Vec<f64> = Vec::with_capacity(capacity);

        for i in 0..capacity {
            samples.push(i);
            weights.push(i as f64);
        }

        let number_choices = 10000;
        let choices = RandomChoice::random_choice_f64(&samples, &weights, number_choices);

        assert!(choices.len() == number_choices);

        let mut weight_counter = BTreeMap::new();

        for choice in choices {
            let counter = weight_counter.entry(choice).or_insert(0);
            *counter += 1;
        }

        let mut last_value: usize = 0;

        for (_, value) in &weight_counter {
            assert!((last_value as i32 - (*value) as i32).abs() <= 2);
            last_value = *value;
            //println!("({}, {})", key, value);
        }
    }

    #[test]
    fn test_random_choice_f32() {
        let capacity: usize = 500;
        let mut samples: Vec<usize> = Vec::with_capacity(capacity);
        let mut weights: Vec<f32> = Vec::with_capacity(capacity);

        for i in 0..capacity {
            samples.push(i);
            weights.push(i as f32);
        }

        let number_choices = 10000;
        let choices = RandomChoice::random_choice_f32(&samples, &weights, number_choices);

        assert!(choices.len() == number_choices);

        let mut weight_counter = BTreeMap::new();

        for choice in choices {
            let counter = weight_counter.entry(choice).or_insert(0);
            *counter += 1;
        }

        let mut last_value: usize = 0;

        for (_, value) in &weight_counter {
            assert!((last_value as i32 - (*value) as i32).abs() <= 2);
            last_value = *value;
            //println!("({}, {})", key, value);
        }
    }

    #[test]
    fn test_random_choice_zero_elements_f64() {
        let capacity: usize = 1000;
        let mut samples: Vec<usize> = Vec::with_capacity(capacity);
        let mut weights: Vec<f64> = Vec::with_capacity(capacity);

        for i in 0..capacity {
            samples.push(i + 1);
            weights.push((i + 1usize) as f64);
        }

        let choices = RandomChoice::random_choice_f64(&samples, &weights, 0 as usize);

        assert!(choices.len() == 0);
    }

    #[test]
    fn test_random_choice_in_place_f64() {
        let mut samples = vec!["hi", "this", "is", "a", "test!"];
        let weights: Vec<f64> = vec![1.0, 1.0, 1.0, 1.0, 1.0];

        RandomChoice::random_choice_in_place_f64(&mut samples, &weights);

        for sample in samples {
            print!("{}, ", sample);
        }
    }

}<|endoftext|>


<commit_before>use multihash::{encode, Hash, MultihashRef};

/// Helper function to convert a hex-encoded byte array back into a bytearray
fn hex_to_bytes(s: &str) -> Vec<u8> {
    let mut c = 0;
    let mut v = Vec::new();
    while c < s.len() {
        v.push(u8::from_str_radix(&s[c..c + 2], 16).unwrap());
        c += 2;
    }
    v
}

macro_rules! assert_encode {
    {$( $alg:ident, $data:expr, $expect:expr; )*} => {
        $(
            assert_eq!(
                encode(Hash::$alg, $data).expect("Must be supported").into_bytes(),
                hex_to_bytes($expect),
                "{:?} encodes correctly", Hash::$alg
            );
        )*
    }
}

#[test]
fn multihash_encode() {
    assert_encode! {
        SHA1, b"beep boop", "11147c8357577f51d4f0a8d393aa1aaafb28863d9421";
        SHA2256, b"helloworld", "1220936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af";
        SHA2256, b"beep boop", "122090ea688e275d580567325032492b597bc77221c62493e76330b85ddda191ef7c";
        SHA2512, b"hello world", "1340309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f";
        SHA3224, b"hello world", "171Cdfb7f18c77e928bb56faeb2da27291bd790bc1045cde45f3210bb6c5";
        SHA3256, b"hello world", "1620644bcc7e564373040999aac89e7622f3ca71fba1d972fd94a31c3bfbf24e3938";
        SHA3384, b"hello world", "153083bff28dde1b1bf5810071c6643c08e5b05bdb836effd70b403ea8ea0a634dc4997eb1053aa3593f590f9c63630dd90b";
        SHA3512, b"hello world", "1440840006653e9ac9e95117a15c915caab81662918e925de9e004f774ff82d7079a40d4d27b1b372657c61d46d470304c88c788b3a4527ad074d1dccbee5dbaa99a";
        Keccak224, b"hello world", "1A1C25f3ecfebabe99686282f57f5c9e1f18244cfee2813d33f955aae568";
        Keccak256, b"hello world", "1B2047173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad";
        Keccak384, b"hello world", "1C3065fc99339a2a40e99d3c40d695b22f278853ca0f925cde4254bcae5e22ece47e6441f91b6568425adc9d95b0072eb49f";
        Keccak512, b"hello world", "1D403ee2b40047b8060f68c67242175660f4174d0af5c01d47168ec20ed619b0b7c42181f40aa1046f39e2ef9efc6910782a998e0013d172458957957fac9405b67d";
    }
}

macro_rules! assert_decode {
    {$( $alg:ident, $hash:expr; )*} => {
        $(
            let hash = hex_to_bytes($hash);
            assert_eq!(
                MultihashRef::from_slice(&hash).unwrap().algorithm(),
                Hash::$alg,
                "{:?} decodes correctly", Hash::$alg
            );
        )*
    }
}

#[test]
fn assert_decode() {
    assert_decode! {
        SHA1, "11147c8357577f51d4f0a8d393aa1aaafb28863d9421";
        SHA2256, "1220936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af";
        SHA2256, "122090ea688e275d580567325032492b597bc77221c62493e76330b85ddda191ef7c";
        SHA2512, "1340309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f";
        SHA3224, "171Cdfb7f18c77e928bb56faeb2da27291bd790bc1045cde45f3210bb6c5";
        SHA3256, "1620644bcc7e564373040999aac89e7622f3ca71fba1d972fd94a31c3bfbf24e3938";
        SHA3384, "153083bff28dde1b1bf5810071c6643c08e5b05bdb836effd70b403ea8ea0a634dc4997eb1053aa3593f590f9c63630dd90b";
        SHA3512, "1440840006653e9ac9e95117a15c915caab81662918e925de9e004f774ff82d7079a40d4d27b1b372657c61d46d470304c88c788b3a4527ad074d1dccbee5dbaa99a";
        Keccak224, "1A1C25f3ecfebabe99686282f57f5c9e1f18244cfee2813d33f955aae568";
        Keccak256, "1B2047173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad";
        Keccak384, "1C3065fc99339a2a40e99d3c40d695b22f278853ca0f925cde4254bcae5e22ece47e6441f91b6568425adc9d95b0072eb49f";
        Keccak512, "1D403ee2b40047b8060f68c67242175660f4174d0af5c01d47168ec20ed619b0b7c42181f40aa1046f39e2ef9efc6910782a998e0013d172458957957fac9405b67d";
    }
}

macro_rules! assert_roundtrip {
    ($( $alg:ident ),*) => {
        $(
            {
                let hash: Vec<u8> = encode(Hash::$alg, b"helloworld").unwrap().into_bytes();
                assert_eq!(
                    MultihashRef::from_slice(&hash).unwrap().algorithm(),
                    Hash::$alg
                );
            }
        )*
    }
}

#[test]
fn assert_roundtrip() {
    assert_roundtrip!(
        SHA1, SHA2256, SHA2512, SHA3224, SHA3256, SHA3384, SHA3512, Keccak224, Keccak256,
        Keccak384, Keccak512
    );
}

#[test]
fn hash_types() {
    assert_eq!(Hash::SHA2256.size(), 32);
}
<commit_msg>test: add test for the public interface of `Multihash`/`MultihashRef`<commit_after>use multihash::{encode, Hash, Multihash, MultihashRef};

/// Helper function to convert a hex-encoded byte array back into a bytearray
fn hex_to_bytes(s: &str) -> Vec<u8> {
    let mut c = 0;
    let mut v = Vec::new();
    while c < s.len() {
        v.push(u8::from_str_radix(&s[c..c + 2], 16).unwrap());
        c += 2;
    }
    v
}

macro_rules! assert_encode {
    {$( $alg:ident, $data:expr, $expect:expr; )*} => {
        $(
            assert_eq!(
                encode(Hash::$alg, $data).expect("Must be supported").into_bytes(),
                hex_to_bytes($expect),
                "{:?} encodes correctly", Hash::$alg
            );
        )*
    }
}

#[test]
fn multihash_encode() {
    assert_encode! {
        SHA1, b"beep boop", "11147c8357577f51d4f0a8d393aa1aaafb28863d9421";
        SHA2256, b"helloworld", "1220936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af";
        SHA2256, b"beep boop", "122090ea688e275d580567325032492b597bc77221c62493e76330b85ddda191ef7c";
        SHA2512, b"hello world", "1340309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f";
        SHA3224, b"hello world", "171Cdfb7f18c77e928bb56faeb2da27291bd790bc1045cde45f3210bb6c5";
        SHA3256, b"hello world", "1620644bcc7e564373040999aac89e7622f3ca71fba1d972fd94a31c3bfbf24e3938";
        SHA3384, b"hello world", "153083bff28dde1b1bf5810071c6643c08e5b05bdb836effd70b403ea8ea0a634dc4997eb1053aa3593f590f9c63630dd90b";
        SHA3512, b"hello world", "1440840006653e9ac9e95117a15c915caab81662918e925de9e004f774ff82d7079a40d4d27b1b372657c61d46d470304c88c788b3a4527ad074d1dccbee5dbaa99a";
        Keccak224, b"hello world", "1A1C25f3ecfebabe99686282f57f5c9e1f18244cfee2813d33f955aae568";
        Keccak256, b"hello world", "1B2047173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad";
        Keccak384, b"hello world", "1C3065fc99339a2a40e99d3c40d695b22f278853ca0f925cde4254bcae5e22ece47e6441f91b6568425adc9d95b0072eb49f";
        Keccak512, b"hello world", "1D403ee2b40047b8060f68c67242175660f4174d0af5c01d47168ec20ed619b0b7c42181f40aa1046f39e2ef9efc6910782a998e0013d172458957957fac9405b67d";
    }
}

macro_rules! assert_decode {
    {$( $alg:ident, $hash:expr; )*} => {
        $(
            let hash = hex_to_bytes($hash);
            assert_eq!(
                MultihashRef::from_slice(&hash).unwrap().algorithm(),
                Hash::$alg,
                "{:?} decodes correctly", Hash::$alg
            );
        )*
    }
}

#[test]
fn assert_decode() {
    assert_decode! {
        SHA1, "11147c8357577f51d4f0a8d393aa1aaafb28863d9421";
        SHA2256, "1220936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af";
        SHA2256, "122090ea688e275d580567325032492b597bc77221c62493e76330b85ddda191ef7c";
        SHA2512, "1340309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f";
        SHA3224, "171Cdfb7f18c77e928bb56faeb2da27291bd790bc1045cde45f3210bb6c5";
        SHA3256, "1620644bcc7e564373040999aac89e7622f3ca71fba1d972fd94a31c3bfbf24e3938";
        SHA3384, "153083bff28dde1b1bf5810071c6643c08e5b05bdb836effd70b403ea8ea0a634dc4997eb1053aa3593f590f9c63630dd90b";
        SHA3512, "1440840006653e9ac9e95117a15c915caab81662918e925de9e004f774ff82d7079a40d4d27b1b372657c61d46d470304c88c788b3a4527ad074d1dccbee5dbaa99a";
        Keccak224, "1A1C25f3ecfebabe99686282f57f5c9e1f18244cfee2813d33f955aae568";
        Keccak256, "1B2047173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad";
        Keccak384, "1C3065fc99339a2a40e99d3c40d695b22f278853ca0f925cde4254bcae5e22ece47e6441f91b6568425adc9d95b0072eb49f";
        Keccak512, "1D403ee2b40047b8060f68c67242175660f4174d0af5c01d47168ec20ed619b0b7c42181f40aa1046f39e2ef9efc6910782a998e0013d172458957957fac9405b67d";
    }
}

macro_rules! assert_roundtrip {
    ($( $alg:ident ),*) => {
        $(
            {
                let hash: Vec<u8> = encode(Hash::$alg, b"helloworld").unwrap().into_bytes();
                assert_eq!(
                    MultihashRef::from_slice(&hash).unwrap().algorithm(),
                    Hash::$alg
                );
            }
        )*
    }
}

#[test]
fn assert_roundtrip() {
    assert_roundtrip!(
        SHA1, SHA2256, SHA2512, SHA3224, SHA3256, SHA3384, SHA3512, Keccak224, Keccak256,
        Keccak384, Keccak512
    );
}

#[test]
fn hash_types() {
    assert_eq!(Hash::SHA2256.size(), 32);
}

/// Testing the public interface of `Multihash` and `MultihashRef`
fn test_methods(hash: Hash, prefix: &str, digest: &str) {
    let expected_bytes = hex_to_bytes(&format!("{}{}", prefix, digest));
    let multihash = encode(hash, b"hello world").unwrap();
    assert_eq!(
        Multihash::from_bytes(expected_bytes.clone()).unwrap(),
        multihash
    );
    assert_eq!(multihash.as_bytes(), &expected_bytes[..]);
    assert_eq!(multihash.algorithm(), hash);
    assert_eq!(multihash.digest(), &hex_to_bytes(digest)[..]);

    let multihash_ref = multihash.as_ref();
    assert_eq!(multihash, multihash_ref);
    assert_eq!(multihash_ref, multihash);
    assert_eq!(
        MultihashRef::from_slice(&expected_bytes[..]).unwrap(),
        multihash_ref
    );
    assert_eq!(multihash_ref.algorithm(), multihash.algorithm());
    assert_eq!(multihash_ref.digest(), multihash.digest());
    assert_eq!(multihash_ref.as_bytes(), multihash.as_bytes());

    let multihash_clone = multihash_ref.to_owned();
    assert_eq!(multihash, multihash_clone);
    assert_eq!(multihash.into_bytes(), &expected_bytes[..]);
}

#[test]
fn multihash_methods() {
    test_methods(
        Hash::SHA1,
        "1114",
        "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed",
    );
    test_methods(
        Hash::SHA2256,
        "1220",
        "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
    );
    test_methods(
        Hash::SHA2512,
        "1340",
        "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f");
    test_methods(
        Hash::SHA3224,
        "171C",
        "dfb7f18c77e928bb56faeb2da27291bd790bc1045cde45f3210bb6c5",
    );
    test_methods(
        Hash::SHA3256,
        "1620",
        "644bcc7e564373040999aac89e7622f3ca71fba1d972fd94a31c3bfbf24e3938",
    );
    test_methods(
        Hash::SHA3384,
        "1530",
        "83bff28dde1b1bf5810071c6643c08e5b05bdb836effd70b403ea8ea0a634dc4997eb1053aa3593f590f9c63630dd90b");
    test_methods(
        Hash::SHA3512,
        "1440",
        "840006653e9ac9e95117a15c915caab81662918e925de9e004f774ff82d7079a40d4d27b1b372657c61d46d470304c88c788b3a4527ad074d1dccbee5dbaa99a");
    test_methods(
        Hash::Keccak224,
        "1A1C",
        "25f3ecfebabe99686282f57f5c9e1f18244cfee2813d33f955aae568",
    );
    test_methods(
        Hash::Keccak256,
        "1B20",
        "47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad",
    );
    test_methods(
        Hash::Keccak384,
        "1C30",
        "65fc99339a2a40e99d3c40d695b22f278853ca0f925cde4254bcae5e22ece47e6441f91b6568425adc9d95b0072eb49f");
    test_methods(
        Hash::Keccak512,
        "1D40",
        "3ee2b40047b8060f68c67242175660f4174d0af5c01d47168ec20ed619b0b7c42181f40aa1046f39e2ef9efc6910782a998e0013d172458957957fac9405b67d");
}

#[test]
fn multihash_errors() {
    assert!(
        Multihash::from_bytes(Vec::new()).is_err(),
        "Should error on empty data"
    );
    assert!(
        Multihash::from_bytes(vec![1, 2, 3]).is_err(),
        "Should error on invalid multihash"
    );
    assert!(
        Multihash::from_bytes(vec![1, 2, 3]).is_err(),
        "Should error on invalid prefix"
    );
    assert!(
        Multihash::from_bytes(vec![0x12, 0x20, 0xff]).is_err(),
        "Should error on correct prefix with wrong digest"
    );
}

#[test]
fn multihash_ref_errors() {
    assert!(
        MultihashRef::from_slice(&[]).is_err(),
        "Should error on empty data"
    );
    assert!(
        MultihashRef::from_slice(&[1, 2, 3]).is_err(),
        "Should error on invalid multihash"
    );
    assert!(
        MultihashRef::from_slice(&[0x12, 0xff, 0x03]).is_err(),
        "Should error on invalid prefix"
    );
    assert!(
        MultihashRef::from_slice(&[0x12, 0x20, 0xff]).is_err(),
        "Should error on correct prefix with wrong digest"
    );
}
<|endoftext|>


<commit_before>// STD Dependencies -----------------------------------------------------------
use std::fmt;

// Macros ---------------------------------------------------------------------
#[macro_export]
macro_rules! require_unique_server {
    () => (
        fn require_unique_server(&self) -> bool {
            true
        }
    );
}

#[macro_export]
macro_rules! require_server_admin {
    () => (
        fn require_server_admin(&self) -> bool {
            true
        }
    );
}

#[macro_export]
macro_rules! require_min_arguments {
    ($count:expr) => (
        fn require_min_arguments(&self) -> usize {
            $count
        }
    );
}

#[macro_export]
macro_rules! require_exact_arguments {
    ($count:expr) => (
        fn require_exact_arguments(&self) -> Option<usize> {
            Some($count)
        }
    );
}

#[macro_export]
macro_rules! delete_command_message {
    () => (
        fn delete_command_message(&self) -> bool {
            true
        }
    );
}

// Modules --------------------------------------------------------------------
mod alias;
mod aliases;
mod ban;
mod bans;
mod delete;
mod greeting;
mod greetings;
mod help;
mod ip;
mod leave;
mod not_found;
mod pin;
mod play;
mod reload;
mod rename;
mod sounds;
mod silence;

// Internal Dependencies ------------------------------------------------------
use ::bot::BotConfig;
use ::core::{Member, Message, Server};
use ::action::{ActionGroup, MessageActions};

// Command Abstraction --------------------------------------------------------
pub struct Command<'a> {
    pub name: String,
    pub arguments: Vec<String>,
    pub message: Message,
    pub server: &'a Server,
    pub member: &'a Member,
    pub config: &'a BotConfig
}

// Public Interface -----------------------------------------------------------
impl<'a> Command<'a> {

    pub fn from_parts(
        name: String,
        arguments: Vec<String>,
        message: Message,
        server: &'a Server,
        member: &'a Member,
        config: &'a BotConfig

    ) -> Command<'a> {
        Command {
            name: name,
            arguments: arguments,
            message: message,
            server: server,
            member: member,
            config: config
        }
    }

    fn run<T: CommandHandler>(self, handler: T) -> ActionGroup {

        let argc = self.arguments.len();
        let mut actions: ActionGroup = vec![];

        if handler.delete_command_message() {
            actions.push(MessageActions::Delete::new(self.message));
        }

        if handler.require_unique_server() && !self.message.has_unique_server() {
            actions.push(MessageActions::Send::single_private(
                &self.message,
                format!(
                    "The command `{}` requires a unique server as its target.
                    Since you are a member of at least two bot-enabled servers,
                    the command cannot be invoked from a private channel.
                    Please re-issue the command from a public channels of the target server.",
                    self.name
                )
            ));

        } else if handler.require_server_admin() && !self.member.is_admin {
            actions.push(MessageActions::Send::single_private(
                &self.message,
                format!(
                    "The command `{}` requires bot admin rights on the current server.",
                    self.name
                )
            ));

        } else if argc < handler.require_min_arguments() {
            actions.append(&mut handler.usage(self));

        } else if argc != handler.require_exact_arguments().unwrap_or(argc) {
            actions.append(&mut handler.usage(self));

        } else {
            actions.append(&mut handler.run(self));
        }

        actions

    }

    pub fn process(self) -> ActionGroup {

        if self.member.is_banned {
            return vec![];

        } else {
            match self.name.as_str() {
                "s" => self.run(play::Handler::instant()),
                "q" => self.run(play::Handler::queued()),
                "delete" => self.run(delete::Handler),
                "rename" => self.run(rename::Handler),
                "sounds" => self.run(sounds::Handler),
                "silence" => self.run(silence::Handler),
                "alias" => self.run(alias::Handler),
                "aliases" => self.run(aliases::Handler),
                "greeting" => self.run(greeting::Handler),
                "greetings" => self.run(greetings::Handler),
                "ban" => self.run(ban::Handler),
                "bans" => self.run(bans::Handler),
                "pin" => self.run(pin::Handler),
                "ip" => self.run(ip::Handler),
                "leave" => self.run(leave::Handler),
                "reload" => self.run(reload::Handler),
                "help" => self.run(help::Handler),
                _ => self.run(not_found::Handler)
            }
        }

    }

}

// Traits  --------------------------------------------------------------------
impl<'a> fmt::Display for Command<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f, "[Command \"{}\" with arguments <{}> from user #{} on #{}]",
            self.name,
            self.arguments.join(", "),
            self.message.user_id,
            self.message.server_id
        )
    }
}

// Command Implementation Trait -----------------------------------------------
pub trait CommandHandler {

    fn run(&self, _: Command) -> ActionGroup;

    fn usage(&self, _: Command) -> ActionGroup {
        vec![]
    }

    fn require_unique_server(&self) -> bool {
        false
    }

    fn require_server_admin(&self) -> bool {
        false
    }

    fn require_min_arguments(&self) -> usize {
        0
    }

    fn require_exact_arguments(&self) -> Option<usize> {
        None
    }

    fn delete_command_message(&self) -> bool {
        false
    }

}

<commit_msg>Fix clippy lint.<commit_after>// STD Dependencies -----------------------------------------------------------
use std::fmt;

// Macros ---------------------------------------------------------------------
#[macro_export]
macro_rules! require_unique_server {
    () => (
        fn require_unique_server(&self) -> bool {
            true
        }
    );
}

#[macro_export]
macro_rules! require_server_admin {
    () => (
        fn require_server_admin(&self) -> bool {
            true
        }
    );
}

#[macro_export]
macro_rules! require_min_arguments {
    ($count:expr) => (
        fn require_min_arguments(&self) -> usize {
            $count
        }
    );
}

#[macro_export]
macro_rules! require_exact_arguments {
    ($count:expr) => (
        fn require_exact_arguments(&self) -> Option<usize> {
            Some($count)
        }
    );
}

#[macro_export]
macro_rules! delete_command_message {
    () => (
        fn delete_command_message(&self) -> bool {
            true
        }
    );
}

// Modules --------------------------------------------------------------------
mod alias;
mod aliases;
mod ban;
mod bans;
mod delete;
mod greeting;
mod greetings;
mod help;
mod ip;
mod leave;
mod not_found;
mod pin;
mod play;
mod reload;
mod rename;
mod sounds;
mod silence;

// Internal Dependencies ------------------------------------------------------
use ::bot::BotConfig;
use ::core::{Member, Message, Server};
use ::action::{ActionGroup, MessageActions};

// Command Abstraction --------------------------------------------------------
pub struct Command<'a> {
    pub name: String,
    pub arguments: Vec<String>,
    pub message: Message,
    pub server: &'a Server,
    pub member: &'a Member,
    pub config: &'a BotConfig
}

// Public Interface -----------------------------------------------------------
impl<'a> Command<'a> {

    pub fn from_parts(
        name: String,
        arguments: Vec<String>,
        message: Message,
        server: &'a Server,
        member: &'a Member,
        config: &'a BotConfig

    ) -> Command<'a> {
        Command {
            name: name,
            arguments: arguments,
            message: message,
            server: server,
            member: member,
            config: config
        }
    }

    fn run<T: CommandHandler>(self, handler: T) -> ActionGroup {

        let argc = self.arguments.len();
        let mut actions: ActionGroup = vec![];

        if handler.delete_command_message() {
            actions.push(MessageActions::Delete::new(self.message));
        }

        if handler.require_unique_server() && !self.message.has_unique_server() {
            actions.push(MessageActions::Send::single_private(
                &self.message,
                format!(
                    "The command `{}` requires a unique server as its target.
                    Since you are a member of at least two bot-enabled servers,
                    the command cannot be invoked from a private channel.
                    Please re-issue the command from a public channels of the target server.",
                    self.name
                )
            ));

        } else if handler.require_server_admin() && !self.member.is_admin {
            actions.push(MessageActions::Send::single_private(
                &self.message,
                format!(
                    "The command `{}` requires bot admin rights on the current server.",
                    self.name
                )
            ));

        } else if argc < handler.require_min_arguments()
               || argc != handler.require_exact_arguments().unwrap_or(argc) {

            actions.append(&mut handler.usage(self));

        } else {
            actions.append(&mut handler.run(self));
        }

        actions

    }

    pub fn process(self) -> ActionGroup {

        if self.member.is_banned {
            return vec![];

        } else {
            match self.name.as_str() {
                "s" => self.run(play::Handler::instant()),
                "q" => self.run(play::Handler::queued()),
                "delete" => self.run(delete::Handler),
                "rename" => self.run(rename::Handler),
                "sounds" => self.run(sounds::Handler),
                "silence" => self.run(silence::Handler),
                "alias" => self.run(alias::Handler),
                "aliases" => self.run(aliases::Handler),
                "greeting" => self.run(greeting::Handler),
                "greetings" => self.run(greetings::Handler),
                "ban" => self.run(ban::Handler),
                "bans" => self.run(bans::Handler),
                "pin" => self.run(pin::Handler),
                "ip" => self.run(ip::Handler),
                "leave" => self.run(leave::Handler),
                "reload" => self.run(reload::Handler),
                "help" => self.run(help::Handler),
                _ => self.run(not_found::Handler)
            }
        }

    }

}

// Traits  --------------------------------------------------------------------
impl<'a> fmt::Display for Command<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f, "[Command \"{}\" with arguments <{}> from user #{} on #{}]",
            self.name,
            self.arguments.join(", "),
            self.message.user_id,
            self.message.server_id
        )
    }
}

// Command Implementation Trait -----------------------------------------------
pub trait CommandHandler {

    fn run(&self, _: Command) -> ActionGroup;

    fn usage(&self, _: Command) -> ActionGroup {
        vec![]
    }

    fn require_unique_server(&self) -> bool {
        false
    }

    fn require_server_admin(&self) -> bool {
        false
    }

    fn require_min_arguments(&self) -> usize {
        0
    }

    fn require_exact_arguments(&self) -> Option<usize> {
        None
    }

    fn delete_command_message(&self) -> bool {
        false
    }

}

<|endoftext|>


<commit_before>use into::IntoError;

#[macro_export]
macro_rules! generate_error_imports {
    () => {
        use std::error::Error;
        use std::fmt::Error as FmtError;
        use std::fmt::{Display, Formatter};

        use $crate::into::IntoError;
    }
}

#[macro_export]
macro_rules! generate_error_module {
    ( $exprs:item ) => {
        pub mod error {
            generate_error_imports!();
            $exprs
        }
    }
}

#[macro_export]
macro_rules! generate_custom_error_types {
    {
        $name: ident,
        $kindname: ident,
        $customMemberTypeName: ident,
        $($kind:ident => $string:expr),*
    } => {
        #[derive(Clone, Copy, Debug, PartialEq)]
        pub enum $kindname {
            $( $kind ),*
        }

        impl Display for $kindname {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                let s = match *self {
                    $( $kindname::$kind => $string ),*
                };
                try!(write!(fmt, "{}", s));
                Ok(())
            }

        }

        impl IntoError for $kindname {
            type Target = $name;

            fn into_error(self) -> Self::Target {
                $name::new(self, None)
            }

            fn into_error_with_cause(self, cause: Box<Error>) -> Self::Target {
                $name::new(self, Some(cause))
            }

        }

        #[derive(Debug)]
        pub struct $name {
            err_type: $kindname,
            cause: Option<Box<Error>>,
            custom_data: Option<$customMemberTypeName>,
        }

        impl $name {

            pub fn new(errtype: $kindname, cause: Option<Box<Error>>) -> $name {
                $name {
                    err_type: errtype,
                    cause: cause,
                    custom_data: None,
                }
            }

            pub fn err_type(&self) -> $kindname {
                self.err_type
            }

        }

        impl Into<$name> for $kindname {

            fn into(self) -> $name {
                $name::new(self, None)
            }

        }

        impl Display for $name {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                try!(write!(fmt, "[{}]", self.err_type));
                Ok(())
            }

        }

        impl Error for $name {

            fn description(&self) -> &str {
                match self.err_type {
                    $( $kindname::$kind => $string ),*
                }
            }

            fn cause(&self) -> Option<&Error> {
                self.cause.as_ref().map(|e| &**e)
            }

        }

    }
}

#[macro_export]
macro_rules! generate_result_helper {
    (
        $name: ident,
        $kindname: ident
    ) => {
        /// Trait to replace
        ///
        /// ```ignore
        /// foo.map_err(Box::new).map_err(|e| SomeType::SomeErrorKind.into_error_with_cause(e))
        /// // or:
        /// foo.map_err(|e| SomeType::SomeErrorKind.into_error_with_cause(Box::new(e)))
        /// ```
        ///
        /// with much nicer
        ///
        /// ```ignore
        /// foo.map_err_into(SomeType::SomeErrorKind)
        /// ```
        ///
        pub trait MapErrInto<T> {
            fn map_err_into(self, error_kind: $kindname) -> Result<T, $name>;
        }

        impl<T, E: Error + 'static> MapErrInto<T> for Result<T, E> {

            fn map_err_into(self, error_kind: $kindname) -> Result<T, $name> {
                self.map_err(Box::new)
                    .map_err(|e| error_kind.into_error_with_cause(e))
            }

        }
    }
}

#[macro_export]
macro_rules! generate_option_helper {
    (
        $name: ident,
        $kindname: ident
    ) => {
        /// Trait to replace
        ///
        /// ```ignore
        /// foo.ok_or(SomeType::SomeErrorKind.into_error())
        /// ```
        ///
        /// with
        ///
        /// ```ignore
        /// foo.ok_or_errkind(SomeType::SomeErrorKind)
        /// ```
        pub trait OkOrErr<T> {
            fn ok_or_errkind(self, kind: $kindname) -> Result<T, $name>;
        }

        impl<T> OkOrErr<T> for Option<T> {

            fn ok_or_errkind(self, kind: $kindname) -> Result<T, $name> {
                self.ok_or(kind.into_error())
            }

        }
    }
}

#[macro_export]
macro_rules! generate_error_types {
    (
        $name: ident,
        $kindname: ident,
        $($kind:ident => $string:expr),*
    ) => {
        #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
        pub struct SomeNotExistingTypeWithATypeNameNoOneWillEverChoose {}
        generate_custom_error_types!($name, $kindname,
                                     SomeNotExistingTypeWithATypeNameNoOneWillEverChoose,
                                     $($kind => $string),*);

        generate_result_helper!($name, $kindname);
        generate_option_helper!($name, $kindname);
    }
}

#[cfg(test)]
mod test {

    generate_error_module!(
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    );

    #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
    pub struct CustomData {
        pub test: i32,
        pub othr: i64,
    }

    generate_error_imports!();

    generate_custom_error_types!(CustomTestError, CustomTestErrorKind,
        CustomData,
        CustomErrorKindA => "customerrorkind a",
        CustomErrorKindB => "customerrorkind B");

    impl CustomTestError {
        pub fn test(&self) -> i32 {
            match self.custom_data {
                Some(t) => t.test,
                None => 0,
            }
        }

        pub fn bar(&self) -> i64 {
            match self.custom_data {
                Some(t) => t.othr,
                None => 0,
            }
        }
    }

    #[test]
    fn test_a() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_b() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_ab() {
        use std::error::Error;
        use self::error::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }

    pub mod anothererrormod {
        generate_error_imports!();
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    }

    #[test]
    fn test_other_a() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_other_b() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_other_ab() {
        use std::error::Error;
        use self::anothererrormod::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }
}
<commit_msg>Add test for error kind mapping<commit_after>use into::IntoError;

#[macro_export]
macro_rules! generate_error_imports {
    () => {
        use std::error::Error;
        use std::fmt::Error as FmtError;
        use std::fmt::{Display, Formatter};

        use $crate::into::IntoError;
    }
}

#[macro_export]
macro_rules! generate_error_module {
    ( $exprs:item ) => {
        pub mod error {
            generate_error_imports!();
            $exprs
        }
    }
}

#[macro_export]
macro_rules! generate_custom_error_types {
    {
        $name: ident,
        $kindname: ident,
        $customMemberTypeName: ident,
        $($kind:ident => $string:expr),*
    } => {
        #[derive(Clone, Copy, Debug, PartialEq)]
        pub enum $kindname {
            $( $kind ),*
        }

        impl Display for $kindname {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                let s = match *self {
                    $( $kindname::$kind => $string ),*
                };
                try!(write!(fmt, "{}", s));
                Ok(())
            }

        }

        impl IntoError for $kindname {
            type Target = $name;

            fn into_error(self) -> Self::Target {
                $name::new(self, None)
            }

            fn into_error_with_cause(self, cause: Box<Error>) -> Self::Target {
                $name::new(self, Some(cause))
            }

        }

        #[derive(Debug)]
        pub struct $name {
            err_type: $kindname,
            cause: Option<Box<Error>>,
            custom_data: Option<$customMemberTypeName>,
        }

        impl $name {

            pub fn new(errtype: $kindname, cause: Option<Box<Error>>) -> $name {
                $name {
                    err_type: errtype,
                    cause: cause,
                    custom_data: None,
                }
            }

            pub fn err_type(&self) -> $kindname {
                self.err_type
            }

        }

        impl Into<$name> for $kindname {

            fn into(self) -> $name {
                $name::new(self, None)
            }

        }

        impl Display for $name {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                try!(write!(fmt, "[{}]", self.err_type));
                Ok(())
            }

        }

        impl Error for $name {

            fn description(&self) -> &str {
                match self.err_type {
                    $( $kindname::$kind => $string ),*
                }
            }

            fn cause(&self) -> Option<&Error> {
                self.cause.as_ref().map(|e| &**e)
            }

        }

    }
}

#[macro_export]
macro_rules! generate_result_helper {
    (
        $name: ident,
        $kindname: ident
    ) => {
        /// Trait to replace
        ///
        /// ```ignore
        /// foo.map_err(Box::new).map_err(|e| SomeType::SomeErrorKind.into_error_with_cause(e))
        /// // or:
        /// foo.map_err(|e| SomeType::SomeErrorKind.into_error_with_cause(Box::new(e)))
        /// ```
        ///
        /// with much nicer
        ///
        /// ```ignore
        /// foo.map_err_into(SomeType::SomeErrorKind)
        /// ```
        ///
        pub trait MapErrInto<T> {
            fn map_err_into(self, error_kind: $kindname) -> Result<T, $name>;
        }

        impl<T, E: Error + 'static> MapErrInto<T> for Result<T, E> {

            fn map_err_into(self, error_kind: $kindname) -> Result<T, $name> {
                self.map_err(Box::new)
                    .map_err(|e| error_kind.into_error_with_cause(e))
            }

        }
    }
}

#[macro_export]
macro_rules! generate_option_helper {
    (
        $name: ident,
        $kindname: ident
    ) => {
        /// Trait to replace
        ///
        /// ```ignore
        /// foo.ok_or(SomeType::SomeErrorKind.into_error())
        /// ```
        ///
        /// with
        ///
        /// ```ignore
        /// foo.ok_or_errkind(SomeType::SomeErrorKind)
        /// ```
        pub trait OkOrErr<T> {
            fn ok_or_errkind(self, kind: $kindname) -> Result<T, $name>;
        }

        impl<T> OkOrErr<T> for Option<T> {

            fn ok_or_errkind(self, kind: $kindname) -> Result<T, $name> {
                self.ok_or(kind.into_error())
            }

        }
    }
}

#[macro_export]
macro_rules! generate_error_types {
    (
        $name: ident,
        $kindname: ident,
        $($kind:ident => $string:expr),*
    ) => {
        #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
        pub struct SomeNotExistingTypeWithATypeNameNoOneWillEverChoose {}
        generate_custom_error_types!($name, $kindname,
                                     SomeNotExistingTypeWithATypeNameNoOneWillEverChoose,
                                     $($kind => $string),*);

        generate_result_helper!($name, $kindname);
        generate_option_helper!($name, $kindname);
    }
}

#[cfg(test)]
mod test {

    generate_error_module!(
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    );

    #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
    pub struct CustomData {
        pub test: i32,
        pub othr: i64,
    }

    generate_error_imports!();

    generate_custom_error_types!(CustomTestError, CustomTestErrorKind,
        CustomData,
        CustomErrorKindA => "customerrorkind a",
        CustomErrorKindB => "customerrorkind B");

    impl CustomTestError {
        pub fn test(&self) -> i32 {
            match self.custom_data {
                Some(t) => t.test,
                None => 0,
            }
        }

        pub fn bar(&self) -> i64 {
            match self.custom_data {
                Some(t) => t.othr,
                None => 0,
            }
        }
    }

    #[test]
    fn test_a() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_b() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_ab() {
        use std::error::Error;
        use self::error::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }

    pub mod anothererrormod {
        generate_error_imports!();
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    }

    #[test]
    fn test_other_a() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_other_b() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_other_ab() {
        use std::error::Error;
        use self::anothererrormod::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }

    #[test]
    fn test_error_kind_mapping() {
        use std::io::{Error, ErrorKind};
        use self::error::{OkOrErr, MapErrInto};
        use self::error::TestErrorKind;

        let err : Result<(), _> = Err(Error::new(ErrorKind::Other, ""));
        let err : Result<(), _> = err.map_err_into(TestErrorKind::TestErrorKindA);

        assert!(err.is_err());
        let err = err.unwrap_err();

        match err.err_type() {
            TestErrorKind::TestErrorKindA => assert!(true),
            _ => assert!(false),
        }
    }

    #[test]
    fn test_error_kind_double_mapping() {
        use std::io::{Error, ErrorKind};
        use self::error::{OkOrErr, MapErrInto};
        use self::error::TestErrorKind;

        let err : Result<(), _> = Err(Error::new(ErrorKind::Other, ""));
        let err : Result<(), _> = err.map_err_into(TestErrorKind::TestErrorKindA)
                                     .map_err_into(TestErrorKind::TestErrorKindB);

        assert!(err.is_err());
        let err = err.unwrap_err();
        match err.err_type() {
            TestErrorKind::TestErrorKindB => assert!(true),
            _ => assert!(false),
        }

        // not sure how to test that the inner error is of TestErrorKindA, actually...
        match err.cause() {
            Some(_) => assert!(true),
            None    => assert!(false),
        }

    }

}
<|endoftext|>


<commit_before>// Copyright (C) 2018, Cloudflare, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate criterion;

use ring::rand::*;

use criterion::Criterion;

fn handshake(c: &mut Criterion) {
    let mut buf = [0; 65535];

    let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
    config
        .load_cert_chain_from_pem_file("examples/cert.crt")
        .unwrap();
    config
        .load_priv_key_from_pem_file("examples/cert.key")
        .unwrap();
    config
        .set_application_protos(b"\x06proto1\x06proto2")
        .unwrap();
    config.set_initial_max_data(2u64.pow(62) - 1);
    config.set_initial_max_stream_data_bidi_local(2u64.pow(62) - 1);
    config.set_initial_max_stream_data_bidi_remote(2u64.pow(62) - 1);
    config.set_initial_max_streams_bidi(3);
    config.set_initial_max_streams_uni(3);
    config.verify_peer(false);

    c.bench_function("handshake", move |b| b.iter(|| {
        let mut pipe = quiche::testing::Pipe::with_config(&mut config).unwrap();
        pipe.handshake(&mut buf).unwrap();
    }));
}

fn stream(c: &mut Criterion) {
    let mut buf = [0; 65535];

    let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
    config
        .load_cert_chain_from_pem_file("examples/cert.crt")
        .unwrap();
    config
        .load_priv_key_from_pem_file("examples/cert.key")
        .unwrap();
    config
        .set_application_protos(b"\x06proto1\x06proto2")
        .unwrap();
    config.set_initial_max_data(2u64.pow(62) - 1);
    config.set_initial_max_stream_data_bidi_local(2u64.pow(62) - 1);
    config.set_initial_max_stream_data_bidi_remote(2u64.pow(62) - 1);
    config.set_initial_max_streams_bidi(3);
    config.set_initial_max_streams_uni(3);
    config.verify_peer(false);

    let mut pipe = quiche::testing::Pipe::with_config(&mut config).unwrap();
    pipe.handshake(&mut buf).unwrap();

    let mut send_buf = vec![0; 1000 * 128];
    SystemRandom::new().fill(&mut send_buf[..]).unwrap();

    let mut recv_buf = vec![0; send_buf.len()];

    c.bench_function("stream", move |b| b.iter(|| {
        pipe.client.stream_send(4, &send_buf, false).unwrap();

        let mut recv_len = 0;

        while recv_len < send_buf.len() {
            loop {
                let len = match pipe.client.send(&mut buf) {
                    Ok(write) => write,

                    Err(quiche::Error::Done) => break,

                    Err(e) => panic!("client send failed {}", e),
                };

                match pipe.server.recv(&mut buf[..len]) {
                    Ok(_) => (),

                    Err(quiche::Error::Done) => (),

                    Err(e) => panic!("server recv failed {}", e),
                }
            }

            let (len, _) = pipe
                .server
                .stream_recv(4, &mut recv_buf[recv_len..])
                .unwrap();
            recv_len += len;

            loop {
                let len = match pipe.server.send(&mut buf) {
                    Ok(write) => write,

                    Err(quiche::Error::Done) => break,

                    Err(e) => panic!("server send failed {}", e),
                };

                match pipe.client.recv(&mut buf[..len]) {
                    Ok(_) => (),

                    Err(quiche::Error::Done) => (),

                    Err(e) => panic!("client recv failed {}", e),
                }
            }
        }

        assert_eq!(&recv_buf, &send_buf);
    }));
}

criterion_group!(benches, handshake, stream);

criterion_main!(benches);
<commit_msg>benches: run stream benchmark with multiple buffer sizes<commit_after>// Copyright (C) 2018, Cloudflare, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate criterion;

use ring::rand::*;

use criterion::Criterion;

fn handshake(c: &mut Criterion) {
    let mut buf = [0; 65535];

    let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
    config
        .load_cert_chain_from_pem_file("examples/cert.crt")
        .unwrap();
    config
        .load_priv_key_from_pem_file("examples/cert.key")
        .unwrap();
    config
        .set_application_protos(b"\x06proto1\x06proto2")
        .unwrap();
    config.set_initial_max_data(2u64.pow(62) - 1);
    config.set_initial_max_stream_data_bidi_local(2u64.pow(62) - 1);
    config.set_initial_max_stream_data_bidi_remote(2u64.pow(62) - 1);
    config.set_initial_max_streams_bidi(3);
    config.set_initial_max_streams_uni(3);
    config.verify_peer(false);

    c.bench_function("handshake", move |b| b.iter(|| {
        let mut pipe = quiche::testing::Pipe::with_config(&mut config).unwrap();
        pipe.handshake(&mut buf).unwrap();
    }));
}

fn stream(c: &mut Criterion) {
    let mut buf = [0; 65535];

    let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
    config
        .load_cert_chain_from_pem_file("examples/cert.crt")
        .unwrap();
    config
        .load_priv_key_from_pem_file("examples/cert.key")
        .unwrap();
    config
        .set_application_protos(b"\x06proto1\x06proto2")
        .unwrap();
    config.set_initial_max_data(2u64.pow(62) - 1);
    config.set_initial_max_stream_data_bidi_local(2u64.pow(62) - 1);
    config.set_initial_max_stream_data_bidi_remote(2u64.pow(62) - 1);
    config.set_initial_max_streams_bidi(3);
    config.set_initial_max_streams_uni(3);
    config.verify_peer(false);

    let mut pipe = quiche::testing::Pipe::with_config(&mut config).unwrap();
    pipe.handshake(&mut buf).unwrap();

    let mut send_buf = vec![0; 5_000_000];
    SystemRandom::new().fill(&mut send_buf[..]).unwrap();

    let mut recv_buf = vec![0; send_buf.len()];

    c.bench_function_over_inputs("stream", move |b, &&size| b.iter(|| {
        pipe.client.stream_send(4, &send_buf[..size], false).unwrap();

        let mut recv_len = 0;

        while recv_len < size {
            loop {
                let len = match pipe.client.send(&mut buf) {
                    Ok(write) => write,

                    Err(quiche::Error::Done) => break,

                    Err(e) => panic!("client send failed {}", e),
                };

                match pipe.server.recv(&mut buf[..len]) {
                    Ok(_) => (),

                    Err(quiche::Error::Done) => (),

                    Err(e) => panic!("server recv failed {}", e),
                }
            }

            let (len, _) = pipe
                .server
                .stream_recv(4, &mut recv_buf[recv_len..])
                .unwrap();
            recv_len += len;

            loop {
                let len = match pipe.server.send(&mut buf) {
                    Ok(write) => write,

                    Err(quiche::Error::Done) => break,

                    Err(e) => panic!("server send failed {}", e),
                };

                match pipe.client.recv(&mut buf[..len]) {
                    Ok(_) => (),

                    Err(quiche::Error::Done) => (),

                    Err(e) => panic!("client recv failed {}", e),
                }
            }
        }

        assert_eq!(&recv_buf[..size], &send_buf[..size]);
    }), &[128_000, 5_000_000]);
}

criterion_group!(benches, handshake, stream);

criterion_main!(benches);
<|endoftext|>