<commit_before>use oppai_common::common::is_last_move_stupid;
use oppai_common::trajectory::{build_trajectories, build_trajectories_from, Trajectory};
use oppai_field::field::wave_diag;
use oppai_field::field::{Field, NonZeroPos, Pos};
use oppai_field::player::Player;
use std::iter;
use std::sync::atomic::{AtomicBool, Ordering};

fn mark_group(field: &Field, start_pos: Pos, player: Player, empty_board: &mut Vec<u32>) -> Vec<Pos> {
  let mut marks = Vec::new();
  wave_diag(field.width(), start_pos, |pos| {
    if empty_board[pos] != 0 {
      return false;
    }
    let cell = field.cell(pos);
    if cell.is_players_point(player) {
      empty_board[pos] = 1;
      marks.push(pos);
      true
    } else {
      false
    }
  });
  marks
}

fn collect_near_moves(field: &Field, player: Player, empty_board: &mut Vec<u32>) -> Vec<Pos> {
  let mut moves = Vec::new();
  for &pos in field
    .points_seq()
    .iter()
    .filter(|&&pos| field.cell(pos).is_players_point(player))
  {
    for &near_pos in field.directions(pos).iter() {
      if empty_board[near_pos] == 0 && field.is_putting_allowed(near_pos) {
        moves.push(near_pos);
        empty_board[near_pos] = 1;
      }
    }
  }
  for &pos in &moves {
    empty_board[pos] = 0;
  }
  moves
}

fn is_trajectoty_alive(field: &mut Field, trajectory: &Trajectory, player: Player, empty_board: &mut Vec<u32>) -> bool {
  if trajectory.points().iter().any(|&pos| !field.is_putting_allowed(pos)) {
    return false;
  }

  for &pos in trajectory.points() {
    field.put_point(pos, player);
  }

  let result = field.get_delta_score(player) > 0 || {
    let enemy = player.next();
    let moves = collect_near_moves(field, enemy, empty_board);
    moves.into_iter().any(|pos| {
      field.put_point(pos, player);
      let result = field.get_delta_score(player) > 0
        && trajectory
          .points()
          .iter()
          .all(|&trajectory_pos| field.cell(trajectory_pos).is_bound());
      field.undo();
      result && {
        let enemies_around = field
          .directions(pos)
          .iter()
          .filter(|&&pos| field.cell(pos).is_players_point(enemy))
          .count();
        enemies_around < 3
          || enemies_around == 3
            && field
              .directions(pos)
              .iter()
              .all(|&near_pos| !field.cell(near_pos).is_putting_allowed())
      }
    })
  };

  for _ in 0..trajectory.len() {
    field.undo();
  }

  result
}

fn is_trajectoty_viable(
  field: &mut Field,
  trajectory: &Trajectory,
  player: Player,
  empty_board: &mut Vec<u32>,
) -> bool {
  let moves = collect_near_moves(field, player, empty_board);
  let enemy = player.next();
  moves.into_iter().all(|enemy_pos| {
    field.put_point(enemy_pos, enemy);

    if field.get_delta_score(enemy) == 0 {
      field.undo();
      return true;
    }

    let result = is_trajectoty_alive(field, trajectory, player, empty_board);

    field.undo();

    result
  })
}

fn ladders_rec(
  field: &mut Field,
  player: Player,
  trajectory: &Trajectory,
  empty_board: &mut Vec<u32>,
  should_stop: &AtomicBool,
  depth: u32,
) -> (Option<NonZeroPos>, i32, u32) {
  match *trajectory.points().as_slice() {
    [pos] => {
      field.put_point(pos, player);
      let cur_score = field.score(player);
      field.undo();
      (NonZeroPos::new(pos), cur_score, depth)
    }
    [pos1, pos2] => {
      let mut max_score = field.score(player);
      let mut best_move = None;
      let mut capture_depth = 0;

      for &(our_pos, enemy_pos) in &[(pos1, pos2), (pos2, pos1)] {
        if trajectory.score() <= max_score {
          break;
        }

        if field.cell(our_pos).is_players_empty_base(player.next()) {
          continue;
        }

        if !field.put_point(our_pos, player) {
          panic!(
            "Failed to put a point to ({}, {}) on the field:\n{}",
            field.to_x(our_pos),
            field.to_y(our_pos),
            field,
          );
        }

        if is_last_move_stupid(field, our_pos, player) {
          field.undo();
          continue;
        }

        if field.get_delta_score(player) > 0 {
          let cur_score = field.score(player);
          field.undo();
          if cur_score > max_score {
            max_score = cur_score;
            best_move = NonZeroPos::new(our_pos);
            capture_depth = depth;
          }
          continue;
        }

        if !field.put_point(enemy_pos, player.next()) {
          panic!(
            "Failed to put a point to ({}, {}) on the field:\n{}",
            field.to_x(our_pos),
            field.to_y(our_pos),
            field,
          );
        }

        let trajectories = build_trajectories_from(field, our_pos, player, 2, empty_board, should_stop);

        if should_stop.load(Ordering::Relaxed) {
          break;
        }

        let marks = mark_group(field, our_pos, player, empty_board);

        for trajectory in trajectories {
          if trajectory.score() <= max_score {
            continue;
          }

          let (_, cur_score, cur_capture_depth) =
            ladders_rec(field, player, &trajectory, empty_board, should_stop, depth + 1);
          let cur_score = cur_score.min(trajectory.score());

          if cur_score > max_score && is_trajectoty_viable(field, &trajectory, player, empty_board) {
            max_score = cur_score;
            best_move = NonZeroPos::new(our_pos);
            capture_depth = cur_capture_depth;
          }
        }

        for pos in marks {
          empty_board[pos] = 0;
        }

        field.undo();
        field.undo();
      }

      (best_move, max_score, capture_depth)
    }
    _ => unreachable!("Trajectory with {} points", trajectory.len()),
  }
}

pub fn ladders(field: &mut Field, player: Player, should_stop: &AtomicBool) -> (Option<NonZeroPos>, i32, u32) {
  let mut empty_board = iter::repeat(0u32).take(field.length()).collect();

  let trajectories = build_trajectories(field, player, 2, &mut empty_board, &should_stop);

  info!("Solving ladders for {} trajectories.", trajectories.len());

  let base_score = field.score(player);
  let mut max_score = base_score;
  let mut capture_depth = 0;
  let mut best_move = None;

  for trajectory in trajectories {
    if should_stop.load(Ordering::Relaxed) {
      break;
    }

    if trajectory.score() <= max_score {
      continue;
    }

    let marks = if let [pos1, _] = *trajectory.points().as_slice() {
      if let Some(&pos) = field
        .directions_diag(pos1)
        .iter()
        .find(|&&pos| field.cell(pos).is_players_point(player))
      {
        // mark one of near groups to not search trajectories from it
        mark_group(field, pos, player, &mut empty_board)
      } else {
        Vec::new()
      }
    } else {
      Vec::new()
    };

    let (cur_pos, cur_score, cur_capture_depth) =
      ladders_rec(field, player, &trajectory, &mut empty_board, should_stop, 0);
    let cur_score = cur_score.min(trajectory.score());
    if cur_score > max_score && is_trajectoty_viable(field, &trajectory, player, &mut empty_board) {
      max_score = cur_score;
      capture_depth = cur_capture_depth;
      best_move = cur_pos;
    }

    for pos in marks {
      empty_board[pos] = 0;
    }
  }

  (best_move, max_score, capture_depth)
}
<commit_msg>Alpha pruning for trajectories.<commit_after>use oppai_common::common::is_last_move_stupid;
use oppai_common::trajectory::{build_trajectories, build_trajectories_from, Trajectory};
use oppai_field::field::wave_diag;
use oppai_field::field::{Field, NonZeroPos, Pos};
use oppai_field::player::Player;
use std::iter;
use std::sync::atomic::{AtomicBool, Ordering};

fn mark_group(field: &Field, start_pos: Pos, player: Player, empty_board: &mut Vec<u32>) -> Vec<Pos> {
  let mut marks = Vec::new();
  wave_diag(field.width(), start_pos, |pos| {
    if empty_board[pos] != 0 {
      return false;
    }
    let cell = field.cell(pos);
    if cell.is_players_point(player) {
      empty_board[pos] = 1;
      marks.push(pos);
      true
    } else {
      false
    }
  });
  marks
}

fn collect_near_moves(field: &Field, player: Player, empty_board: &mut Vec<u32>) -> Vec<Pos> {
  let mut moves = Vec::new();
  for &pos in field
    .points_seq()
    .iter()
    .filter(|&&pos| field.cell(pos).is_players_point(player))
  {
    for &near_pos in field.directions(pos).iter() {
      if empty_board[near_pos] == 0 && field.is_putting_allowed(near_pos) {
        moves.push(near_pos);
        empty_board[near_pos] = 1;
      }
    }
  }
  for &pos in &moves {
    empty_board[pos] = 0;
  }
  moves
}

fn is_trajectoty_alive(field: &mut Field, trajectory: &Trajectory, player: Player, empty_board: &mut Vec<u32>) -> bool {
  if trajectory.points().iter().any(|&pos| !field.is_putting_allowed(pos)) {
    return false;
  }

  for &pos in trajectory.points() {
    field.put_point(pos, player);
  }

  let result = field.get_delta_score(player) > 0 || {
    let enemy = player.next();
    let moves = collect_near_moves(field, enemy, empty_board);
    moves.into_iter().any(|pos| {
      field.put_point(pos, player);
      let result = field.get_delta_score(player) > 0
        && trajectory
          .points()
          .iter()
          .all(|&trajectory_pos| field.cell(trajectory_pos).is_bound());
      field.undo();
      result && {
        let enemies_around = field
          .directions(pos)
          .iter()
          .filter(|&&pos| field.cell(pos).is_players_point(enemy))
          .count();
        enemies_around < 3
          || enemies_around == 3
            && field
              .directions(pos)
              .iter()
              .all(|&near_pos| !field.cell(near_pos).is_putting_allowed())
      }
    })
  };

  for _ in 0..trajectory.len() {
    field.undo();
  }

  result
}

fn is_trajectoty_viable(
  field: &mut Field,
  trajectory: &Trajectory,
  player: Player,
  empty_board: &mut Vec<u32>,
) -> bool {
  let moves = collect_near_moves(field, player, empty_board);
  let enemy = player.next();
  moves.into_iter().all(|enemy_pos| {
    field.put_point(enemy_pos, enemy);

    if field.get_delta_score(enemy) == 0 {
      field.undo();
      return true;
    }

    let result = is_trajectoty_alive(field, trajectory, player, empty_board);

    field.undo();

    result
  })
}

fn ladders_rec(
  field: &mut Field,
  player: Player,
  trajectory: &Trajectory,
  mut alpha: i32,
  empty_board: &mut Vec<u32>,
  should_stop: &AtomicBool,
  depth: u32,
) -> (Option<NonZeroPos>, i32, u32) {
  match *trajectory.points().as_slice() {
    [pos] => {
      field.put_point(pos, player);
      let cur_score = field.score(player);
      field.undo();
      (NonZeroPos::new(pos), cur_score, depth)
    }
    [pos1, pos2] => {
      let mut best_move = None;
      let mut capture_depth = 0;

      for &(our_pos, enemy_pos) in &[(pos1, pos2), (pos2, pos1)] {
        if trajectory.score() <= alpha {
          break;
        }

        if field.cell(our_pos).is_players_empty_base(player.next()) {
          continue;
        }

        if !field.put_point(our_pos, player) {
          panic!(
            "Failed to put a point to ({}, {}) on the field:\n{}",
            field.to_x(our_pos),
            field.to_y(our_pos),
            field,
          );
        }

        if is_last_move_stupid(field, our_pos, player) {
          field.undo();
          continue;
        }

        if field.get_delta_score(player) > 0 {
          let cur_score = field.score(player);
          field.undo();
          if cur_score > alpha {
            alpha = cur_score;
            best_move = NonZeroPos::new(our_pos);
            capture_depth = depth;
          }
          continue;
        }

        if !field.put_point(enemy_pos, player.next()) {
          panic!(
            "Failed to put a point to ({}, {}) on the field:\n{}",
            field.to_x(our_pos),
            field.to_y(our_pos),
            field,
          );
        }

        let trajectories = build_trajectories_from(field, our_pos, player, 2, empty_board, should_stop);

        if should_stop.load(Ordering::Relaxed) {
          break;
        }

        let marks = mark_group(field, our_pos, player, empty_board);

        for trajectory in trajectories {
          if trajectory.score() <= alpha {
            continue;
          }

          let (_, cur_score, cur_capture_depth) =
            ladders_rec(field, player, &trajectory, alpha, empty_board, should_stop, depth + 1);
          let cur_score = cur_score.min(trajectory.score());

          if cur_score > alpha && is_trajectoty_viable(field, &trajectory, player, empty_board) {
            alpha = cur_score;
            best_move = NonZeroPos::new(our_pos);
            capture_depth = cur_capture_depth;
          }
        }

        for pos in marks {
          empty_board[pos] = 0;
        }

        field.undo();
        field.undo();
      }

      (best_move, alpha, capture_depth)
    }
    _ => unreachable!("Trajectory with {} points", trajectory.len()),
  }
}

pub fn ladders(field: &mut Field, player: Player, should_stop: &AtomicBool) -> (Option<NonZeroPos>, i32, u32) {
  let mut empty_board = iter::repeat(0u32).take(field.length()).collect();

  let trajectories = build_trajectories(field, player, 2, &mut empty_board, &should_stop);

  info!("Solving ladders for {} trajectories.", trajectories.len());

  let mut alpha = field.score(player);
  let mut capture_depth = 0;
  let mut best_move = None;

  for trajectory in trajectories {
    if should_stop.load(Ordering::Relaxed) {
      break;
    }

    if trajectory.score() <= alpha {
      continue;
    }

    let marks = if let [pos1, _] = *trajectory.points().as_slice() {
      if let Some(&pos) = field
        .directions_diag(pos1)
        .iter()
        .find(|&&pos| field.cell(pos).is_players_point(player))
      {
        // mark one of near groups to not search trajectories from it
        mark_group(field, pos, player, &mut empty_board)
      } else {
        Vec::new()
      }
    } else {
      Vec::new()
    };

    let (cur_pos, cur_score, cur_capture_depth) =
      ladders_rec(field, player, &trajectory, alpha, &mut empty_board, should_stop, 0);
    let cur_score = cur_score.min(trajectory.score());
    if cur_score > alpha && is_trajectoty_viable(field, &trajectory, player, &mut empty_board) {
      alpha = cur_score;
      capture_depth = cur_capture_depth;
      best_move = cur_pos;
    }

    for pos in marks {
      empty_board[pos] = 0;
    }
  }

  (best_move, alpha, capture_depth)
}
<|endoftext|>


<commit_before>//! A few random tests.
//! Knowing how much I neglect this aspect of software development,
//! there probably won't be a significant coverage.

extern crate libxml;

use libxml::tree::{Document, Node, Namespace};
use libxml::xpath::{Context};
use libxml::parser::{Parser};

#[test]
/// Build a hello world XML doc
fn hello_builder() {
  let doc_result = Document::new();
  assert!(doc_result.is_ok());
  let mut doc = doc_result.unwrap();

  let hello_element_result = Node::new("hello", None, &doc);
  assert!(hello_element_result.is_ok());
  let mut hello_element = hello_element_result.unwrap();

  let mock_ns_result = Namespace::new(&hello_element, "http://example.com/ns/mock", "mock");
  assert!(mock_ns_result.is_ok());
  // let mock_ns = mock_ns_result.unwrap();

  doc.set_root_element(&mut hello_element);

  hello_element.set_content("world!");

  let added = hello_element.add_child(None, "child");
  assert!(added.is_ok());
  let new_child = added.unwrap();

  new_child.set_content("set content");

  let node_string = doc.node_to_string(hello_element);
  assert!(node_string.len() > 1);

  // Add a PI
  doc.create_processing_instruction("piname","picontent").is_ok();

  let doc_string = doc.to_string();
  assert!(doc_string.len() > 1);
  assert!(doc.save_file("tests/results/helloworld.xml").is_ok());
}

#[test]
/// Duplicate an xml file
fn duplicate_file() {
    let parser = Parser::default();
    {
      let doc_parse = parser.parse_file("tests/resources/file01.xml");
      assert!(doc_parse.is_ok());

      let doc = doc_parse.unwrap();
      doc.save_file("tests/results/copy.xml").unwrap();
    }
}

#[test]
/// Can load an HTML file
fn can_load_html_file() {
  let parser = Parser::default_html();
  {
    let doc_parse = parser.parse_file("tests/resources/example.html");
    assert!(doc_parse.is_ok());

    let doc = doc_parse.unwrap();
    let root_result = doc.get_root_element();
    assert!(root_result.is_ok());
    let root = root_result.unwrap();
    assert_eq!(root.get_name(),"html");
  }
}

#[test]
/// Root node and first child of root node are different
/// (There is a tiny chance this might fail for a correct program)
fn child_of_root_has_different_hash() {
  let parser = Parser::default();
  {
    let doc = parser.parse_file("tests/resources/file01.xml").unwrap();
    let root = doc.get_root_element().unwrap();
    assert!(!root.is_text_node());
    if let Some(child) = root.get_first_child() {
      assert!(root != child);
    } else {
      assert!(false);   //test failed - child doesn't exist
    }
  }
}

#[test]
/// Test the evaluation of an xpath expression yields the correct number of nodes
fn test_xpath_result_number_correct() {
  let parser = Parser::default();
  let doc = parser.parse_file("tests/resources/file01.xml").unwrap();
  let context = Context::new(&doc).unwrap();

  let result1 = context.evaluate("//child").unwrap();
  assert_eq!(result1.get_number_of_nodes(), 2);
  assert_eq!(result1.get_nodes_as_vec().len(), 2);

  let result2 = context.evaluate("//nonexistent").unwrap();
  assert_eq!(result2.get_number_of_nodes(), 0);
  assert_eq!(result2.get_nodes_as_vec().len(), 0);
}

#[test]
/// Test that an xpath expression finds the correct node and
/// that the class names are interpreted correctly.
fn test_class_names() {
  let parser = Parser::default_html();
  let doc = parser.parse_file("tests/resources/file02.xml").unwrap();
  let context = Context::new(&doc).unwrap();

  let result = context.evaluate("/html/body/p").unwrap();
  assert_eq!(result.get_number_of_nodes(), 1);

  let node = &result.get_nodes_as_vec()[0];
  let names = node.get_class_names();
  assert_eq!(names.len(), 2);
  assert!(names.contains("paragraph"));
  assert!(names.contains("important"));
  assert!(!names.contains("nonsense"));
}
<commit_msg>move pi to separate test (still broken ...)<commit_after>//! A few random tests.
//! Knowing how much I neglect this aspect of software development,
//! there probably won't be a significant coverage.

extern crate libxml;

use libxml::tree::{Document, Node, Namespace};
use libxml::xpath::{Context};
use libxml::parser::{Parser};

#[test]
/// Build a hello world XML doc
fn hello_builder() {
  let doc_result = Document::new();
  assert!(doc_result.is_ok());
  let mut doc = doc_result.unwrap();

  let hello_element_result = Node::new("hello", None, &doc);
  assert!(hello_element_result.is_ok());
  let mut hello_element = hello_element_result.unwrap();

  let mock_ns_result = Namespace::new(&hello_element, "http://example.com/ns/mock", "mock");
  assert!(mock_ns_result.is_ok());
  // let mock_ns = mock_ns_result.unwrap();

  doc.set_root_element(&mut hello_element);

  hello_element.set_content("world!");

  let added = hello_element.add_child(None, "child");
  assert!(added.is_ok());
  let new_child = added.unwrap();

  new_child.set_content("set content");

  let node_string = doc.node_to_string(hello_element);
  assert!(node_string.len() > 1);

  let doc_string = doc.to_string();
  assert!(doc_string.len() > 1);
  assert!(doc.save_file("tests/results/helloworld.xml").is_ok());
}

#[test]
fn create_pi() {
  let doc_result = Document::new();
  assert!(doc_result.is_ok());
  let mut doc = doc_result.unwrap();
  // Add a PI
  let node_ok = doc.create_processing_instruction("piname","picontent");
  assert!(node_ok.is_ok());
  let doc_string = doc.to_string();
  println!("{:?}", doc_string);
  assert!(doc_string.len() > 1);
}

#[test]
/// Duplicate an xml file
fn duplicate_file() {
    let parser = Parser::default();
    {
      let doc_parse = parser.parse_file("tests/resources/file01.xml");
      assert!(doc_parse.is_ok());

      let doc = doc_parse.unwrap();
      doc.save_file("tests/results/copy.xml").unwrap();
    }
}

#[test]
/// Can load an HTML file
fn can_load_html_file() {
  let parser = Parser::default_html();
  {
    let doc_parse = parser.parse_file("tests/resources/example.html");
    assert!(doc_parse.is_ok());

    let doc = doc_parse.unwrap();
    let root_result = doc.get_root_element();
    assert!(root_result.is_ok());
    let root = root_result.unwrap();
    assert_eq!(root.get_name(),"html");
  }
}

#[test]
/// Root node and first child of root node are different
/// (There is a tiny chance this might fail for a correct program)
fn child_of_root_has_different_hash() {
  let parser = Parser::default();
  {
    let doc = parser.parse_file("tests/resources/file01.xml").unwrap();
    let root = doc.get_root_element().unwrap();
    assert!(!root.is_text_node());
    if let Some(child) = root.get_first_child() {
      assert!(root != child);
    } else {
      assert!(false);   //test failed - child doesn't exist
    }
  }
}

#[test]
/// Test the evaluation of an xpath expression yields the correct number of nodes
fn test_xpath_result_number_correct() {
  let parser = Parser::default();
  let doc = parser.parse_file("tests/resources/file01.xml").unwrap();
  let context = Context::new(&doc).unwrap();

  let result1 = context.evaluate("//child").unwrap();
  assert_eq!(result1.get_number_of_nodes(), 2);
  assert_eq!(result1.get_nodes_as_vec().len(), 2);

  let result2 = context.evaluate("//nonexistent").unwrap();
  assert_eq!(result2.get_number_of_nodes(), 0);
  assert_eq!(result2.get_nodes_as_vec().len(), 0);
}

#[test]
/// Test that an xpath expression finds the correct node and
/// that the class names are interpreted correctly.
fn test_class_names() {
  let parser = Parser::default_html();
  let doc = parser.parse_file("tests/resources/file02.xml").unwrap();
  let context = Context::new(&doc).unwrap();

  let result = context.evaluate("/html/body/p").unwrap();
  assert_eq!(result.get_number_of_nodes(), 1);

  let node = &result.get_nodes_as_vec()[0];
  let names = node.get_class_names();
  assert_eq!(names.len(), 2);
  assert!(names.contains("paragraph"));
  assert!(names.contains("important"));
  assert!(!names.contains("nonsense"));
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(stainless)]

extern crate stainless;
extern crate icepick;

mod test {
    use icepick::score;
    use icepick::score::Match;

    pub fn do_score<'a>(choice: &'a String, query: &str) -> Option<Match<'a>> {
       let query_stirng = query.to_string();
       score::score(&choice,  &query_stirng)
    }

    pub fn match_quality(choice: &str, query: &str) -> f32 {
        let choice_stirng = choice.to_string();
        let query_stirng = query.to_string();
        let m = score::score(&choice_stirng, &query_stirng);
        let Quality(quality) = m.unwrap().quality;
        quality
    }

    pub fn match_substring(choice: &str, query: &str) -> (usize, usize) {
        let choice_stirng = choice.to_string();
        let query_stirng = query.to_string();
        let m = score::score(&choice_stirng, &query_stirng);
        let Substring(start,end) = m.unwrap().range;
        (start,end)
    }

    pub use athena::score::Substring;
    pub use athena::score::Quality;

    describe! score_and_match {
        it "scores_greater_than_zero_and_shows_match" {
            let range =  match_substring("a", "a");
            assert_eq!(range, (0,1));
        }

        it "match_range_ends_in_non_inclusive" {
            //                           0123456789
            let range = match_substring("ana.gemspec", "asp");
            assert_eq!(range, (2,9));
        }
    }

    describe! score_test {
        describe! mismatch {
            it "no_match_when_the_choice_is_emtpy" {
                let input = "".to_string();
                assert_eq!(do_score(&input, "a"), None);
            }

            it "no_match_if_query_is_longer_than_the_choice" {
                let input = "a".to_string();
                assert_eq!(do_score(&input, "aaaaa"), None);
            }

            it "no_match_if_query_does_not_match_at_all" {
                let input = "a".to_string();
                assert_eq!(do_score(&input, "b"), None);
            }

            it "repeated_character_does_not_match" {
                let input = "a".to_string();
                assert_eq!(do_score(&input,  "aa"), None);
            }
        }

        describe! empty_query {
            it "scores_one_when_the_query_is_empty" {
                assert_eq!(match_quality("a", ""), 1.0);
            }
        }

        describe! match_quality {
            it "scores_greater_than_zero_if_query_matches_choice" {
                assert!(match_quality("a", "a") > 0.0);
                assert!(match_quality("ab", "a") > 0.0);
                assert!(match_quality("ba", "a") > 0.0);
                assert!(match_quality("bab", "a") > 0.0);
                assert!(match_quality("babababab", "aaaa") > 0.0);
            }

            it "matches_punctuation" {
                assert!(match_quality("/! symbols $^", "/!$^") > 0.0);
            }

            it "normalizes_score_based_on_length" {
                assert_eq!(match_quality("a", "a"), 1.0);
                assert_eq!(match_quality("ab", "ab"), 0.5);
                assert_eq!(match_quality("a long string", "a long string"), 1.0 / "a long string".len() as f32);
                assert_eq!(match_quality("spec/search_spec.rb", "sear"), 1.0 / "spec/search_spec.rb".len() as f32)
            }

            it "scores_higher_for_better_matches" {
                assert!(match_quality("ahtena.gemspec", "asp") > match_quality("algorithm4_spec.rb", "asp"));
                assert!(match_quality("readme.md", "em") > match_quality("benchmark.rb", "em"));
                assert!(match_quality("search.rb", "sear") > match_quality("spec/search_spec.rb", "sear"));
            }

            it "scores_shorter_matches_higher" {
                assert!(match_quality("fbb", "fbb") > match_quality("foo bar baz", "fbb"));
                assert!(match_quality("foo", "foo") > match_quality("longer foo", "foo"));
                assert!(match_quality("foo", "foo") > match_quality("foo longer", "foo"));
                assert!(match_quality("1/2/3/4", "1/2/3") > match_quality("1/9/2/3/4", "1/2/3"));
            }

            it "scores_the_tighter_of_two_matches_regardless_of_order" {
                let beginning = "121padding2";
                let end = "1padding212";
                assert_eq!(match_quality(beginning, "12"), match_quality(end, "12"));
            }

            it "tighter_matches_score_higher" {
                assert!(match_quality("long 12 long", "12") > match_quality("1 long 2", "12"));
            }
        }
    }
}
<commit_msg>Fix leftover from rename to icepick<commit_after>#![feature(plugin)]
#![plugin(stainless)]

extern crate stainless;
extern crate icepick;

mod test {
    use icepick::score;
    use icepick::score::Match;

    pub fn do_score<'a>(choice: &'a String, query: &str) -> Option<Match<'a>> {
       let query_stirng = query.to_string();
       score::score(&choice,  &query_stirng)
    }

    pub fn match_quality(choice: &str, query: &str) -> f32 {
        let choice_stirng = choice.to_string();
        let query_stirng = query.to_string();
        let m = score::score(&choice_stirng, &query_stirng);
        let Quality(quality) = m.unwrap().quality;
        quality
    }

    pub fn match_substring(choice: &str, query: &str) -> (usize, usize) {
        let choice_stirng = choice.to_string();
        let query_stirng = query.to_string();
        let m = score::score(&choice_stirng, &query_stirng);
        let Substring(start,end) = m.unwrap().range;
        (start,end)
    }

    pub use icepick::score::Substring;
    pub use icepick::score::Quality;

    describe! score_and_match {
        it "scores_greater_than_zero_and_shows_match" {
            let range =  match_substring("a", "a");
            assert_eq!(range, (0,1));
        }

        it "match_range_ends_in_non_inclusive" {
            //                           0123456789
            let range = match_substring("ana.gemspec", "asp");
            assert_eq!(range, (2,9));
        }
    }

    describe! score_test {
        describe! mismatch {
            it "no_match_when_the_choice_is_emtpy" {
                let input = "".to_string();
                assert_eq!(do_score(&input, "a"), None);
            }

            it "no_match_if_query_is_longer_than_the_choice" {
                let input = "a".to_string();
                assert_eq!(do_score(&input, "aaaaa"), None);
            }

            it "no_match_if_query_does_not_match_at_all" {
                let input = "a".to_string();
                assert_eq!(do_score(&input, "b"), None);
            }

            it "repeated_character_does_not_match" {
                let input = "a".to_string();
                assert_eq!(do_score(&input,  "aa"), None);
            }
        }

        describe! empty_query {
            it "scores_one_when_the_query_is_empty" {
                assert_eq!(match_quality("a", ""), 1.0);
            }
        }

        describe! match_quality {
            it "scores_greater_than_zero_if_query_matches_choice" {
                assert!(match_quality("a", "a") > 0.0);
                assert!(match_quality("ab", "a") > 0.0);
                assert!(match_quality("ba", "a") > 0.0);
                assert!(match_quality("bab", "a") > 0.0);
                assert!(match_quality("babababab", "aaaa") > 0.0);
            }

            it "matches_punctuation" {
                assert!(match_quality("/! symbols $^", "/!$^") > 0.0);
            }

            it "normalizes_score_based_on_length" {
                assert_eq!(match_quality("a", "a"), 1.0);
                assert_eq!(match_quality("ab", "ab"), 0.5);
                assert_eq!(match_quality("a long string", "a long string"), 1.0 / "a long string".len() as f32);
                assert_eq!(match_quality("spec/search_spec.rb", "sear"), 1.0 / "spec/search_spec.rb".len() as f32)
            }

            it "scores_higher_for_better_matches" {
                assert!(match_quality("ahtena.gemspec", "asp") > match_quality("algorithm4_spec.rb", "asp"));
                assert!(match_quality("readme.md", "em") > match_quality("benchmark.rb", "em"));
                assert!(match_quality("search.rb", "sear") > match_quality("spec/search_spec.rb", "sear"));
            }

            it "scores_shorter_matches_higher" {
                assert!(match_quality("fbb", "fbb") > match_quality("foo bar baz", "fbb"));
                assert!(match_quality("foo", "foo") > match_quality("longer foo", "foo"));
                assert!(match_quality("foo", "foo") > match_quality("foo longer", "foo"));
                assert!(match_quality("1/2/3/4", "1/2/3") > match_quality("1/9/2/3/4", "1/2/3"));
            }

            it "scores_the_tighter_of_two_matches_regardless_of_order" {
                let beginning = "121padding2";
                let end = "1padding212";
                assert_eq!(match_quality(beginning, "12"), match_quality(end, "12"));
            }

            it "tighter_matches_score_higher" {
                assert!(match_quality("long 12 long", "12") > match_quality("1 long 2", "12"));
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! Logging for alacritty.
//!
//! The main executable is supposed to call `initialize()` exactly once during
//! startup. All logging messages are written to stdout, given that their
//! log-level is sufficient for the level configured in `cli::Options`.
use std::env;
use std::fs::{File, OpenOptions};
use std::io::{self, LineWriter, Stdout, Write};
use std::path::PathBuf;
use std::process;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};

use glutin::event_loop::EventLoopProxy;
use log::{self, Level};

use alacritty_terminal::event::Event;
use alacritty_terminal::message_bar::Message;
use alacritty_terminal::term::color;

use crate::cli::Options;

const ALACRITTY_LOG_ENV: &str = "ALACRITTY_LOG";

pub fn initialize(
    options: &Options,
    event_proxy: EventLoopProxy<Event>,
) -> Result<Option<PathBuf>, log::SetLoggerError> {
    log::set_max_level(options.log_level);

    // Use env_logger if RUST_LOG environment variable is defined. Otherwise,
    // use the alacritty-only logger.
    if std::env::var("RUST_LOG").is_ok() {
        env_logger::try_init()?;
        Ok(None)
    } else {
        let logger = Logger::new(event_proxy);
        let path = logger.file_path();
        log::set_boxed_logger(Box::new(logger))?;
        Ok(path)
    }
}

pub struct Logger {
    logfile: Mutex<OnDemandLogFile>,
    stdout: Mutex<LineWriter<Stdout>>,
    event_proxy: Mutex<EventLoopProxy<Event>>,
}

impl Logger {
    fn new(event_proxy: EventLoopProxy<Event>) -> Self {
        let logfile = Mutex::new(OnDemandLogFile::new());
        let stdout = Mutex::new(LineWriter::new(io::stdout()));

        Logger { logfile, stdout, event_proxy: Mutex::new(event_proxy) }
    }

    fn file_path(&self) -> Option<PathBuf> {
        if let Ok(logfile) = self.logfile.lock() {
            Some(logfile.path().clone())
        } else {
            None
        }
    }
}

impl log::Log for Logger {
    fn enabled(&self, metadata: &log::Metadata<'_>) -> bool {
        metadata.level() <= log::max_level()
    }

    fn log(&self, record: &log::Record<'_>) {
        if self.enabled(record.metadata()) && record.target().starts_with("alacritty") {
            let now = time::strftime("%F %R", &time::now()).unwrap();

            let msg = if record.level() >= Level::Trace {
                format!(
                    "[{}] [{}] [{}:{}] {}\n",
                    now,
                    record.level(),
                    record.file().unwrap_or("?"),
                    record.line().map(|l| l.to_string()).unwrap_or_else(|| "?".into()),
                    record.args()
                )
            } else {
                format!("[{}] [{}] {}\n", now, record.level(), record.args())
            };

            if let Ok(ref mut logfile) = self.logfile.lock() {
                let _ = logfile.write_all(msg.as_ref());

                if record.level() <= Level::Warn {
                    #[cfg(not(windows))]
                    let env_var = format!("${}", ALACRITTY_LOG_ENV);
                    #[cfg(windows)]
                    let env_var = format!("%{}%", ALACRITTY_LOG_ENV);

                    let msg = format!(
                        "[{}] See log at {} ({}):\n{}",
                        record.level(),
                        logfile.path.to_string_lossy(),
                        env_var,
                        record.args(),
                    );
                    let color = match record.level() {
                        Level::Error => color::RED,
                        Level::Warn => color::YELLOW,
                        _ => unreachable!(),
                    };

                    if let Ok(event_proxy) = self.event_proxy.lock() {
                        let mut message = Message::new(msg, color);
                        message.set_target(record.target().to_owned());

                        let _ = event_proxy.send_event(Event::Message(message));
                    }
                }
            }

            if let Ok(ref mut stdout) = self.stdout.lock() {
                let _ = stdout.write_all(msg.as_ref());
            }
        }
    }

    fn flush(&self) {}
}

struct OnDemandLogFile {
    file: Option<LineWriter<File>>,
    created: Arc<AtomicBool>,
    path: PathBuf,
}

impl OnDemandLogFile {
    fn new() -> Self {
        let mut path = env::temp_dir();
        path.push(format!("Alacritty-{}.log", process::id()));

        // Set log path as an environment variable
        env::set_var(ALACRITTY_LOG_ENV, path.as_os_str());

        OnDemandLogFile { path, file: None, created: Arc::new(AtomicBool::new(false)) }
    }

    fn file(&mut self) -> Result<&mut LineWriter<File>, io::Error> {
        // Allow to recreate the file if it has been deleted at runtime
        if self.file.is_some() && !self.path.as_path().exists() {
            self.file = None;
        }

        // Create the file if it doesn't exist yet
        if self.file.is_none() {
            let file = OpenOptions::new().append(true).create(true).open(&self.path);

            match file {
                Ok(file) => {
                    self.file = Some(io::LineWriter::new(file));
                    self.created.store(true, Ordering::Relaxed);
                    let _ =
                        writeln!(io::stdout(), "Created log file at \"{}\"", self.path.display());
                },
                Err(e) => {
                    let _ = writeln!(io::stdout(), "Unable to create log file: {}", e);
                    return Err(e);
                },
            }
        }

        Ok(self.file.as_mut().unwrap())
    }

    fn path(&self) -> &PathBuf {
        &self.path
    }
}

impl Write for OnDemandLogFile {
    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
        self.file()?.write(buf)
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        self.file()?.flush()
    }
}
<commit_msg>Add seconds and nanoseconds to log output<commit_after>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! Logging for alacritty.
//!
//! The main executable is supposed to call `initialize()` exactly once during
//! startup. All logging messages are written to stdout, given that their
//! log-level is sufficient for the level configured in `cli::Options`.
use std::env;
use std::fs::{File, OpenOptions};
use std::io::{self, LineWriter, Stdout, Write};
use std::path::PathBuf;
use std::process;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};

use glutin::event_loop::EventLoopProxy;
use log::{self, Level};

use alacritty_terminal::event::Event;
use alacritty_terminal::message_bar::Message;
use alacritty_terminal::term::color;

use crate::cli::Options;

const ALACRITTY_LOG_ENV: &str = "ALACRITTY_LOG";

pub fn initialize(
    options: &Options,
    event_proxy: EventLoopProxy<Event>,
) -> Result<Option<PathBuf>, log::SetLoggerError> {
    log::set_max_level(options.log_level);

    // Use env_logger if RUST_LOG environment variable is defined. Otherwise,
    // use the alacritty-only logger.
    if std::env::var("RUST_LOG").is_ok() {
        env_logger::try_init()?;
        Ok(None)
    } else {
        let logger = Logger::new(event_proxy);
        let path = logger.file_path();
        log::set_boxed_logger(Box::new(logger))?;
        Ok(path)
    }
}

pub struct Logger {
    logfile: Mutex<OnDemandLogFile>,
    stdout: Mutex<LineWriter<Stdout>>,
    event_proxy: Mutex<EventLoopProxy<Event>>,
}

impl Logger {
    fn new(event_proxy: EventLoopProxy<Event>) -> Self {
        let logfile = Mutex::new(OnDemandLogFile::new());
        let stdout = Mutex::new(LineWriter::new(io::stdout()));

        Logger { logfile, stdout, event_proxy: Mutex::new(event_proxy) }
    }

    fn file_path(&self) -> Option<PathBuf> {
        if let Ok(logfile) = self.logfile.lock() {
            Some(logfile.path().clone())
        } else {
            None
        }
    }
}

impl log::Log for Logger {
    fn enabled(&self, metadata: &log::Metadata<'_>) -> bool {
        metadata.level() <= log::max_level()
    }

    fn log(&self, record: &log::Record<'_>) {
        if self.enabled(record.metadata()) && record.target().starts_with("alacritty") {
            let now = time::strftime("%F %T.%f", &time::now()).unwrap();

            let msg = if record.level() >= Level::Trace {
                format!(
                    "[{}] [{}] [{}:{}] {}\n",
                    now,
                    record.level(),
                    record.file().unwrap_or("?"),
                    record.line().map(|l| l.to_string()).unwrap_or_else(|| "?".into()),
                    record.args()
                )
            } else {
                format!("[{}] [{}] {}\n", now, record.level(), record.args())
            };

            if let Ok(ref mut logfile) = self.logfile.lock() {
                let _ = logfile.write_all(msg.as_ref());

                if record.level() <= Level::Warn {
                    #[cfg(not(windows))]
                    let env_var = format!("${}", ALACRITTY_LOG_ENV);
                    #[cfg(windows)]
                    let env_var = format!("%{}%", ALACRITTY_LOG_ENV);

                    let msg = format!(
                        "[{}] See log at {} ({}):\n{}",
                        record.level(),
                        logfile.path.to_string_lossy(),
                        env_var,
                        record.args(),
                    );
                    let color = match record.level() {
                        Level::Error => color::RED,
                        Level::Warn => color::YELLOW,
                        _ => unreachable!(),
                    };

                    if let Ok(event_proxy) = self.event_proxy.lock() {
                        let mut message = Message::new(msg, color);
                        message.set_target(record.target().to_owned());

                        let _ = event_proxy.send_event(Event::Message(message));
                    }
                }
            }

            if let Ok(ref mut stdout) = self.stdout.lock() {
                let _ = stdout.write_all(msg.as_ref());
            }
        }
    }

    fn flush(&self) {}
}

struct OnDemandLogFile {
    file: Option<LineWriter<File>>,
    created: Arc<AtomicBool>,
    path: PathBuf,
}

impl OnDemandLogFile {
    fn new() -> Self {
        let mut path = env::temp_dir();
        path.push(format!("Alacritty-{}.log", process::id()));

        // Set log path as an environment variable
        env::set_var(ALACRITTY_LOG_ENV, path.as_os_str());

        OnDemandLogFile { path, file: None, created: Arc::new(AtomicBool::new(false)) }
    }

    fn file(&mut self) -> Result<&mut LineWriter<File>, io::Error> {
        // Allow to recreate the file if it has been deleted at runtime
        if self.file.is_some() && !self.path.as_path().exists() {
            self.file = None;
        }

        // Create the file if it doesn't exist yet
        if self.file.is_none() {
            let file = OpenOptions::new().append(true).create(true).open(&self.path);

            match file {
                Ok(file) => {
                    self.file = Some(io::LineWriter::new(file));
                    self.created.store(true, Ordering::Relaxed);
                    let _ =
                        writeln!(io::stdout(), "Created log file at \"{}\"", self.path.display());
                },
                Err(e) => {
                    let _ = writeln!(io::stdout(), "Unable to create log file: {}", e);
                    return Err(e);
                },
            }
        }

        Ok(self.file.as_mut().unwrap())
    }

    fn path(&self) -> &PathBuf {
        &self.path
    }
}

impl Write for OnDemandLogFile {
    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
        self.file()?.write(buf)
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        self.file()?.flush()
    }
}
<|endoftext|>


<commit_before>
extern crate ndarray;
#[macro_use]
extern crate ndarray_linalg;

use ndarray::*;
use ndarray_linalg::prelude::*;

fn test1d<A, Sa, Sb, Tol>(uplo: UPLO, a: ArrayBase<Sa, Ix2>, b: ArrayBase<Sb, Ix1>, tol: Tol)
    where A: Field + Absolute<Output = Tol>,
          Sa: Data<Elem = A>,
          Sb: DataMut<Elem = A> + DataOwned,
          Tol: RealField
{
    println!("a = {:?}", &a);
    println!("b = {:?}", &b);
    let x = a.solve_triangular(uplo, Diag::NonUnit, &b).unwrap();
    println!("x = {:?}", &x);
    let b_ = a.dot(&x);
    println!("Ax = {:?}", &b_);
    assert_close_l2!(&b_, &b, tol);
}

fn test2d<A, Sa, Sb, Tol>(uplo: UPLO, a: ArrayBase<Sa, Ix2>, b: ArrayBase<Sb, Ix2>, tol: Tol)
    where A: Field + Absolute<Output = Tol>,
          Sa: Data<Elem = A>,
          Sb: DataMut<Elem = A> + DataOwned + DataClone,
          Tol: RealField
{
    println!("a = {:?}", &a);
    println!("b = {:?}", &b);
    let ans = b.clone();
    let x = a.solve_triangular(uplo, Diag::NonUnit, b).unwrap();
    println!("x = {:?}", &x);
    let b_ = a.dot(&x);
    println!("Ax = {:?}", &b_);
    println!("A^Tx = {:?}", a.t().dot(&x));
    println!("Ax^T = {:?}", a.dot(&x.t()));
    println!("(Ax^T)^T = {:?}", a.dot(&x.t()).t());
    assert_close_l2!(&b_, &ans, tol);
}

#[test]
fn triangular_1d_upper() {
    let n = 3;
    let b: Array1<f64> = random_vector(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Upper);
    test1d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_1d_lower() {
    let n = 3;
    let b: Array1<f64> = random_vector(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Lower);
    test1d(UPLO::Lower, a, b, 1e-7);
}

#[test]
fn triangular_1d_lower_t() {
    let n = 3;
    let b: Array1<f64> = random_vector(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Lower).reversed_axes();
    test1d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_1d_upper_t() {
    let n = 3;
    let b: Array1<f64> = random_vector(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Upper).reversed_axes();
    test1d(UPLO::Lower, a, b, 1e-7);
}

#[test]
fn triangular_2d_upper() {
    let n = 3;
    let b: Array2<f64> = random_square(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Upper);
    test2d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_2d_lower() {
    let n = 3;
    let b: Array2<f64> = random_square(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Lower);
    test2d(UPLO::Lower, a, b, 1e-7);
}

#[test]
fn triangular_2d_lower_t() {
    let n = 3;
    let b: Array2<f64> = random_square(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Lower).reversed_axes();
    test2d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_2d_upper_t() {
    let n = 3;
    let b: Array2<f64> = random_square(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Upper).reversed_axes();
    test2d(UPLO::Lower, a, b, 1e-7);
}

#[test]
fn triangular_2d_upper_bt() {
    let n = 3;
    let b: Array2<f64> = random_square(n).reversed_axes();
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Upper);
    test2d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_2d_lower_bt() {
    let n = 3;
    let b: Array2<f64> = random_square(n).reversed_axes();
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Lower);
    test2d(UPLO::Lower, a, b, 1e-7);
}

#[test]
fn triangular_2d_lower_t_bt() {
    let n = 3;
    let b: Array2<f64> = random_square(n).reversed_axes();
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Lower).reversed_axes();
    test2d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_2d_upper_t_bt() {
    let n = 3;
    let b: Array2<f64> = random_square(n).reversed_axes();
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Upper).reversed_axes();
    test2d(UPLO::Lower, a, b, 1e-7);
}
<commit_msg>Update test for non-square b<commit_after>
extern crate ndarray;
#[macro_use]
extern crate ndarray_linalg;

use ndarray::*;
use ndarray_linalg::prelude::*;

fn test1d<A, Sa, Sb, Tol>(uplo: UPLO, a: ArrayBase<Sa, Ix2>, b: ArrayBase<Sb, Ix1>, tol: Tol)
    where A: Field + Absolute<Output = Tol>,
          Sa: Data<Elem = A>,
          Sb: DataMut<Elem = A> + DataOwned,
          Tol: RealField
{
    println!("a = {:?}", &a);
    println!("b = {:?}", &b);
    let x = a.solve_triangular(uplo, Diag::NonUnit, &b).unwrap();
    println!("x = {:?}", &x);
    let b_ = a.dot(&x);
    println!("Ax = {:?}", &b_);
    assert_close_l2!(&b_, &b, tol);
}

fn test2d<A, Sa, Sb, Tol>(uplo: UPLO, a: ArrayBase<Sa, Ix2>, b: ArrayBase<Sb, Ix2>, tol: Tol)
    where A: Field + Absolute<Output = Tol>,
          Sa: Data<Elem = A>,
          Sb: DataMut<Elem = A> + DataOwned + DataClone,
          Tol: RealField
{
    println!("a = {:?}", &a);
    println!("b = {:?}", &b);
    let ans = b.clone();
    let x = a.solve_triangular(uplo, Diag::NonUnit, b).unwrap();
    println!("x = {:?}", &x);
    let b_ = a.dot(&x);
    println!("Ax = {:?}", &b_);
    assert_close_l2!(&b_, &ans, tol);
}

#[test]
fn triangular_1d_upper() {
    let n = 3;
    let b: Array1<f64> = random_vector(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Upper);
    test1d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_1d_lower() {
    let n = 3;
    let b: Array1<f64> = random_vector(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Lower);
    test1d(UPLO::Lower, a, b, 1e-7);
}

#[test]
fn triangular_1d_lower_t() {
    let n = 3;
    let b: Array1<f64> = random_vector(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Lower).reversed_axes();
    test1d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_1d_upper_t() {
    let n = 3;
    let b: Array1<f64> = random_vector(n);
    let a: Array2<f64> = random_square(n).into_triangular(UPLO::Upper).reversed_axes();
    test1d(UPLO::Lower, a, b, 1e-7);
}

#[test]
fn triangular_2d_upper() {
    let b: Array2<f64> = random_matrix(3, 4);
    let a: Array2<f64> = random_square(3).into_triangular(UPLO::Upper);
    test2d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_2d_lower() {
    let b: Array2<f64> = random_matrix(3, 4);
    let a: Array2<f64> = random_square(3).into_triangular(UPLO::Lower);
    test2d(UPLO::Lower, a, b, 1e-7);
}

#[test]
fn triangular_2d_lower_t() {
    let b: Array2<f64> = random_matrix(3, 4);
    let a: Array2<f64> = random_square(3).into_triangular(UPLO::Lower).reversed_axes();
    test2d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_2d_upper_t() {
    let b: Array2<f64> = random_matrix(3, 4);
    let a: Array2<f64> = random_square(3).into_triangular(UPLO::Upper).reversed_axes();
    test2d(UPLO::Lower, a, b, 1e-7);
}

#[test]
fn triangular_2d_upper_bt() {
    let b: Array2<f64> = random_matrix(4, 3).reversed_axes();
    let a: Array2<f64> = random_square(3).into_triangular(UPLO::Upper);
    test2d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_2d_lower_bt() {
    let b: Array2<f64> = random_matrix(4, 3).reversed_axes();
    let a: Array2<f64> = random_square(3).into_triangular(UPLO::Lower);
    test2d(UPLO::Lower, a, b, 1e-7);
}

#[test]
fn triangular_2d_lower_t_bt() {
    let b: Array2<f64> = random_matrix(4, 3).reversed_axes();
    let a: Array2<f64> = random_square(3).into_triangular(UPLO::Lower).reversed_axes();
    test2d(UPLO::Upper, a, b, 1e-7);
}

#[test]
fn triangular_2d_upper_t_bt() {
    let b: Array2<f64> = random_matrix(4, 3).reversed_axes();
    let a: Array2<f64> = random_square(3).into_triangular(UPLO::Upper).reversed_axes();
    test2d(UPLO::Lower, a, b, 1e-7);
}
<|endoftext|>


<commit_before>pub mod details;
pub mod instruments;
pub mod summary;

use serde_json;

use client::Client;
use self::details::AccountDetails;
use self::details::Details;
use self::summary::AccountSummary;
use self::summary::Summary;
use self::instruments::AccountInstruments;
use self::instruments::Instrument;

fn none() -> Option<&'static Client<'static>> { None }

#[derive(Deserialize)]
pub struct Accounts<'a> {
    pub accounts: Vec<Account<'a>>
}

#[derive(Deserialize)]
pub struct Account<'a> {
    pub id: String,
    pub tags: Vec<String>,
    #[serde(default = "none")]
    #[serde(skip_deserializing)]
    pub client: Option<&'a Client<'a>>
}

impl <'a>Account<'a> {
    pub fn details(&self) -> Details {
        let input = self.client().get(format!("accounts/{}", self.id).as_str());
        let result: AccountDetails = serde_json::from_str(&input).unwrap();

        result.account
    }

    pub fn instruments(&self) -> Vec<Instrument> {
        let input = self.client().get(
            format!("accounts/{}/instruments", self.id).as_str()
        );
        let result: AccountInstruments = serde_json::from_str(&input).unwrap();

        result.instruments
    }

    pub fn summary(&self) -> Summary {
        let input = self.client().get(
            format!("accounts/{}/summary", self.id).as_str()
        );
        let result: AccountSummary = serde_json::from_str(&input).unwrap();

        result.account
    }

    fn client(&self) -> &'a Client<'a> {
        self.client.expect("Account cannot refer to a client")
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::env;

    // # TODO: Move integration tests to `tests/`
    #[test]
    fn it_can_read_account_details() {
        let url = env::var("OANDA_API_URL").unwrap();
        let key = env::var("OANDA_API_KEY").unwrap();
        let account_id = env::var("OANDA_TEST_ACCOUNT_ID").unwrap();

        let client = Client::new(&url, &key);
        let accounts = client.accounts();

        let account = accounts.first().unwrap().clone();
        let details = account.details();

        assert_eq!(details.alias.unwrap(), "Testv20")
    }

    #[test]
    fn it_can_read_account_summary() {
        let url = env::var("OANDA_API_URL").unwrap();
        let key = env::var("OANDA_API_KEY").unwrap();
        let account_id = env::var("OANDA_TEST_ACCOUNT_ID").unwrap();

        let client = Client::new(&url, &key);
        let accounts = client.accounts();

        let account = accounts.first().unwrap().clone();
        let summary = account.summary();

        assert_eq!(summary.alias.unwrap(), "Testv20")
    }

    #[test]
    fn it_can_read_account_instruments() {
        let url = env::var("OANDA_API_URL").unwrap();
        let key = env::var("OANDA_API_KEY").unwrap();
        let account_id = env::var("OANDA_TEST_ACCOUNT_ID").unwrap();

        let client = Client::new(&url, &key);
        let accounts = client.accounts();

        let account = accounts.first().unwrap().clone();
        let instruments = account.instruments();
        // DKK just hapepns to the be the first one, the result here is a list
        // of all USD_* tradable currencies because the test account is USD
        assert_eq!(instruments.first().unwrap().name, "USD_DKK")
    }
}
<commit_msg>Make the instruments test more robust<commit_after>pub mod details;
pub mod instruments;
pub mod summary;

use serde_json;

use client::Client;
use self::details::AccountDetails;
use self::details::Details;
use self::summary::AccountSummary;
use self::summary::Summary;
use self::instruments::AccountInstruments;
use self::instruments::Instrument;

fn none() -> Option<&'static Client<'static>> { None }

#[derive(Deserialize)]
pub struct Accounts<'a> {
    pub accounts: Vec<Account<'a>>
}

#[derive(Deserialize)]
pub struct Account<'a> {
    pub id: String,
    pub tags: Vec<String>,
    #[serde(default = "none")]
    #[serde(skip_deserializing)]
    pub client: Option<&'a Client<'a>>
}

impl <'a>Account<'a> {
    pub fn details(&self) -> Details {
        let input = self.client().get(format!("accounts/{}", self.id).as_str());
        let result: AccountDetails = serde_json::from_str(&input).unwrap();

        result.account
    }

    pub fn instruments(&self) -> Vec<Instrument> {
        let input = self.client().get(
            format!("accounts/{}/instruments", self.id).as_str()
        );
        let result: AccountInstruments = serde_json::from_str(&input).unwrap();

        result.instruments
    }

    pub fn summary(&self) -> Summary {
        let input = self.client().get(
            format!("accounts/{}/summary", self.id).as_str()
        );
        let result: AccountSummary = serde_json::from_str(&input).unwrap();

        result.account
    }

    fn client(&self) -> &'a Client<'a> {
        self.client.expect("Account cannot refer to a client")
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::env;

    // # TODO: Move integration tests to `tests/`
    #[test]
    fn it_can_read_account_details() {
        let url = env::var("OANDA_API_URL").unwrap();
        let key = env::var("OANDA_API_KEY").unwrap();
        let account_id = env::var("OANDA_TEST_ACCOUNT_ID").unwrap();

        let client = Client::new(&url, &key);
        let accounts = client.accounts();

        let account = accounts.first().unwrap().clone();
        let details = account.details();

        assert_eq!(details.alias.unwrap(), "Testv20")
    }

    #[test]
    fn it_can_read_account_summary() {
        let url = env::var("OANDA_API_URL").unwrap();
        let key = env::var("OANDA_API_KEY").unwrap();
        let account_id = env::var("OANDA_TEST_ACCOUNT_ID").unwrap();

        let client = Client::new(&url, &key);
        let accounts = client.accounts();

        let account = accounts.first().unwrap().clone();
        let summary = account.summary();

        assert_eq!(summary.alias.unwrap(), "Testv20")
    }

    #[test]
    fn it_can_read_account_instruments() {
        let url = env::var("OANDA_API_URL").unwrap();
        let key = env::var("OANDA_API_KEY").unwrap();
        let account_id = env::var("OANDA_TEST_ACCOUNT_ID").unwrap();

        let client = Client::new(&url, &key);
        let accounts = client.accounts();

        let account = accounts.first().unwrap().clone();
        let instruments = account.instruments();
        // the result here is a list of all USD_* tradable currencies because
        // the test account is USD, just make sure we find one we "expect"
        assert_eq!(
            instruments.into_iter().any(|x| x.name == "USD_DKK"), true
        )
    }
}
<|endoftext|>


<commit_before>extern crate timely;
extern crate differential_dataflow;
use differential_dataflow::trace::implementations::ord::OrdValSpine;
use differential_dataflow::trace::{Trace, TraceReader, Batch, Batcher};
use differential_dataflow::trace::cursor::CursorDebug;
// use differential_dataflow::operators::ValueHistory2;
use differential_dataflow::hashable::UnsignedWrapper;

type IntegerTrace = OrdValSpine<UnsignedWrapper<u64>, u64, usize, i64>;

fn get_trace() -> differential_dataflow::trace::implementations::spine::Spine<differential_dataflow::hashable::UnsignedWrapper<u64>, u64, usize, i64, differential_dataflow::trace::implementations::ord::OrdValBatch<differential_dataflow::hashable::UnsignedWrapper<u64>, u64, usize, i64>> {
    let mut trace = IntegerTrace::new();
    {
        let mut batcher = <<
            IntegerTrace as TraceReader<UnsignedWrapper<u64>, u64, usize, i64>>::Batch as Batch<
            UnsignedWrapper<u64>, u64, usize, i64>>::Batcher::new();

        batcher.push_batch(&mut vec![
            ((1.into(), 2), 0, 1),
            ((2.into(), 3), 1, 1),
            ((2.into(), 3), 2, -1),
        ]);

        let batch_ts = &[1, 2, 3];
        let batches = batch_ts.iter().map(move |i| batcher.seal(&[*i]));
        for b in batches {
            trace.insert(b);
        }
    }
    trace
}

#[test]
fn test_trace() {
    let mut trace = get_trace();

    let vec_1 = trace.cursor_through(&[1]).unwrap().to_vec();
    assert_eq!(vec_1, vec![((1.into(), 2), vec![(0, 1)])]);

    let vec_2 = trace.cursor_through(&[2]).unwrap().to_vec();

    println!("--> {:?}", vec_2);
    assert_eq!(vec_2, vec![
               ((1.into(), 2), vec![(0, 1)]),
               ((2.into(), 3), vec![(1, 1)]),
    ]);

    let vec_3 = trace.cursor_through(&[3]).unwrap().to_vec();
    assert_eq!(vec_3, vec![
               ((1.into(), 2), vec![(0, 1)]),
               ((2.into(), 3), vec![(1, 1), (2, -1)]),
    ]);

    let vec_4 = trace.cursor().to_vec();
    assert_eq!(vec_4, vec_3);
}

#[test]
fn test_advance() {
    let mut trace = get_trace();

    trace.advance_by(&[2]);
    trace.distinguish_since(&[2]);

    assert_eq!(
        trace.cursor_through(&[2]).unwrap().to_vec(),
        vec![((1.into(), 2), vec![(2, 1)]), ((2.into(), 3), vec![(2, 1)])]);

    trace.distinguish_since(&[3]);

    assert_eq!(
        trace.cursor_through(&[3]).unwrap().to_vec(),
        vec![((1.into(), 2), vec![(2, 1)]), ((2.into(), 3), vec![(2, 1), (2, -1)])]);
}
<commit_msg>fix trace test<commit_after>extern crate timely;
extern crate differential_dataflow;

use std::rc::Rc;

use differential_dataflow::trace::implementations::ord::OrdValSpine;
use differential_dataflow::trace::{Trace, TraceReader, Batch, Batcher};
use differential_dataflow::trace::cursor::CursorDebug;
use differential_dataflow::hashable::UnsignedWrapper;

use differential_dataflow::trace::implementations::ord::OrdValBatch;
use differential_dataflow::trace::implementations::spine::Spine;

type IntegerTrace = OrdValSpine<UnsignedWrapper<u64>, u64, usize, i64>;

fn get_trace() -> Spine<UnsignedWrapper<u64>, u64, usize, i64, Rc<OrdValBatch<UnsignedWrapper<u64>, u64, usize, i64>>> {
    let mut trace = IntegerTrace::new();
    {
        let mut batcher = <<
            IntegerTrace as TraceReader<UnsignedWrapper<u64>, u64, usize, i64>>::Batch as Batch<
            UnsignedWrapper<u64>, u64, usize, i64>>::Batcher::new();

        batcher.push_batch(&mut vec![
            ((1.into(), 2), 0, 1),
            ((2.into(), 3), 1, 1),
            ((2.into(), 3), 2, -1),
        ]);

        let batch_ts = &[1, 2, 3];
        let batches = batch_ts.iter().map(move |i| batcher.seal(&[*i]));
        for b in batches {
            trace.insert(b);
        }
    }
    trace
}

#[test]
fn test_trace() {
    let mut trace = get_trace();

    let vec_1 = trace.cursor_through(&[1]).unwrap().to_vec();
    assert_eq!(vec_1, vec![((1.into(), 2), vec![(0, 1)])]);

    let vec_2 = trace.cursor_through(&[2]).unwrap().to_vec();

    println!("--> {:?}", vec_2);
    assert_eq!(vec_2, vec![
               ((1.into(), 2), vec![(0, 1)]),
               ((2.into(), 3), vec![(1, 1)]),
    ]);

    let vec_3 = trace.cursor_through(&[3]).unwrap().to_vec();
    assert_eq!(vec_3, vec![
               ((1.into(), 2), vec![(0, 1)]),
               ((2.into(), 3), vec![(1, 1), (2, -1)]),
    ]);

    let vec_4 = trace.cursor().to_vec();
    assert_eq!(vec_4, vec_3);
}

#[test]
fn test_advance() {
    let mut trace = get_trace();

    trace.advance_by(&[2]);
    trace.distinguish_since(&[2]);

    assert_eq!(
        trace.cursor_through(&[2]).unwrap().to_vec(),
        vec![((1.into(), 2), vec![(2, 1)]), ((2.into(), 3), vec![(2, 1)])]);

    trace.distinguish_since(&[3]);

    assert_eq!(
        trace.cursor_through(&[3]).unwrap().to_vec(),
        vec![((1.into(), 2), vec![(2, 1)]), ((2.into(), 3), vec![(2, 1), (2, -1)])]);
}
<|endoftext|>


<commit_before>//! Cipher defined with Ring

use ring::{
    aead::{
        Aad,
        Algorithm,
        Nonce,
        NonceSequence,
        OpeningKey,
        SealingKey,
        UnboundKey,
        AES_128_GCM,
        AES_256_GCM,
        CHACHA20_POLY1305,
        NONCE_LEN,
    },
    error::Unspecified,
};

use crate::crypto::{
    aead::{increase_nonce, make_skey},
    cipher::Error,
    AeadDecryptor,
    AeadEncryptor,
    CipherResult,
    CipherType,
};

use byte_string::ByteStr;
use bytes::{BufMut, BytesMut};
use log::error;

/// AEAD ciphers provided by Ring
pub enum RingAeadCryptoVariant {
    Seal(SealingKey<RingAeadNonceSequence>),
    Open(OpeningKey<RingAeadNonceSequence>),
}

pub struct RingAeadNonceSequence {
    nonce: [u8; NONCE_LEN],
}

impl RingAeadNonceSequence {
    fn new() -> RingAeadNonceSequence {
        RingAeadNonceSequence {
            nonce: [0u8; NONCE_LEN],
        }
    }
}

impl NonceSequence for RingAeadNonceSequence {
    fn advance(&mut self) -> Result<Nonce, Unspecified> {
        let nonce = Nonce::assume_unique_for_key(self.nonce);
        increase_nonce(&mut self.nonce);
        Ok(nonce)
    }
}

/// AEAD Cipher context
///
/// According to SIP004, the `nonce` has to incr 1 after each encrypt/decrypt.
pub struct RingAeadCipher {
    cipher: RingAeadCryptoVariant,
    cipher_type: CipherType,
}

impl RingAeadCipher {
    /// Initialize context
    pub fn new(t: CipherType, key: &[u8], salt: &[u8], is_seal: bool) -> RingAeadCipher {
        // TODO: Check if salt is duplicated

        // Nonce is 12 bytes
        assert_eq!(t.iv_size(), NONCE_LEN);

        let skey = make_skey(t, key, salt);
        let cipher = RingAeadCipher::new_variant(t, &skey, is_seal);
        RingAeadCipher { cipher, cipher_type: t }
    }

    fn new_variant(t: CipherType, key: &[u8], is_seal: bool) -> RingAeadCryptoVariant {
        match t {
            CipherType::Aes128Gcm => RingAeadCipher::new_crypt(&AES_128_GCM, key, is_seal),
            CipherType::Aes256Gcm => RingAeadCipher::new_crypt(&AES_256_GCM, key, is_seal),
            CipherType::ChaCha20IetfPoly1305 => RingAeadCipher::new_crypt(&CHACHA20_POLY1305, key, is_seal),
            _ => panic!("unsupported cipher in ring {:?}", t),
        }
    }

    #[inline]
    fn new_crypt(algorithm: &'static Algorithm, key: &[u8], is_seal: bool) -> RingAeadCryptoVariant {
        use ring::aead::BoundKey;

        let unbound_key = UnboundKey::new(algorithm, key).unwrap();

        if is_seal {
            RingAeadCryptoVariant::Seal(SealingKey::new(unbound_key, RingAeadNonceSequence::new()))
        } else {
            RingAeadCryptoVariant::Open(OpeningKey::new(unbound_key, RingAeadNonceSequence::new()))
        }
    }
}

impl AeadEncryptor for RingAeadCipher {
    fn encrypt(&mut self, input: &[u8], output: &mut [u8]) {
        let tag_len = self.cipher_type.tag_size();
        let buf_len = input.len() + tag_len;
        assert_eq!(output.len(), buf_len);

        let mut buf = BytesMut::with_capacity(output.len());
        buf.put_slice(input);

        if let RingAeadCryptoVariant::Seal(ref mut key) = self.cipher {
            key.seal_in_place_append_tag(Aad::empty(), &mut buf).unwrap();
        } else {
            unreachable!("encrypt is called on a non-seal cipher");
        }

        output.copy_from_slice(&buf[..buf_len]);
    }
}

impl AeadDecryptor for RingAeadCipher {
    fn decrypt(&mut self, input: &[u8], output: &mut [u8]) -> CipherResult<()> {
        let tag_len = self.cipher_type.tag_size();
        assert_eq!(output.len() + tag_len, input.len());

        let mut buf = BytesMut::with_capacity(input.len());
        buf.put_slice(input);

        if let RingAeadCryptoVariant::Open(ref mut key) = self.cipher {
            match key.open_in_place(Aad::empty(), &mut buf) {
                Ok(obuf) => {
                    output.copy_from_slice(obuf);
                    Ok(())
                }
                Err(..) => {
                    error!(
                        "AEAD decrypt failed, input={:?}, tag={:?}, opening: {:?}",
                        ByteStr::new(&input[..output.len()]),
                        ByteStr::new(&input[output.len()..]),
                        key,
                    );
                    Err(Error::AeadDecryptFailed)
                }
            }
        } else {
            unreachable!("decrypt is called on a non-open cipher");
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::crypto::CipherType;

    fn test_ring_aead(ct: CipherType) {
        let key = ct.bytes_to_key(b"PassWORD");
        let message = b"message";

        let iv = ct.gen_init_vec();

        let mut enc = RingAeadCipher::new(ct, &key[..], &iv[..], true);

        let mut encrypted_msg = vec![0u8; message.len() + ct.tag_size()];
        enc.encrypt(message, &mut encrypted_msg);

        assert_ne!(message, &encrypted_msg[..]);

        let mut dec = RingAeadCipher::new(ct, &key[..], &iv[..], false);
        let mut decrypted_msg = vec![0u8; message.len()];
        dec.decrypt(&encrypted_msg[..], &mut decrypted_msg).unwrap();

        assert_eq!(&decrypted_msg[..], message);
    }

    #[test]
    fn test_ring_aes128gcm() {
        test_ring_aead(CipherType::Aes128Gcm);
    }

    #[test]
    fn test_ring_aes256gcm() {
        test_ring_aead(CipherType::Aes256Gcm);
    }

    #[test]
    fn test_ring_chacha20poly1305() {
        test_ring_aead(CipherType::ChaCha20IetfPoly1305);
    }
}
<commit_msg>Optimize ring AEAD cipher data copy<commit_after>//! Cipher defined with Ring

use ring::{
    aead::{
        Aad,
        Algorithm,
        Nonce,
        NonceSequence,
        OpeningKey,
        SealingKey,
        UnboundKey,
        AES_128_GCM,
        AES_256_GCM,
        CHACHA20_POLY1305,
        NONCE_LEN,
    },
    error::Unspecified,
};

use crate::crypto::{
    aead::{increase_nonce, make_skey},
    cipher::Error,
    AeadDecryptor,
    AeadEncryptor,
    CipherResult,
    CipherType,
};

use byte_string::ByteStr;
use bytes::{BufMut, BytesMut};
use log::error;

/// AEAD ciphers provided by Ring
pub enum RingAeadCryptoVariant {
    Seal(SealingKey<RingAeadNonceSequence>),
    Open(OpeningKey<RingAeadNonceSequence>),
}

pub struct RingAeadNonceSequence {
    nonce: [u8; NONCE_LEN],
}

impl RingAeadNonceSequence {
    fn new() -> RingAeadNonceSequence {
        RingAeadNonceSequence {
            nonce: [0u8; NONCE_LEN],
        }
    }
}

impl NonceSequence for RingAeadNonceSequence {
    fn advance(&mut self) -> Result<Nonce, Unspecified> {
        let nonce = Nonce::assume_unique_for_key(self.nonce);
        increase_nonce(&mut self.nonce);
        Ok(nonce)
    }
}

/// AEAD Cipher context
///
/// According to SIP004, the `nonce` has to incr 1 after each encrypt/decrypt.
pub struct RingAeadCipher {
    cipher: RingAeadCryptoVariant,
    cipher_type: CipherType,
}

impl RingAeadCipher {
    /// Initialize context
    pub fn new(t: CipherType, key: &[u8], salt: &[u8], is_seal: bool) -> RingAeadCipher {
        // TODO: Check if salt is duplicated

        // Nonce is 12 bytes
        assert_eq!(t.iv_size(), NONCE_LEN);

        let skey = make_skey(t, key, salt);
        let cipher = RingAeadCipher::new_variant(t, &skey, is_seal);
        RingAeadCipher { cipher, cipher_type: t }
    }

    fn new_variant(t: CipherType, key: &[u8], is_seal: bool) -> RingAeadCryptoVariant {
        match t {
            CipherType::Aes128Gcm => RingAeadCipher::new_crypt(&AES_128_GCM, key, is_seal),
            CipherType::Aes256Gcm => RingAeadCipher::new_crypt(&AES_256_GCM, key, is_seal),
            CipherType::ChaCha20IetfPoly1305 => RingAeadCipher::new_crypt(&CHACHA20_POLY1305, key, is_seal),
            _ => panic!("unsupported cipher in ring {:?}", t),
        }
    }

    #[inline]
    fn new_crypt(algorithm: &'static Algorithm, key: &[u8], is_seal: bool) -> RingAeadCryptoVariant {
        use ring::aead::BoundKey;

        let unbound_key = UnboundKey::new(algorithm, key).unwrap();

        if is_seal {
            RingAeadCryptoVariant::Seal(SealingKey::new(unbound_key, RingAeadNonceSequence::new()))
        } else {
            RingAeadCryptoVariant::Open(OpeningKey::new(unbound_key, RingAeadNonceSequence::new()))
        }
    }
}

struct SealBuffer<'a> {
    buffer: &'a mut [u8],
    input_len: usize,
}

impl<'a> AsRef<[u8]> for SealBuffer<'a> {
    fn as_ref(&self) -> &[u8] {
        &self.buffer[..self.input_len]
    }
}

impl<'a> AsMut<[u8]> for SealBuffer<'a> {
    fn as_mut(&mut self) -> &mut [u8] {
        &mut self.buffer[..self.input_len]
    }
}

impl<'a, 'in_out> Extend<&'in_out u8> for SealBuffer<'a> {
    fn extend<T: IntoIterator<Item = &'in_out u8>>(&mut self, iter: T) {
        let mut idx = 0;
        for b in iter {
            self.buffer[self.input_len + idx] = *b;
            idx += 1;
        }
    }
}

impl AeadEncryptor for RingAeadCipher {
    fn encrypt(&mut self, input: &[u8], output: &mut [u8]) {
        let tag_len = self.cipher_type.tag_size();
        let buf_len = input.len() + tag_len;
        assert_eq!(output.len(), buf_len);

        output[..input.len()].copy_from_slice(input);

        let mut buf = SealBuffer {
            buffer: output,
            input_len: input.len(),
        };

        if let RingAeadCryptoVariant::Seal(ref mut key) = self.cipher {
            key.seal_in_place_append_tag(Aad::empty(), &mut buf).unwrap();
        } else {
            unreachable!("encrypt is called on a non-seal cipher");
        }
    }
}

impl AeadDecryptor for RingAeadCipher {
    fn decrypt(&mut self, input: &[u8], output: &mut [u8]) -> CipherResult<()> {
        let tag_len = self.cipher_type.tag_size();
        assert_eq!(output.len() + tag_len, input.len());

        let mut buf = BytesMut::with_capacity(input.len());
        buf.put_slice(input);

        if let RingAeadCryptoVariant::Open(ref mut key) = self.cipher {
            match key.open_in_place(Aad::empty(), &mut buf) {
                Ok(obuf) => {
                    output.copy_from_slice(obuf);
                    Ok(())
                }
                Err(..) => {
                    error!(
                        "AEAD decrypt failed, input={:?}, tag={:?}, opening: {:?}",
                        ByteStr::new(&input[..output.len()]),
                        ByteStr::new(&input[output.len()..]),
                        key,
                    );
                    Err(Error::AeadDecryptFailed)
                }
            }
        } else {
            unreachable!("decrypt is called on a non-open cipher");
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::crypto::CipherType;

    fn test_ring_aead(ct: CipherType) {
        let key = ct.bytes_to_key(b"PassWORD");
        let message = b"message";

        let iv = ct.gen_init_vec();

        let mut enc = RingAeadCipher::new(ct, &key[..], &iv[..], true);

        let mut encrypted_msg = vec![0u8; message.len() + ct.tag_size()];
        enc.encrypt(message, &mut encrypted_msg);

        assert_ne!(message, &encrypted_msg[..]);

        let mut dec = RingAeadCipher::new(ct, &key[..], &iv[..], false);
        let mut decrypted_msg = vec![0u8; message.len()];
        dec.decrypt(&encrypted_msg[..], &mut decrypted_msg).unwrap();

        assert_eq!(&decrypted_msg[..], message);
    }

    #[test]
    fn test_ring_aes128gcm() {
        test_ring_aead(CipherType::Aes128Gcm);
    }

    #[test]
    fn test_ring_aes256gcm() {
        test_ring_aead(CipherType::Aes256Gcm);
    }

    #[test]
    fn test_ring_chacha20poly1305() {
        test_ring_aead(CipherType::ChaCha20IetfPoly1305);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use super::stream::Stream;

#[derive(Debug)]
pub enum DatabaseError {
    TableExists,
}

pub struct Database {
    tables: HashMap<String, Stream>
}

impl Database {
    pub fn new() -> Database {
        Database{
            tables: HashMap::new()
        }
    }

    fn create_stream(&mut self, name: &str) -> Result<(), DatabaseError> {
        let tmp = Stream::new();
        self.tables.insert(name.to_string(), tmp);
        Ok(())
    }

    fn get_table_mut(&mut self, name: &str) -> Option<&mut Stream> {
        self.tables.get_mut(name)
    }
}

#[cfg(test)]
mod tests {
    use super::Database;

    // returns a valid DB for use with testing with valid simple schema
    fn get_db_with_stream() {
        let mut db = Database::new();
        db.create_stream("Jon");

    }

    #[test]
    fn create_table() {
        let mut db = Database::new();
        db.create_stream("Jon");
    }

}
<commit_msg>Ensuring an error is thrown when trying to create a stream that already exists.  Closes #1<commit_after>use std::collections::HashMap;
use super::stream::Stream;

#[derive(Debug, PartialEq)]
pub enum DatabaseError {
    TableExists,
}

pub struct Database {
    tables: HashMap<String, Stream>
}

impl Database {
    pub fn new() -> Database {
        Database{
            tables: HashMap::new()
        }
    }

    fn create_stream(&mut self, name: &str) -> Result<(), DatabaseError> {
        let tmp = Stream::new();
        if self.tables.contains_key(name) {
            return Err(DatabaseError::TableExists);
        }
        self.tables.insert(name.to_string(), tmp);
        Ok(())
    }

    fn get_stream_mut(&mut self, name: &str) -> Option<&mut Stream> {
        self.tables.get_mut(name)
    }
}

#[cfg(test)]
mod tests {
    use super::Database;
    use super::DatabaseError;

    // returns a valid DB for use with testing with valid simple schema
    fn get_db_with_stream() -> Database {
        let mut db = Database::new();
        db.create_stream("Jon");

        db
    }

    #[test]
    fn create_table() {
        let mut db = Database::new();
        db.create_stream("Jon");
    }

    #[test]
    fn create_table_fails_when_table_exists() {
        let mut db = get_db_with_stream();
        if let Err(result) = db.create_stream("Jon") {
            assert_eq!(result, DatabaseError::TableExists);
        } else {
            panic!("Was expecting DatabaseError::TableExists, got an OK");
        }

    }
}
<|endoftext|>


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

pub const DBUS_TIMEOUT: i32 = 20000; // millieconds

pub const STRATIS_VERSION: &'static str = "1";
pub const MANAGER_NAME: &'static str = "/Manager";
pub const STRATIS_BASE_PATH: &'static str = "/org/storage/stratis1";
pub const STRATIS_BASE_SERVICE: &'static str = "org.storage.stratis1";
pub const STRATIS_BASE_MANAGER: &'static str = "/org/storage/stratis1/Manager";
pub const STRATIS_MANAGER_INTERFACE: &'static str = "org.storage.stratis1.Manager";
pub const STRATIS_POOL_BASE_INTERFACE: &'static str = "org.storage.stratis1.pool";
pub const STRATIS_VOLUME_BASE_INTERFACE: &'static str = "org.storage.stratis1.volume";
pub const STRATIS_DEV_BASE_INTERFACE: &'static str = "org.storage.stratis1.dev";
pub const STRATIS_CACHE_BASE_INTERFACE: &'static str = "org.storage.stratis1.cache";
pub const STRATIS_POOL_BASE_PATH: &'static str = "/org/storage/stratis/pool";

pub const LIST_POOLS: &'static str = "ListPools";
pub const CREATE_POOL: &'static str = "CreatePool";
pub const DESTROY_POOL: &'static str = "DestroyPool";
pub const GET_POOL_OBJECT_PATH: &'static str = "GetPoolObjectPath";
pub const GET_VOLUME_OBJECT_PATH: &'static str = "GetVolumeObjectPath";
pub const GET_DEV_OBJECT_PATH: &'static str = "GetDevObjectPath";
pub const GET_CACHE_OBJECT_PATH: &'static str = "GetCacheObjectPath";
pub const GET_ERROR_CODES: &'static str = "GetErrorCodes";
pub const GET_RAID_LEVELS: &'static str = "GetRaidLevels";
pub const GET_DEV_TYPES: &'static str = "GetDevTypes";

pub trait HasCodes {
    /// Indicates that this enum can be converted to an int or described
    /// with a string.
    fn get_error_int(&self) -> u16;
    fn get_error_string(&self) -> &str;
}

custom_derive! {
    #[derive(Copy, Clone, EnumDisplay,
             IterVariants(StratisDBusErrorVariants),
             IterVariantNames(StratisDBusErrorVariantNames))]
    #[allow(non_camel_case_types)]
    pub enum StratisErrorEnum {
        STRATIS_OK,
        STRATIS_ERROR,
        STRATIS_NULL,
        STRATIS_NOTFOUND,
        STRATIS_POOL_NOTFOUND,
        STRATIS_VOLUME_NOTFOUND,
        STRATIS_DEV_NOTFOUND,
        STRATIS_CACHE_NOTFOUND,
        STRATIS_BAD_PARAM,
        STRATIS_ALREADY_EXISTS,
        STRATIS_NULL_NAME,
        STRATIS_NO_POOLS,
        STRATIS_LIST_FAILURE,
    }
}

impl HasCodes for StratisErrorEnum {
    fn get_error_int(&self) -> u16 {
        *self as u16
    }

    fn get_error_string(&self) -> &str {
        match *self {
            // TODO deal with internationalization/do this better
            StratisErrorEnum::STRATIS_OK => "Ok",
            StratisErrorEnum::STRATIS_ERROR => "A general error happened",
            StratisErrorEnum::STRATIS_NULL => "Null parameter was supplied",
            StratisErrorEnum::STRATIS_NOTFOUND => "Not found",
            StratisErrorEnum::STRATIS_POOL_NOTFOUND => "Pool not found",
            StratisErrorEnum::STRATIS_VOLUME_NOTFOUND => "Volume not found",
            StratisErrorEnum::STRATIS_CACHE_NOTFOUND => "Cache not found",
            StratisErrorEnum::STRATIS_BAD_PARAM => "Bad parameter",
            StratisErrorEnum::STRATIS_DEV_NOTFOUND => "Dev not found",
            StratisErrorEnum::STRATIS_ALREADY_EXISTS => "Already exists",
            StratisErrorEnum::STRATIS_NULL_NAME => "Null name supplied",
            StratisErrorEnum::STRATIS_NO_POOLS => "No pools",
            StratisErrorEnum::STRATIS_LIST_FAILURE => "List operation failure.",
        }
    }
}

custom_derive! {
    #[derive(Copy, Clone, EnumDisplay,
             IterVariants(StratisDBusRaidTypeVariants),
             IterVariantNames(StratisDBusRaidTypeVariantNames))]
    #[allow(non_camel_case_types)]
    pub enum StratisRaidType {
        STRATIS_RAID_TYPE_UNKNOWN,
        /** Single */
        STRATIS_RAID_TYPE_SINGLE,
        /** Mirror between two disks. For 4 disks or more, they are RAID10.*/
        STRATIS_RAID_TYPE_RAID1,
        /** Block-level striping with distributed parity */
        STRATIS_RAID_TYPE_RAID5,
        /** Block-level striping with two distributed parities, aka, RAID-DP */
        STRATIS_RAID_TYPE_RAID6,
    }
}

impl HasCodes for StratisRaidType {
    fn get_error_int(&self) -> u16 {
        *self as u16
    }

    fn get_error_string(&self) -> &str {
        match *self {
            StratisRaidType::STRATIS_RAID_TYPE_UNKNOWN => "Ok",
            StratisRaidType::STRATIS_RAID_TYPE_SINGLE => "Single",
            StratisRaidType::STRATIS_RAID_TYPE_RAID1 => {
                "Mirror between two disks. For 4 disks or more, they are RAID10"
            }
            StratisRaidType::STRATIS_RAID_TYPE_RAID5 => {
                "Block-level striping with distributed parity"
            }
            StratisRaidType::STRATIS_RAID_TYPE_RAID6 => {
                "Block-level striping with two distributed parities, aka, RAID-DP"
            }
        }
    }
}
<commit_msg>Specify RAID1 as a mirror<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

pub const DBUS_TIMEOUT: i32 = 20000; // millieconds

pub const STRATIS_VERSION: &'static str = "1";
pub const MANAGER_NAME: &'static str = "/Manager";
pub const STRATIS_BASE_PATH: &'static str = "/org/storage/stratis1";
pub const STRATIS_BASE_SERVICE: &'static str = "org.storage.stratis1";
pub const STRATIS_BASE_MANAGER: &'static str = "/org/storage/stratis1/Manager";
pub const STRATIS_MANAGER_INTERFACE: &'static str = "org.storage.stratis1.Manager";
pub const STRATIS_POOL_BASE_INTERFACE: &'static str = "org.storage.stratis1.pool";
pub const STRATIS_VOLUME_BASE_INTERFACE: &'static str = "org.storage.stratis1.volume";
pub const STRATIS_DEV_BASE_INTERFACE: &'static str = "org.storage.stratis1.dev";
pub const STRATIS_CACHE_BASE_INTERFACE: &'static str = "org.storage.stratis1.cache";
pub const STRATIS_POOL_BASE_PATH: &'static str = "/org/storage/stratis/pool";

pub const LIST_POOLS: &'static str = "ListPools";
pub const CREATE_POOL: &'static str = "CreatePool";
pub const DESTROY_POOL: &'static str = "DestroyPool";
pub const GET_POOL_OBJECT_PATH: &'static str = "GetPoolObjectPath";
pub const GET_VOLUME_OBJECT_PATH: &'static str = "GetVolumeObjectPath";
pub const GET_DEV_OBJECT_PATH: &'static str = "GetDevObjectPath";
pub const GET_CACHE_OBJECT_PATH: &'static str = "GetCacheObjectPath";
pub const GET_ERROR_CODES: &'static str = "GetErrorCodes";
pub const GET_RAID_LEVELS: &'static str = "GetRaidLevels";
pub const GET_DEV_TYPES: &'static str = "GetDevTypes";

pub trait HasCodes {
    /// Indicates that this enum can be converted to an int or described
    /// with a string.
    fn get_error_int(&self) -> u16;
    fn get_error_string(&self) -> &str;
}

custom_derive! {
    #[derive(Copy, Clone, EnumDisplay,
             IterVariants(StratisDBusErrorVariants),
             IterVariantNames(StratisDBusErrorVariantNames))]
    #[allow(non_camel_case_types)]
    pub enum StratisErrorEnum {
        STRATIS_OK,
        STRATIS_ERROR,
        STRATIS_NULL,
        STRATIS_NOTFOUND,
        STRATIS_POOL_NOTFOUND,
        STRATIS_VOLUME_NOTFOUND,
        STRATIS_DEV_NOTFOUND,
        STRATIS_CACHE_NOTFOUND,
        STRATIS_BAD_PARAM,
        STRATIS_ALREADY_EXISTS,
        STRATIS_NULL_NAME,
        STRATIS_NO_POOLS,
        STRATIS_LIST_FAILURE,
    }
}

impl HasCodes for StratisErrorEnum {
    fn get_error_int(&self) -> u16 {
        *self as u16
    }

    fn get_error_string(&self) -> &str {
        match *self {
            // TODO deal with internationalization/do this better
            StratisErrorEnum::STRATIS_OK => "Ok",
            StratisErrorEnum::STRATIS_ERROR => "A general error happened",
            StratisErrorEnum::STRATIS_NULL => "Null parameter was supplied",
            StratisErrorEnum::STRATIS_NOTFOUND => "Not found",
            StratisErrorEnum::STRATIS_POOL_NOTFOUND => "Pool not found",
            StratisErrorEnum::STRATIS_VOLUME_NOTFOUND => "Volume not found",
            StratisErrorEnum::STRATIS_CACHE_NOTFOUND => "Cache not found",
            StratisErrorEnum::STRATIS_BAD_PARAM => "Bad parameter",
            StratisErrorEnum::STRATIS_DEV_NOTFOUND => "Dev not found",
            StratisErrorEnum::STRATIS_ALREADY_EXISTS => "Already exists",
            StratisErrorEnum::STRATIS_NULL_NAME => "Null name supplied",
            StratisErrorEnum::STRATIS_NO_POOLS => "No pools",
            StratisErrorEnum::STRATIS_LIST_FAILURE => "List operation failure.",
        }
    }
}

custom_derive! {
    #[derive(Copy, Clone, EnumDisplay,
             IterVariants(StratisDBusRaidTypeVariants),
             IterVariantNames(StratisDBusRaidTypeVariantNames))]
    #[allow(non_camel_case_types)]
    pub enum StratisRaidType {
        STRATIS_RAID_TYPE_UNKNOWN,
        /** Single */
        STRATIS_RAID_TYPE_SINGLE,
        /** Mirror between two disks. For 4 disks or more, they are RAID10.*/
        STRATIS_RAID_TYPE_RAID1,
        /** Block-level striping with distributed parity */
        STRATIS_RAID_TYPE_RAID5,
        /** Block-level striping with two distributed parities, aka, RAID-DP */
        STRATIS_RAID_TYPE_RAID6,
    }
}

impl HasCodes for StratisRaidType {
    fn get_error_int(&self) -> u16 {
        *self as u16
    }

    fn get_error_string(&self) -> &str {
        match *self {
            StratisRaidType::STRATIS_RAID_TYPE_UNKNOWN => "Ok",
            StratisRaidType::STRATIS_RAID_TYPE_SINGLE => "Single",
            StratisRaidType::STRATIS_RAID_TYPE_RAID1 => "Mirrored",
            StratisRaidType::STRATIS_RAID_TYPE_RAID5 => {
                "Block-level striping with distributed parity"
            }
            StratisRaidType::STRATIS_RAID_TYPE_RAID6 => {
                "Block-level striping with two distributed parities"
            }
        }
    }
}
<|endoftext|>


<commit_before>use random::Random;

pub trait Environment {
  fn num_actions(&self) -> i16;
  fn reward(&self) -> f64;
  fn observation(&self) -> i16;

  fn update(&mut self, action: i16);
}

pub struct CoinFlip {
  last_toss: i16,
  last_guess: i16,
  random: Box<Random>,
}

impl CoinFlip {
  pub fn new(random: Box<Random>) -> CoinFlip {
    CoinFlip {
      last_toss: 0,   // tails

      // TODO(dinowernli): Add an enum for guesses for either
      // HEADS, TAILS. or INVALID.
      last_guess: -1,
      random: random,
    }
  }
}

impl Environment for CoinFlip {
  fn num_actions(&self) -> i16 {
    return 2;
  }

  fn reward(&self) -> f64 {
    return if self.last_guess == self.last_toss { 1.0 } else { 0.0 };
  }

  fn observation(&self) -> i16 {
    return self.last_toss;
  }

  fn update(&mut self, action: i16) {
    self.last_guess = match action {
      0 => 0,
      1 => 1,
      _ => -1,  // Invalid.
    };

    // Just alternate heads and tails for now.
    self.last_toss = self.random.next_modulo(2) as i16;
  }
}
<commit_msg>Use enums instead of int to encode coin toss results.<commit_after>use random::Random;

pub trait Environment {
  fn num_actions(&self) -> i16;
  fn reward(&self) -> f64;
  fn observation(&self) -> i16;

  fn update(&mut self, action: i16);
}

pub struct CoinFlip {
  last_toss: CoinToss,
  last_guess: Option<CoinToss>,
  random: Box<Random>,
}

#[derive(Copy, Clone, Debug, PartialEq)]
enum CoinToss {
  Heads,
  Tails,
}

impl CoinFlip {
  pub fn new(random: Box<Random>) -> CoinFlip {
    CoinFlip {
      last_toss: CoinToss::Tails,
      last_guess: None,
      random: random,
    }
  }
}

impl Environment for CoinFlip {
  fn num_actions(&self) -> i16 {
    return 2;
  }

  fn reward(&self) -> f64 {
    match self.last_guess  {
      Some(val) => if val == self.last_toss { 11.0 } else { 10.0 },
      _ => 0.0,
    }
  }

  fn observation(&self) -> i16 {
    match self.last_toss  {
      CoinToss::Heads => 0,
      CoinToss::Tails => 1,
    }
  }

  fn update(&mut self, action: i16) {
    self.last_guess = match action {
      0 => Some(CoinToss::Heads),
      1 => Some(CoinToss::Tails),
      _ => None,
    };

    // Just alternate heads and tails for now.
    let r = self.random.next_modulo(2);
    self.last_toss = if r == 1 { CoinToss::Heads } else { CoinToss::Tails};
  }
}
<|endoftext|>


<commit_before>use sfml::graphics::Color;

pub static black : Color =  Color { red: 34, green: 34, blue: 34, alpha: 255 };
pub static gray : Color = Color {red: 94, green: 102, blue: 105, alpha: 255 };
pub static navy : Color = Color {red:75, green: 62, blue: 77, alpha: 255 };
pub static blue : Color = Color { red: 30, green: 140, blue: 147, alpha: 255 };
pub static orange : Color = Color { red: 215, green: 79, blue: 51, alpha: 255 };
pub static red : Color = Color { red: 204, green: 51, blue: 63, alpha: 255 };
pub static green : Color = Color { red: 86, green: 205, blue: 38, alpha: 255 };
pub static dark_green : Color = Color { red: 54, green: 171, blue: 138, alpha: 255 };
pub static yellow : Color = Color { red: 222, green: 239, blue: 187, alpha: 255 };
pub static white : Color = Color { red: 250, green: 250, blue: 250, alpha: 255 };
pub static invisible : Color = Color { red: 0, green: 0, blue: 0, alpha: 0 };
<commit_msg>Fix color struct names<commit_after>use sfml::graphics::Color;

pub static black : Color =  Color { r: 34, g: 34, b: 34, a: 255 };
pub static gray : Color = Color {r: 94, g: 102, b: 105, a: 255 };
pub static navy : Color = Color {r:75, g: 62, b: 77, a: 255 };
pub static blue : Color = Color { r: 30, g: 140, b: 147, a: 255 };
pub static orange : Color = Color { r: 215, g: 79, b: 51, a: 255 };
pub static red : Color = Color { r: 204, g: 51, b: 63, a: 255 };
pub static green : Color = Color { r: 86, g: 205, b: 38, a: 255 };
pub static dark_green : Color = Color { r: 54, g: 171, b: 138, a: 255 };
pub static yellow : Color = Color { r: 222, g: 239, b: 187, a: 255 };
pub static white : Color = Color { r: 250, g: 250, b: 250, a: 255 };
pub static invisible : Color = Color { r: 0, g: 0, b: 0, a: 0 };
<|endoftext|>