<commit_before>use std::cmp::max;

use vec::Vec2;
use view::View;
use printer::Printer;
use align::*;
use event::*;
use super::scroll::ScrollBase;

use unicode_width::UnicodeWidthStr;
use unicode_segmentation::UnicodeSegmentation;

/// A simple view showing a fixed text
pub struct TextView {
    content: String,
    rows: Vec<Row>,

    align: Align,

    // ScrollBase make many scrolling-related things easier
    scrollbase: ScrollBase,
    last_size: Option<Vec2>,
    width: Option<usize>,
}

// Subset of the main content representing a row on the display.
struct Row {
    start: usize,
    end: usize,
    width: usize,
}

// If the last character is a newline, strip it.
fn strip_last_newline(content: &str) -> &str {
    if !content.is_empty() && content.chars().last().unwrap() == '\n' {
        &content[..content.len() - 1]
    } else {
        content
    }
}

/// Returns the number of lines required to display the given text with the
/// specified maximum line width.
fn get_line_span(line: &str, max_width: usize) -> usize {
    // TODO: this method is stupid. Look at LinesIterator and do the same
    // (Or use a common function? Better!)
    let mut lines = 1;
    let mut length = 0;
    for l in line.split(' ').map(|word| word.width()) {
        length += l;
        if length > max_width {
            length = l;
            lines += 1;
        }
        length += 1;
    }
    lines
}

impl TextView {
    /// Creates a new TextView with the given content.
    pub fn new(content: &str) -> Self {
        let content = strip_last_newline(content);
        TextView {
            content: content.to_string(),
            rows: Vec::new(),
            scrollbase: ScrollBase::new(),
            align: Align::top_left(),
            last_size: None,
            width: None,
        }
    }

    /// Sets the horizontal alignment for this view.
    pub fn h_align(mut self, h: HAlign) -> Self {
        self.align.h = h;

        self
    }

    /// Sets the vertical alignment for this view.
    pub fn v_align(mut self, v: VAlign) -> Self {
        self.align.v = v;

        self
    }

    /// Sets the alignment for this view.
    pub fn align(mut self, a: Align) -> Self {
        self.align = a;

        self
    }

    /// Replace the text in this view.
    pub fn set_content(&mut self, content: &str) {
        let content = strip_last_newline(content);
        self.content = content.to_string();
    }

    /// Returns the current text in this view.
    pub fn get_content(&self) -> &str {
        &self.content
    }

    /// Returns the number of lines required to display the content
    /// with the given width.
    fn get_num_lines(&self, max_width: usize) -> usize {
        self.content
            .split('\n')
            .map(|line| get_line_span(line, max_width))
            .fold(0, |sum, x| sum + x)
    }

    // In the absence of any constraint, what size would we like?
    fn get_ideal_size(&self) -> Vec2 {
        let mut max_width = 0;
        let mut height = 0;

        for line in self.content.split('\n') {
            height += 1;
            max_width = max(max_width, line.width());
        }

        Vec2::new(max_width, height)
    }

    fn is_cache_valid(&self, size: Vec2) -> bool {
        match self.last_size {
            None => false,
            Some(last) => if last.x != size.x {
                false
            } else {
                (last.y < self.rows.len()) == (size.y < self.rows.len())
            },
        }
    }

    fn compute_rows(&mut self, size: Vec2) {
        if !self.is_cache_valid(size) {
            // Recompute
            self.rows = LinesIterator::new(&self.content, size.x).collect();
            let mut scrollbar = 0;
            if self.rows.len() > size.y {
                scrollbar = 2;
                // If we're too high, include a scrollbar
                self.rows = LinesIterator::new(&self.content, size.x - scrollbar)
                    .collect();
            }

            self.width = self.rows.iter().map(|row| row.width).max().map(|w| w + scrollbar);

            self.last_size = Some(size);
        }
    }
}

// Given a multiline string, and a given maximum width,
// iterates on the computed rows.
struct LinesIterator<'a> {
    content: &'a str,
    start: usize,
    width: usize,
}

impl<'a> LinesIterator<'a> {
    // Start an iterator on the given content.
    fn new(content: &'a str, width: usize) -> Self {
        LinesIterator {
            content: content,
            width: width,
            start: 0,
        }
    }
}

impl<'a> Iterator for LinesIterator<'a> {
    type Item = Row;

    fn next(&mut self) -> Option<Row> {
        if self.start >= self.content.len() {
            // This is the end.
            return None;
        }

        let start = self.start;
        let content = &self.content[self.start..];

        let next = content.find('\n').unwrap_or(content.len());
        let content = &content[..next];

        let line_width = content.width();
        if line_width <= self.width {
            // We found a newline before the allowed limit.
            // Break early.
            self.start += next + 1;
            return Some(Row {
                start: start,
                end: next + start,
                width: line_width,
            });
        }

        // Keep adding indivisible tokens
        let head_bytes = match head_bytes(content.split(' '), self.width, " ") {
            0 => head_bytes(content.graphemes(true), self.width, ""),
            other => { self.start += 1; other },
        };

        self.start += head_bytes;

        Some(Row {
            start: start,
            end: start + head_bytes,
            width: self.width,
        })
    }
}

impl View for TextView {
    fn draw(&mut self, printer: &Printer) {

        let h = self.rows.len();
        let offset = self.align.v.get_offset(h, printer.size.y);
        let printer = &printer.sub_printer(Vec2::new(0, offset),
                                           printer.size,
                                           true);

        self.scrollbase.draw(printer, |printer, i| {
            let row = &self.rows[i];
            let text = &self.content[row.start..row.end];
            let l = text.width();
            let x = self.align.h.get_offset(l, printer.size.x);
            printer.print((x, 0), text);
        });
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        if !self.scrollbase.scrollable() {
            return EventResult::Ignored;
        }

        match event {
            Event::Key(Key::Home) => self.scrollbase.scroll_top(),
            Event::Key(Key::End) => self.scrollbase.scroll_bottom(),
            Event::Key(Key::Up) if self.scrollbase.can_scroll_up() => {
                self.scrollbase.scroll_up(1)
            }
            Event::Key(Key::Down) if self.scrollbase
                                         .can_scroll_down() => {
                self.scrollbase.scroll_down(1)
            }
            Event::Key(Key::PageDown) => self.scrollbase.scroll_down(10),
            Event::Key(Key::PageUp) => self.scrollbase.scroll_up(10),
            _ => return EventResult::Ignored,
        }

        EventResult::Consumed(None)
    }

    fn get_min_size(&mut self, size: Vec2) -> Vec2 {
        // If we have no directive, ask for a single big line.
        // TODO: what if the text has newlines??
        // Don't _force_ the max width, but take it if we have to.

        self.compute_rows(size);
        Vec2::new(self.width.unwrap_or(0), self.rows.len())
    }

    fn take_focus(&mut self) -> bool {
        self.scrollbase.scrollable()
    }

    fn layout(&mut self, size: Vec2) {
        // Compute the text rows.
        self.compute_rows(size);
        self.scrollbase.set_heights(size.y, self.rows.len());
    }
}

fn head_bytes<'a, I: Iterator<Item=&'a str>>(iter: I, width: usize, overhead: &str)
                                        -> usize {
    let overhead_width = overhead.width();
    let overhead_len = overhead.len();

    let sum = iter.scan(0, |w, token| {
                      *w += token.width();
                      if *w > width {
                          None
                      } else {
                          // Add a space
                          *w += overhead_width;
                          Some(token)
                      }
                  })
                  .map(|token| token.len() + overhead_len)
                  .fold(0, |a, b| a + b);

    // We counted overhead_len once too many times,
    // but only if the iterator was non empty.
    if sum == 0 {
        sum
    } else {
        sum - overhead_len
    }
}
<commit_msg>Invalidate TextView cache on content change<commit_after>use std::cmp::max;

use vec::Vec2;
use view::View;
use printer::Printer;
use align::*;
use event::*;
use super::scroll::ScrollBase;

use unicode_width::UnicodeWidthStr;
use unicode_segmentation::UnicodeSegmentation;

/// A simple view showing a fixed text
pub struct TextView {
    content: String,
    rows: Vec<Row>,

    align: Align,

    // ScrollBase make many scrolling-related things easier
    scrollbase: ScrollBase,
    last_size: Option<Vec2>,
    width: Option<usize>,
}

// Subset of the main content representing a row on the display.
struct Row {
    start: usize,
    end: usize,
    width: usize,
}

// If the last character is a newline, strip it.
fn strip_last_newline(content: &str) -> &str {
    if !content.is_empty() && content.chars().last().unwrap() == '\n' {
        &content[..content.len() - 1]
    } else {
        content
    }
}

/// Returns the number of lines required to display the given text with the
/// specified maximum line width.
fn get_line_span(line: &str, max_width: usize) -> usize {
    // TODO: this method is stupid. Look at LinesIterator and do the same
    // (Or use a common function? Better!)
    let mut lines = 1;
    let mut length = 0;
    for l in line.split(' ').map(|word| word.width()) {
        length += l;
        if length > max_width {
            length = l;
            lines += 1;
        }
        length += 1;
    }
    lines
}

impl TextView {
    /// Creates a new TextView with the given content.
    pub fn new(content: &str) -> Self {
        let content = strip_last_newline(content);
        TextView {
            content: content.to_string(),
            rows: Vec::new(),
            scrollbase: ScrollBase::new(),
            align: Align::top_left(),
            last_size: None,
            width: None,
        }
    }

    /// Sets the horizontal alignment for this view.
    pub fn h_align(mut self, h: HAlign) -> Self {
        self.align.h = h;

        self
    }

    /// Sets the vertical alignment for this view.
    pub fn v_align(mut self, v: VAlign) -> Self {
        self.align.v = v;

        self
    }

    /// Sets the alignment for this view.
    pub fn align(mut self, a: Align) -> Self {
        self.align = a;

        self
    }

    /// Replace the text in this view.
    pub fn set_content(&mut self, content: &str) {
        let content = strip_last_newline(content);
        self.content = content.to_string();
        self.invalidate();
    }

    /// Returns the current text in this view.
    pub fn get_content(&self) -> &str {
        &self.content
    }

    /// Returns the number of lines required to display the content
    /// with the given width.
    fn get_num_lines(&self, max_width: usize) -> usize {
        self.content
            .split('\n')
            .map(|line| get_line_span(line, max_width))
            .fold(0, |sum, x| sum + x)
    }

    // In the absence of any constraint, what size would we like?
    fn get_ideal_size(&self) -> Vec2 {
        let mut max_width = 0;
        let mut height = 0;

        for line in self.content.split('\n') {
            height += 1;
            max_width = max(max_width, line.width());
        }

        Vec2::new(max_width, height)
    }

    fn is_cache_valid(&self, size: Vec2) -> bool {
        match self.last_size {
            None => false,
            Some(last) => if last.x != size.x {
                false
            } else {
                (last.y < self.rows.len()) == (size.y < self.rows.len())
            },
        }
    }

    fn compute_rows(&mut self, size: Vec2) {
        if !self.is_cache_valid(size) {
            // Recompute
            self.rows = LinesIterator::new(&self.content, size.x).collect();
            let mut scrollbar = 0;
            if self.rows.len() > size.y {
                scrollbar = 2;
                // If we're too high, include a scrollbar
                self.rows = LinesIterator::new(&self.content, size.x - scrollbar)
                    .collect();
            }

            self.width = self.rows.iter().map(|row| row.width).max().map(|w| w + scrollbar);

            self.last_size = Some(size);
        }
    }

    // Invalidates the cache, so next call will recompute everything.
    fn invalidate(&mut self) {
        self.last_size = None;
    }
}

// Given a multiline string, and a given maximum width,
// iterates on the computed rows.
struct LinesIterator<'a> {
    content: &'a str,
    start: usize,
    width: usize,
}

impl<'a> LinesIterator<'a> {
    // Start an iterator on the given content.
    fn new(content: &'a str, width: usize) -> Self {
        LinesIterator {
            content: content,
            width: width,
            start: 0,
        }
    }
}

impl<'a> Iterator for LinesIterator<'a> {
    type Item = Row;

    fn next(&mut self) -> Option<Row> {
        if self.start >= self.content.len() {
            // This is the end.
            return None;
        }

        let start = self.start;
        let content = &self.content[self.start..];

        let next = content.find('\n').unwrap_or(content.len());
        let content = &content[..next];

        let line_width = content.width();
        if line_width <= self.width {
            // We found a newline before the allowed limit.
            // Break early.
            self.start += next + 1;
            return Some(Row {
                start: start,
                end: next + start,
                width: line_width,
            });
        }

        // Keep adding indivisible tokens
        let head_bytes = match head_bytes(content.split(' '), self.width, " ") {
            0 => head_bytes(content.graphemes(true), self.width, ""),
            other => { self.start += 1; other },
        };

        self.start += head_bytes;

        Some(Row {
            start: start,
            end: start + head_bytes,
            width: self.width,
        })
    }
}

impl View for TextView {
    fn draw(&mut self, printer: &Printer) {

        let h = self.rows.len();
        let offset = self.align.v.get_offset(h, printer.size.y);
        let printer = &printer.sub_printer(Vec2::new(0, offset),
                                           printer.size,
                                           true);

        self.scrollbase.draw(printer, |printer, i| {
            let row = &self.rows[i];
            let text = &self.content[row.start..row.end];
            let l = text.width();
            let x = self.align.h.get_offset(l, printer.size.x);
            printer.print((x, 0), text);
        });
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        if !self.scrollbase.scrollable() {
            return EventResult::Ignored;
        }

        match event {
            Event::Key(Key::Home) => self.scrollbase.scroll_top(),
            Event::Key(Key::End) => self.scrollbase.scroll_bottom(),
            Event::Key(Key::Up) if self.scrollbase.can_scroll_up() => {
                self.scrollbase.scroll_up(1)
            }
            Event::Key(Key::Down) if self.scrollbase
                                         .can_scroll_down() => {
                self.scrollbase.scroll_down(1)
            }
            Event::Key(Key::PageDown) => self.scrollbase.scroll_down(10),
            Event::Key(Key::PageUp) => self.scrollbase.scroll_up(10),
            _ => return EventResult::Ignored,
        }

        EventResult::Consumed(None)
    }

    fn get_min_size(&mut self, size: Vec2) -> Vec2 {
        // If we have no directive, ask for a single big line.
        // TODO: what if the text has newlines??
        // Don't _force_ the max width, but take it if we have to.

        self.compute_rows(size);
        Vec2::new(self.width.unwrap_or(0), self.rows.len())
    }

    fn take_focus(&mut self) -> bool {
        self.scrollbase.scrollable()
    }

    fn layout(&mut self, size: Vec2) {
        // Compute the text rows.
        self.compute_rows(size);
        self.scrollbase.set_heights(size.y, self.rows.len());
    }
}

fn head_bytes<'a, I: Iterator<Item=&'a str>>(iter: I, width: usize, overhead: &str)
                                        -> usize {
    let overhead_width = overhead.width();
    let overhead_len = overhead.len();

    let sum = iter.scan(0, |w, token| {
                      *w += token.width();
                      if *w > width {
                          None
                      } else {
                          // Add a space
                          *w += overhead_width;
                          Some(token)
                      }
                  })
                  .map(|token| token.len() + overhead_len)
                  .fold(0, |a, b| a + b);

    // We counted overhead_len once too many times,
    // but only if the iterator was non empty.
    if sum == 0 {
        sum
    } else {
        sum - overhead_len
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]
use aptos_config::config::NodeConfig;
use hex::FromHex;
use rand::{rngs::StdRng, SeedableRng};
use std::path::PathBuf;
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
#[structopt(about = "Aptos Node")]
struct Args {
    #[structopt(
        short = "f",
        long,
        required_unless = "test",
        help = "Path to NodeConfig"
    )]
    config: Option<PathBuf>,
    #[structopt(long, help = "Enable a single validator testnet")]
    test: bool,

    #[structopt(
        long,
        help = "RNG Seed to use when starting single validator testnet",
        parse(try_from_str = FromHex::from_hex),
        requires("test")
    )]
    seed: Option<[u8; 32]>,

    #[structopt(long, help = "Enabling random ports for testnet", requires("test"))]
    random_ports: bool,

    #[structopt(
        long,
        help = "Paths to module blobs to be included in genesis. Can include both files and directories",
        requires("test")
    )]
    genesis_modules: Option<Vec<PathBuf>>,

    #[structopt(
        long,
        help = "Lazy mode, set this flag will set `consensus#mempool_poll_count` config to `u64::MAX` and only commit a block when there is user transaction in mempool",
        requires("test")
    )]
    lazy: bool,
}

#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

fn main() {
    let args = Args::from_args();

    if args.test {
        println!("Entering test mode, this should never be used in production!");
        let rng = args
            .seed
            .map(StdRng::from_seed)
            .unwrap_or_else(StdRng::from_entropy);
        let genesis_modules = if let Some(module_paths) = args.genesis_modules {
            framework::load_modules_from_paths(&module_paths)
        } else {
            cached_framework_packages::module_blobs().to_vec()
        };
        aptos_node::load_test_environment(
            args.config,
            args.random_ports,
            args.lazy,
            genesis_modules,
            rng,
        );
    } else {
        let config = NodeConfig::load(args.config.unwrap()).expect("Failed to load node config");
        println!("Using node config {:?}", &config);
        aptos_node::start(config, None);
    };
}
<commit_msg>[Aptos Node] Improve error message around config file loading failure. (#1748)<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]
use aptos_config::config::NodeConfig;
use hex::FromHex;
use rand::{rngs::StdRng, SeedableRng};
use std::path::PathBuf;
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
#[structopt(about = "Aptos Node")]
struct Args {
    #[structopt(
        short = "f",
        long,
        required_unless = "test",
        help = "Path to NodeConfig"
    )]
    config: Option<PathBuf>,
    #[structopt(long, help = "Enable a single validator testnet")]
    test: bool,

    #[structopt(
        long,
        help = "RNG Seed to use when starting single validator testnet",
        parse(try_from_str = FromHex::from_hex),
        requires("test")
    )]
    seed: Option<[u8; 32]>,

    #[structopt(long, help = "Enabling random ports for testnet", requires("test"))]
    random_ports: bool,

    #[structopt(
        long,
        help = "Paths to module blobs to be included in genesis. Can include both files and directories",
        requires("test")
    )]
    genesis_modules: Option<Vec<PathBuf>>,

    #[structopt(
        long,
        help = "Lazy mode, set this flag will set `consensus#mempool_poll_count` config to `u64::MAX` and only commit a block when there is user transaction in mempool",
        requires("test")
    )]
    lazy: bool,
}

#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

fn main() {
    let args = Args::from_args();

    if args.test {
        println!("Entering test mode, this should never be used in production!");
        let rng = args
            .seed
            .map(StdRng::from_seed)
            .unwrap_or_else(StdRng::from_entropy);
        let genesis_modules = if let Some(module_paths) = args.genesis_modules {
            framework::load_modules_from_paths(&module_paths)
        } else {
            cached_framework_packages::module_blobs().to_vec()
        };
        aptos_node::load_test_environment(
            args.config,
            args.random_ports,
            args.lazy,
            genesis_modules,
            rng,
        );
    } else {
        // Load the config file
        let config_path = args.config.unwrap();
        let config = NodeConfig::load(config_path.clone()).unwrap_or_else(|error| {
            panic!(
                "Failed to load node config file! Given file path: {:?}. Error: {:?}",
                config_path, error
            )
        });
        println!("Using node config {:?}", &config);

        // Start the node
        aptos_node::start(config, None);
    };
}
<|endoftext|>


<commit_before>//! Abstractions for page tables and other paging related structures.

pub use self::page_table::*;
pub use self::recursive::*;

use addr::{VirtAddr, PhysAddr};
use core::ops::{Add, AddAssign, Sub, SubAssign};
use ux::*;

mod page_table;
mod recursive;

/// The default page size on x86_64.
pub const PAGE_SIZE: u16 = 4096;

/// A virtual 4kB page.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Page {
   number: u64,
}

impl Page {
    /// Returns the page that contains the given virtual address.
    pub fn containing_address(address: VirtAddr) -> Page {
        Page { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    pub fn from_page_table_indices(p4_index: u9, p3_index: u9, p2_index: u9, p1_index: u9)
        -> Page
    {
        use bit_field::BitField;

        let mut addr = 0;
        addr.set_bits(39..48, u64::from(p4_index));
        addr.set_bits(30..39, u64::from(p3_index));
        addr.set_bits(21..30, u64::from(p2_index));
        addr.set_bits(12..21, u64::from(p1_index));
        Page::containing_address(VirtAddr::new(addr))
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> VirtAddr {
        VirtAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    /// Returns the level 4 page table index of this page.
    pub fn p4_index(&self) -> u9 {
        self.start_address().p4_index()
    }

    /// Returns the level 3 page table index of this page.
    pub fn p3_index(&self) -> u9 {
        self.start_address().p3_index()
    }

    /// Returns the level 2 page table index of this page.
    pub fn p2_index(&self) -> u9 {
        self.start_address().p2_index()
    }

    /// Returns the level 1 page table index of this page.
    pub fn p1_index(&self) -> u9 {
        self.start_address().p1_index()
    }

    pub fn range(start: Page, end: Page) -> PageRange {
        PageRange { start, end }
    }

    pub fn range_inclusive(start: Page, end: Page) -> PageRangeInclusive {
        PageRangeInclusive { start, end }
    }
}

impl Add<u64> for Page {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for Page {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for Page {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for Page {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

pub struct PageRange {
    pub start: Page,
    pub end: Page,
}

impl Iterator for PageRange {
    type Item = Page;

    fn next(&mut self) -> Option<Page> {
        if self.start < self.end {
            let page = self.start.clone();
            self.start += 1;
            Some(page)
        } else {
            None
        }
    }
}

pub struct PageRangeInclusive {
    pub start: Page,
    pub end: Page,
}

impl Iterator for PageRangeInclusive {
    type Item = Page;

    fn next(&mut self) -> Option<Page> {
        if self.start <= self.end {
            let page = self.start.clone();
            self.start += 1;
            Some(page)
        } else {
            None
        }
    }
}

/// A physical 4kB frame.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct PhysFrame {
   number: u64,
}

impl PhysFrame {
    /// Returns the frame that contains the given physical address.
    pub fn containing_address(address: PhysAddr) -> PhysFrame {
        PhysFrame { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> PhysAddr {
        PhysAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    pub fn range(start: PhysFrame, end: PhysFrame) -> PhysFrameRange {
        PhysFrameRange { start, end }
    }

    pub fn range_inclusive(start: PhysFrame, end: PhysFrame) -> PhysFrameRangeInclusive {
        PhysFrameRangeInclusive { start, end }
    }
}

impl Add<u64> for PhysFrame {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for PhysFrame {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for PhysFrame {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for PhysFrame {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

pub struct PhysFrameRange {
    pub start: PhysFrame,
    pub end: PhysFrame,
}

impl Iterator for PhysFrameRange {
    type Item = PhysFrame;

    fn next(&mut self) -> Option<PhysFrame> {
        if self.start < self.end {
            let frame = self.start.clone();
            self.start += 1;
            Some(frame)
        } else {
            None
        }
    }
}

pub struct PhysFrameRangeInclusive {
    pub start: PhysFrame,
    pub end: PhysFrame,
}

impl Iterator for PhysFrameRangeInclusive {
    type Item = PhysFrame;

    fn next(&mut self) -> Option<PhysFrame> {
        if self.start <= self.end {
            let frame = self.start.clone();
            self.start += 1;
            Some(frame)
        } else {
            None
        }
    }
}
<commit_msg>Add test for new range types<commit_after>//! Abstractions for page tables and other paging related structures.

pub use self::page_table::*;
pub use self::recursive::*;

use addr::{VirtAddr, PhysAddr};
use core::ops::{Add, AddAssign, Sub, SubAssign};
use ux::*;

mod page_table;
mod recursive;

/// The default page size on x86_64.
pub const PAGE_SIZE: u16 = 4096;

/// A virtual 4kB page.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Page {
   number: u64,
}

impl Page {
    /// Returns the page that contains the given virtual address.
    pub fn containing_address(address: VirtAddr) -> Page {
        Page { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    pub fn from_page_table_indices(p4_index: u9, p3_index: u9, p2_index: u9, p1_index: u9)
        -> Page
    {
        use bit_field::BitField;

        let mut addr = 0;
        addr.set_bits(39..48, u64::from(p4_index));
        addr.set_bits(30..39, u64::from(p3_index));
        addr.set_bits(21..30, u64::from(p2_index));
        addr.set_bits(12..21, u64::from(p1_index));
        Page::containing_address(VirtAddr::new(addr))
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> VirtAddr {
        VirtAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    /// Returns the level 4 page table index of this page.
    pub fn p4_index(&self) -> u9 {
        self.start_address().p4_index()
    }

    /// Returns the level 3 page table index of this page.
    pub fn p3_index(&self) -> u9 {
        self.start_address().p3_index()
    }

    /// Returns the level 2 page table index of this page.
    pub fn p2_index(&self) -> u9 {
        self.start_address().p2_index()
    }

    /// Returns the level 1 page table index of this page.
    pub fn p1_index(&self) -> u9 {
        self.start_address().p1_index()
    }

    pub fn range(start: Page, end: Page) -> PageRange {
        PageRange { start, end }
    }

    pub fn range_inclusive(start: Page, end: Page) -> PageRangeInclusive {
        PageRangeInclusive { start, end }
    }
}

impl Add<u64> for Page {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for Page {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for Page {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for Page {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

pub struct PageRange {
    pub start: Page,
    pub end: Page,
}

impl Iterator for PageRange {
    type Item = Page;

    fn next(&mut self) -> Option<Page> {
        if self.start < self.end {
            let page = self.start.clone();
            self.start += 1;
            Some(page)
        } else {
            None
        }
    }
}

pub struct PageRangeInclusive {
    pub start: Page,
    pub end: Page,
}

impl Iterator for PageRangeInclusive {
    type Item = Page;

    fn next(&mut self) -> Option<Page> {
        if self.start <= self.end {
            let page = self.start.clone();
            self.start += 1;
            Some(page)
        } else {
            None
        }
    }
}

/// A physical 4kB frame.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct PhysFrame {
   number: u64,
}

impl PhysFrame {
    /// Returns the frame that contains the given physical address.
    pub fn containing_address(address: PhysAddr) -> PhysFrame {
        PhysFrame { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> PhysAddr {
        PhysAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    pub fn range(start: PhysFrame, end: PhysFrame) -> PhysFrameRange {
        PhysFrameRange { start, end }
    }

    pub fn range_inclusive(start: PhysFrame, end: PhysFrame) -> PhysFrameRangeInclusive {
        PhysFrameRangeInclusive { start, end }
    }
}

impl Add<u64> for PhysFrame {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for PhysFrame {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for PhysFrame {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for PhysFrame {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

pub struct PhysFrameRange {
    pub start: PhysFrame,
    pub end: PhysFrame,
}

impl Iterator for PhysFrameRange {
    type Item = PhysFrame;

    fn next(&mut self) -> Option<PhysFrame> {
        if self.start < self.end {
            let frame = self.start.clone();
            self.start += 1;
            Some(frame)
        } else {
            None
        }
    }
}

pub struct PhysFrameRangeInclusive {
    pub start: PhysFrame,
    pub end: PhysFrame,
}

impl Iterator for PhysFrameRangeInclusive {
    type Item = PhysFrame;

    fn next(&mut self) -> Option<PhysFrame> {
        if self.start <= self.end {
            let frame = self.start.clone();
            self.start += 1;
            Some(frame)
        } else {
            None
        }
    }
}

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

    #[test]
    pub fn test_page_ranges() {
        let page_size = u64::from(PAGE_SIZE);
        let number = 1000;

        let start_addr = VirtAddr::new(0xdeadbeaf);
        let start = Page::containing_address(start_addr);
        let end = start.clone() + number;

        let mut range = Page::range(start.clone(), end.clone());
        for i in 0..number {
            assert_eq!(range.next(),
            Some(Page::containing_address(start_addr + u64::from(PAGE_SIZE) * i)));
        }
        assert_eq!(range.next(), None);

        let mut range_inclusive = Page::range_inclusive(start, end);
        for i in 0..=number {
            assert_eq!(range_inclusive.next(),
            Some(Page::containing_address(start_addr + u64::from(PAGE_SIZE) * i)));
        }
        assert_eq!(range_inclusive.next(), None);
    }
}
<|endoftext|>


<commit_before>//! Abstractions for page tables and other paging related structures.

pub use self::page_table::*;

use addr::{VirtAddr, PhysAddr};

use ux::*;

mod page_table;

/// The default page size on x86_64.
pub const PAGE_SIZE: u16 = 4096;

/// A virtual 4kB page.
pub struct Page {
   number: u64,
}

impl Page {
    /// Returns the page that contains the given virtual address.
    pub fn containing_address(address: VirtAddr) -> Page {
        Page { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> VirtAddr {
        VirtAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    /// Returns the level 4 page table index of this page.
    pub fn p4_index(&self) -> u9 {
        self.start_address().p4_index()
    }

    /// Returns the level 3 page table index of this page.
    pub fn p3_index(&self) -> u9 {
        self.start_address().p3_index()
    }

    /// Returns the level 2 page table index of this page.
    pub fn p2_index(&self) -> u9 {
        self.start_address().p2_index()
    }

    /// Returns the level 1 page table index of this page.
    pub fn p1_index(&self) -> u9 {
        self.start_address().p1_index()
    }
}

/// A physical 4kB frame.
pub struct PhysFrame {
   number: u64,
}

impl PhysFrame {
    /// Returns the frame that contains the given physical address.
    pub fn containing_address(address: PhysAddr) -> PhysFrame {
        PhysFrame { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> PhysAddr {
        PhysAddr::new(self.number * u64::from(PAGE_SIZE))
    }
}
<commit_msg>Implement Add for Page and PhysFrame<commit_after>//! Abstractions for page tables and other paging related structures.

pub use self::page_table::*;

use addr::{VirtAddr, PhysAddr};
use core::ops::Add;
use ux::*;

mod page_table;

/// The default page size on x86_64.
pub const PAGE_SIZE: u16 = 4096;

/// A virtual 4kB page.
pub struct Page {
   number: u64,
}

impl Page {
    /// Returns the page that contains the given virtual address.
    pub fn containing_address(address: VirtAddr) -> Page {
        Page { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> VirtAddr {
        VirtAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    /// Returns the level 4 page table index of this page.
    pub fn p4_index(&self) -> u9 {
        self.start_address().p4_index()
    }

    /// Returns the level 3 page table index of this page.
    pub fn p3_index(&self) -> u9 {
        self.start_address().p3_index()
    }

    /// Returns the level 2 page table index of this page.
    pub fn p2_index(&self) -> u9 {
        self.start_address().p2_index()
    }

    /// Returns the level 1 page table index of this page.
    pub fn p1_index(&self) -> u9 {
        self.start_address().p1_index()
    }
}

impl Add<u64> for Page {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

/// A physical 4kB frame.
pub struct PhysFrame {
   number: u64,
}

impl PhysFrame {
    /// Returns the frame that contains the given physical address.
    pub fn containing_address(address: PhysAddr) -> PhysFrame {
        PhysFrame { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> PhysAddr {
        PhysAddr::new(self.number * u64::from(PAGE_SIZE))
    }
}

impl Add<u64> for PhysFrame {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}
<|endoftext|>


<commit_before>extern crate db_key;
extern crate leveldb;
extern crate serialize;
extern crate core;

mod utils;
mod database;
mod comparator;
mod binary;
mod iterator;
mod snapshots;
mod cache;
<commit_msg>Make the tests warning free<commit_after>#![feature(tempdir)]
#![feature(path)]
#![feature(core)]

extern crate db_key;
extern crate leveldb;
extern crate core;

mod utils;
mod database;
mod comparator;
mod binary;
mod iterator;
mod snapshots;
mod cache;
<|endoftext|>


<commit_before>extern crate kv_cab;

use kv_cab::{ KV, Value };

macro_rules! test_setup {
    ( $p:ident, $i:ident ) => {
        let _ = std::fs::remove_file($p);
        let mut $i = KV::<String, Value>::new($p);
    }
}

macro_rules! test_teardown {
    ( $p:ident ) => {
        use std::{thread, time};

        thread::sleep(time::Duration::from_secs(1));
        let _ = std::fs::remove_file($p);
    }
}

#[test]
fn test_create() {
    let test_cab_path ="./test_create.cab";

    let _ = std::fs::remove_file(test_cab_path);
    let _ = KV::<String, Value>::new(test_cab_path);

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_string() {
    let test_cab_path = "./text_insert_string.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_int() {
    let test_cab_path = "./test_insert_int.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::Int(0i32));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_float() {
    let test_cab_path = "./test_insert_float.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::Float(0f32));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_string() {
    let test_cab_path = "./test_get_string.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::String("value".to_string())));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_int() {
    let test_cab_path = "./test_get_int.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::Int(0i32));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::Int(0i32)));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_float() {
    let test_cab_path = "./test_get_float.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::Float(0f32));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::Float(0f32)));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_none() {
    let test_cab_path = "./test_get_none.cab";
    test_setup!(test_cab_path, test_store);

    assert_eq!(test_store.get("none".to_string()), None);

    test_teardown!(test_cab_path);
}

#[test]
fn test_remove() {
    let test_cab_path = "./test_remove.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
        assert_eq!(res, Ok(true));
    }

    {
        let res = test_store.remove("key".to_string());
        assert_eq!(res, Ok(true));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_remove_none() {
    let test_cab_path = "./test_remove_none.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.remove("key".to_string());
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_keys() {
    let test_cab_path = "./test_keys.cab";
    test_setup!(test_cab_path, test_store);

    assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    assert!(test_store.insert("key2".to_string(), Value::String("value2".to_string())) == Ok(true));

    assert!(test_store.keys().len() == 2);
    assert!(test_store.remove("key".to_string()) == Ok(true));
    assert!(test_store.keys().len() == 1);
    assert!(test_store.remove("key2".to_string()) == Ok(true));
    assert!(test_store.keys().len() == 0);

    test_teardown!(test_cab_path);
}

#[test]
fn test_kv_all() {
    let test_cab_path = "./test_kv_all.cab";
    test_setup!(test_cab_path, test_store);

    assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    assert!(test_store.get("key".to_string()).is_some());
    assert!(test_store.remove("key".to_string()) == Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_multi_instance() {
    let test_cab_path = "./test_multi_instance.cab";
    {
        let mut test_store = KV::<String, Value>::new(test_cab_path);
        assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    }
    {
        let mut test_store = KV::<String, Value>::new(test_cab_path);
        assert!(test_store.get("key".to_string()) == Some(Value::String("value".to_string())));
        assert!(test_store.remove("key".to_string()) == Ok(true));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_multithread_instance() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        std::thread::sleep(std::time::Duration::new(1u64, 0u32));
        assert!(test_store.get("key".to_string()).is_some());
        assert!(test_store.remove("key".to_string()) == Ok(true));
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}

#[test]
fn test_multithread_instance_insert() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance_insert.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        for i in 0..1000 {
            assert!(test_store.insert(format!("{}", i), Value::Int(i)) == Ok(true));
        }
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        for i in 1000..2000 {
            assert!(test_store.insert(format!("{}", i), Value::Int(i)) == Ok(true));
        }
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}

#[test]
fn test_multithread_instance_read_between() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance_read_between.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        std::thread::sleep(std::time::Duration::new(1u64, 0u32));
        assert!(test_store.get("key".to_string()).unwrap() == Value::String("value".to_string()));
        assert!(test_store.remove("key".to_string()) == Ok(true));
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}
<commit_msg>Added more tests for creating incorrect type and multiple instances inserting<commit_after>extern crate kv_cab;

use kv_cab::{ KV, Value };

macro_rules! test_setup {
    ( $p:ident, $i:ident ) => {
        let _ = std::fs::remove_file($p);
        let mut $i = KV::<String, Value>::new($p);
    }
}

macro_rules! test_teardown {
    ( $p:ident ) => {
        use std::{thread, time};

        thread::sleep(time::Duration::from_secs(1));
        let _ = std::fs::remove_file($p);
    }
}

#[test]
fn test_create() {
    let test_cab_path ="./test_create.cab";

    let _ = std::fs::remove_file(test_cab_path);
    let _ = KV::<String, Value>::new(test_cab_path);

    test_teardown!(test_cab_path);
}

#[test]
fn test_create_wrong_type() {
    let test_cab_path ="./test_create_wrong_type.cab";

    let _ = std::fs::remove_file(test_cab_path);

    let mut test_store = KV::<String, Value>::new(test_cab_path);
    let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
    assert_eq!(res, Ok(true));

    let mut test_store_2 = KV::<i32, Value>::new(test_cab_path);
    assert_eq!(test_store_2.keys().len(), 0);

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_string() {
    let test_cab_path = "./text_insert_string.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_int() {
    let test_cab_path = "./test_insert_int.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::Int(0i32));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_float() {
    let test_cab_path = "./test_insert_float.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::Float(0f32));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_string() {
    let test_cab_path = "./test_get_string.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::String("value".to_string())));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_int() {
    let test_cab_path = "./test_get_int.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::Int(0i32));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::Int(0i32)));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_float() {
    let test_cab_path = "./test_get_float.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::Float(0f32));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::Float(0f32)));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_none() {
    let test_cab_path = "./test_get_none.cab";
    test_setup!(test_cab_path, test_store);

    assert_eq!(test_store.get("none".to_string()), None);

    test_teardown!(test_cab_path);
}

#[test]
fn test_remove() {
    let test_cab_path = "./test_remove.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
        assert_eq!(res, Ok(true));
    }

    {
        let res = test_store.remove("key".to_string());
        assert_eq!(res, Ok(true));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_remove_none() {
    let test_cab_path = "./test_remove_none.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.remove("key".to_string());
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_keys() {
    let test_cab_path = "./test_keys.cab";
    test_setup!(test_cab_path, test_store);

    assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    assert!(test_store.insert("key2".to_string(), Value::String("value2".to_string())) == Ok(true));

    assert!(test_store.keys().len() == 2);
    assert!(test_store.remove("key".to_string()) == Ok(true));
    assert!(test_store.keys().len() == 1);
    assert!(test_store.remove("key2".to_string()) == Ok(true));
    assert!(test_store.keys().len() == 0);

    test_teardown!(test_cab_path);
}

#[test]
fn test_kv_all() {
    let test_cab_path = "./test_kv_all.cab";
    test_setup!(test_cab_path, test_store);

    assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    assert!(test_store.get("key".to_string()).is_some());
    assert!(test_store.remove("key".to_string()) == Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_multi_instance() {
    let test_cab_path = "./test_multi_instance.cab";
    {
        let mut test_store = KV::<String, Value>::new(test_cab_path);
        assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    }
    {
        let mut test_store = KV::<String, Value>::new(test_cab_path);
        assert!(test_store.get("key".to_string()) == Some(Value::String("value".to_string())));
        assert!(test_store.remove("key".to_string()) == Ok(true));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_multithread_instance() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        std::thread::sleep(std::time::Duration::new(1u64, 0u32));
        assert!(test_store.get("key".to_string()).is_some());
        assert!(test_store.remove("key".to_string()) == Ok(true));
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}

#[test]
fn test_multithread_instance_insert() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance_insert.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        for i in 0..1000 {
            assert!(test_store.insert(format!("{}", i), Value::Int(i)) == Ok(true));
            assert!(test_store.get(format!("{}", i)).is_some());
        }
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        for i in 1000..2000 {
            assert!(test_store.insert(format!("{}", i), Value::Int(i)) == Ok(true));
            assert!(test_store.get(format!("{}", i)).is_some());
        }
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}

#[test]
fn test_multithread_many_instance_insert() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_many_instance_insert.cab";
    let mut check_store = KV::<i32, Value>::new(TEST_CAB_PATH);

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<i32, Value>::new(TEST_CAB_PATH);
        for i in 0..1000 {
            assert!(test_store.insert(i, Value::Int(i)) == Ok(true));
            assert!(test_store.get(i).is_some());
        }
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<i32, Value>::new(TEST_CAB_PATH);
        for i in 0..1000 {
            assert!(test_store.insert(i, Value::Int(i)) == Ok(true));
            assert!(test_store.get(i).is_some());
        }
    });

    let t_3 = thread::spawn(|| {
        let mut test_store = KV::<i32, Value>::new(TEST_CAB_PATH);
        for i in 1000..2000 {
            assert!(test_store.insert(i, Value::Int(i)) == Ok(true));
            assert!(test_store.get(i).is_some());
        }
    });

    let t_4 = thread::spawn(|| {
        let mut test_store = KV::<i32, Value>::new(TEST_CAB_PATH);
        for i in 1000..2000 {
            assert!(test_store.insert(i, Value::Int(i)) == Ok(true));
            assert!(test_store.get(i).is_some());
        }
    });

    assert!(t_1.join().is_ok());
    assert!(t_2.join().is_ok());
    assert!(t_3.join().is_ok());
    assert!(t_4.join().is_ok());

    for i in 0..2000 {
        assert!(check_store.get(i).unwrap() == Value::Int(i));
    }

    test_teardown!(TEST_CAB_PATH);
}

#[test]
fn test_multithread_instance_read_between() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance_read_between.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        std::thread::sleep(std::time::Duration::new(1u64, 0u32));
        assert!(test_store.get("key".to_string()).unwrap() == Value::String("value".to_string()));
        assert!(test_store.remove("key".to_string()) == Ok(true));
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate diff;
extern crate bindgen;
extern crate shlex;

use bindgen::{Builder, builder, clang_version};
use std::fs;
use std::io::{BufRead, BufReader, Error, ErrorKind, Read, Write};
use std::path::PathBuf;
use std::process::Command;

#[path="../src/options.rs"]
mod options;
use options::builder_from_flags;

fn compare_generated_header(header: &PathBuf,
                            builder: Builder)
                            -> Result<(), Error> {
    let file_name = try!(header.file_name()
        .ok_or(Error::new(ErrorKind::Other, "spawn_bindgen expects a file")));

    let mut expected = PathBuf::from(header);
    expected.pop();
    expected.pop();
    expected.push("expectations");
    expected.push("tests");
    expected.push(file_name);
    expected.set_extension("rs");

    // If the expectation file doesn't exist, see if we have different test
    // expectations for different libclang versions.
    if !expected.is_file() {
        let file_name = expected.file_name().unwrap().to_owned();
        expected.pop();

        if cfg!(feature = "testing_only_libclang_4") {
            expected.push("libclang-4");
        } else if cfg!(feature = "testing_only_libclang_3_9") {
            expected.push("libclang-3.9");
        } else if cfg!(feature = "testing_only_libclang_3_8") {
            expected.push("libclang-3.8");
        } else {
            match clang_version().parsed {
                None => {},
                Some(version) => {
                    let (maj, min) = version;
                    let version_str = if maj >= 4 {
                        "4".to_owned()
                    } else {
                        format!("{}.{}", maj, min)
                    };
                    expected.push(format!("libclang-{}", version_str));
                }
            }
        }

        expected.push(file_name);

        if !expected.is_file() {
            panic!("missing test expectation file and/or 'testing_only_libclang_$VERSION' \
                    feature for header '{}'; looking for expectation file at '{}'",
                   header.display(),
                   expected.display());
        }
    }

    // We skip the generate() error here so we get a full diff below
    let output = match builder.generate() {
        Ok(bindings) => bindings.to_string(),
        Err(_) => "".to_string(),
    };

    let mut buffer = String::new();
    {
        if let Ok(expected_file) = fs::File::open(&expected) {
            try!(BufReader::new(expected_file).read_to_string(&mut buffer));
        }
    }

    if output == buffer {
        if !output.is_empty() {
            return Ok(());
        }
        return Err(Error::new(ErrorKind::Other,
                              "Something's gone really wrong!"));
    }

    println!("diff expected generated");
    println!("--- expected: {:?}", expected);
    println!("+++ generated from: {:?}", header);

    for diff in diff::lines(&buffer, &output) {
        match diff {
            diff::Result::Left(l) => println!("-{}", l),
            diff::Result::Both(l, _) => println!(" {}", l),
            diff::Result::Right(r) => println!("+{}", r),
        }
    }

    // Override the diff.
    {
        let mut expected_file = try!(fs::File::create(&expected));
        try!(expected_file.write_all(output.as_bytes()));
    }

    Err(Error::new(ErrorKind::Other, "Header and binding differ!"))
}

fn create_bindgen_builder(header: &PathBuf) -> Result<Option<Builder>, Error> {
    let source = try!(fs::File::open(header));
    let reader = BufReader::new(source);

    // Scoop up bindgen-flags from test header
    let mut flags = Vec::with_capacity(2);

    for line in reader.lines() {
        let line = try!(line);
        if !line.starts_with("// bindgen") {
            continue;
        }

        if line.contains("bindgen-flags: ") {
            let extra_flags = line.split("bindgen-flags: ")
                .last()
                .and_then(shlex::split)
                .unwrap();
            flags.extend(extra_flags.into_iter());
        } else if line.contains("bindgen-osx-only") {
            let prepend_flags = ["--raw-line", "#![cfg(target_os=\"macos\")]"];
            flags = prepend_flags.into_iter()
                .map(ToString::to_string)
                .chain(flags)
                .collect();
        } else if line.contains("bindgen-generate-bindings-on-linux-only") &&
          !cfg!(target_os = "linux") {
              return Ok(None);
        }
    }

    // Fool builder_from_flags() into believing it has real env::args_os...
    // - add "bindgen" as executable name 0th element
    // - add header filename as 1st element
    // - prepend raw lines so they're in the right order for expected output
    // - append the test header's bindgen flags
    let header_str = try!(header.to_str()
        .ok_or(Error::new(ErrorKind::Other, "Invalid header file name")));

    let prepend = ["bindgen",
                   "--with-derive-default",
                   header_str,
                   "--raw-line",
                   "",
                   "--raw-line",
                   "#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]",
                   "--raw-line",
                   ""];

    let args = prepend.into_iter()
        .map(ToString::to_string)
        .chain(flags.into_iter());

    builder_from_flags(args)
        .map(|(builder, _, _)| Some(builder))
}

macro_rules! test_header {
    ($function:ident, $header:expr) => (
        #[test]
        fn $function() {
            let header = PathBuf::from($header);
            let result = create_bindgen_builder(&header)
                .and_then(|builder| {
                    if let Some(builder) = builder {
                        compare_generated_header(&header, builder)
                    } else {
                        Ok(())
                    }
                });

            if let Err(err) = result {
                panic!("{}", err);
            }
        }
    )
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));

#[test]
fn test_header_contents() {
    let bindings = builder()
        .header_contents("test.h", "int foo(const char* a);")
        .generate()
        .unwrap()
        .to_string();
    assert_eq!(bindings, "/* automatically generated by rust-bindgen */

extern \"C\" {
    pub fn foo(a: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int;
}
");
}

#[test]
fn test_multiple_header_calls_in_builder() {
    let actual = builder()
        .header(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/func_ptr.h"))
        .header(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/enum.h"))
        .generate()
        .unwrap()
        .to_string();

    let expected = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/expectations/tests/test_multiple_header_calls_in_builder.rs"));

    if actual != expected {
        println!("Generated bindings differ from expected!");

        for diff in diff::lines(&actual, &expected) {
            match diff {
                diff::Result::Left(l) => println!("-{}", l),
                diff::Result::Both(l, _) => println!(" {}", l),
                diff::Result::Right(r) => println!("+{}", r),
            }
        }

        panic!();
    }
}

#[test]
fn no_system_header_includes() {
    assert!(Command::new("./ci/no-includes.sh")
            .current_dir(env!("CARGO_MANIFEST_DIR"))
            .spawn()
            .expect("should spawn ./ci/no-includes.sh OK")
            .wait()
            .expect("should wait for ./ci/no-includes OK")
            .success());
}

#[test]
fn dump_preprocessed_input() {
    let arg_keyword = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/arg_keyword.hpp");
    let empty_layout = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/cpp-empty-layout.hpp");

    builder()
        .header(arg_keyword)
        .header(empty_layout)
        .dump_preprocessed_input()
        .expect("should dump preprocessed input");

    fn slurp(p: &str) -> String {
        let mut contents = String::new();
        let mut file = fs::File::open(p).unwrap();
        file.read_to_string(&mut contents).unwrap();
        contents
    }

    let bindgen_ii = slurp("__bindgen.ii");
    let arg_keyword = slurp(arg_keyword);
    let empty_layout = slurp(empty_layout);

    assert!(bindgen_ii.find(&arg_keyword).is_some(),
            "arg_keyword.hpp is in the preprocessed file");
    assert!(bindgen_ii.find(&empty_layout).is_some(),
            "cpp-empty-layout.hpp is in the preprocessed file");
}
<commit_msg>Have tests targetting Linux by default on Windows<commit_after>extern crate clap;
extern crate diff;
extern crate bindgen;
extern crate shlex;

use bindgen::{Builder, builder, clang_version};
use std::fs;
use std::io::{BufRead, BufReader, Error, ErrorKind, Read, Write};
use std::path::PathBuf;
use std::process::Command;

#[path="../src/options.rs"]
mod options;
use options::builder_from_flags;

fn compare_generated_header(header: &PathBuf,
                            builder: Builder)
                            -> Result<(), Error> {
    let file_name = try!(header.file_name()
        .ok_or(Error::new(ErrorKind::Other, "spawn_bindgen expects a file")));

    let mut expected = PathBuf::from(header);
    expected.pop();
    expected.pop();
    expected.push("expectations");
    expected.push("tests");
    expected.push(file_name);
    expected.set_extension("rs");

    // If the expectation file doesn't exist, see if we have different test
    // expectations for different libclang versions.
    if !expected.is_file() {
        let file_name = expected.file_name().unwrap().to_owned();
        expected.pop();

        if cfg!(feature = "testing_only_libclang_4") {
            expected.push("libclang-4");
        } else if cfg!(feature = "testing_only_libclang_3_9") {
            expected.push("libclang-3.9");
        } else if cfg!(feature = "testing_only_libclang_3_8") {
            expected.push("libclang-3.8");
        } else {
            match clang_version().parsed {
                None => {},
                Some(version) => {
                    let (maj, min) = version;
                    let version_str = if maj >= 4 {
                        "4".to_owned()
                    } else {
                        format!("{}.{}", maj, min)
                    };
                    expected.push(format!("libclang-{}", version_str));
                }
            }
        }

        expected.push(file_name);

        if !expected.is_file() {
            panic!("missing test expectation file and/or 'testing_only_libclang_$VERSION' \
                    feature for header '{}'; looking for expectation file at '{}'",
                   header.display(),
                   expected.display());
        }
    }

    // We skip the generate() error here so we get a full diff below
    let output = match builder.generate() {
        Ok(bindings) => bindings.to_string(),
        Err(_) => "".to_string(),
    };

    let mut buffer = String::new();
    {
        if let Ok(expected_file) = fs::File::open(&expected) {
            try!(BufReader::new(expected_file).read_to_string(&mut buffer));
        }
    }

    if output == buffer {
        if !output.is_empty() {
            return Ok(());
        }
        return Err(Error::new(ErrorKind::Other,
                              "Something's gone really wrong!"));
    }

    println!("diff expected generated");
    println!("--- expected: {:?}", expected);
    println!("+++ generated from: {:?}", header);

    for diff in diff::lines(&buffer, &output) {
        match diff {
            diff::Result::Left(l) => println!("-{}", l),
            diff::Result::Both(l, _) => println!(" {}", l),
            diff::Result::Right(r) => println!("+{}", r),
        }
    }

    // Override the diff.
    {
        let mut expected_file = try!(fs::File::create(&expected));
        try!(expected_file.write_all(output.as_bytes()));
    }

    Err(Error::new(ErrorKind::Other, "Header and binding differ!"))
}

fn create_bindgen_builder(header: &PathBuf) -> Result<Option<Builder>, Error> {
    let source = try!(fs::File::open(header));
    let reader = BufReader::new(source);

    // Scoop up bindgen-flags from test header
    let mut flags = Vec::with_capacity(2);

    for line in reader.lines() {
        let line = try!(line);
        if !line.starts_with("// bindgen") {
            continue;
        }

        if line.contains("bindgen-flags: ") {
            let extra_flags = line.split("bindgen-flags: ")
                .last()
                .and_then(shlex::split)
                .unwrap();
            flags.extend(extra_flags.into_iter());
        } else if line.contains("bindgen-osx-only") {
            let prepend_flags = ["--raw-line", "#![cfg(target_os=\"macos\")]"];
            flags = prepend_flags.into_iter()
                .map(ToString::to_string)
                .chain(flags)
                .collect();
        } else if line.contains("bindgen-generate-bindings-on-linux-only") &&
          !cfg!(target_os = "linux") {
              return Ok(None);
        }
    }

    // Windows platform has various different conventions than *nix platforms,
    // e.g. default enum underlying type, struct padding, mangling. Most tests
    // were written and checked on Linux and macOS, and thus they could fail on
    // Windows. We just make those tests targetting Linux instead as far as one
    // isn't annotated for a specific target.
    if cfg!(target_os = "windows") {
        if flags.iter().all(|flag| !flag.starts_with("--target=")) {
            if !flags.iter().any(|flag| flag == "--") {
                flags.push("--".into());
            }
            flags.push("--target=x86_64-unknown-linux".into());
        }
    }

    // Fool builder_from_flags() into believing it has real env::args_os...
    // - add "bindgen" as executable name 0th element
    // - add header filename as 1st element
    // - prepend raw lines so they're in the right order for expected output
    // - append the test header's bindgen flags
    let header_str = try!(header.to_str()
        .ok_or(Error::new(ErrorKind::Other, "Invalid header file name")));

    let prepend = ["bindgen",
                   "--with-derive-default",
                   header_str,
                   "--raw-line",
                   "",
                   "--raw-line",
                   "#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]",
                   "--raw-line",
                   ""];

    let args = prepend.into_iter()
        .map(ToString::to_string)
        .chain(flags.into_iter());

    builder_from_flags(args)
        .map(|(builder, _, _)| Some(builder))
}

macro_rules! test_header {
    ($function:ident, $header:expr) => (
        #[test]
        fn $function() {
            let header = PathBuf::from($header);
            let result = create_bindgen_builder(&header)
                .and_then(|builder| {
                    if let Some(builder) = builder {
                        compare_generated_header(&header, builder)
                    } else {
                        Ok(())
                    }
                });

            if let Err(err) = result {
                panic!("{}", err);
            }
        }
    )
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));

#[test]
fn test_header_contents() {
    let bindings = builder()
        .header_contents("test.h", "int foo(const char* a);")
        .generate()
        .unwrap()
        .to_string();
    assert_eq!(bindings, "/* automatically generated by rust-bindgen */

extern \"C\" {
    pub fn foo(a: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int;
}
");
}

#[test]
fn test_multiple_header_calls_in_builder() {
    let actual = builder()
        .header(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/func_ptr.h"))
        .header(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/enum.h"))
        .generate()
        .unwrap()
        .to_string();

    let expected = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/expectations/tests/test_multiple_header_calls_in_builder.rs"));

    if actual != expected {
        println!("Generated bindings differ from expected!");

        for diff in diff::lines(&actual, &expected) {
            match diff {
                diff::Result::Left(l) => println!("-{}", l),
                diff::Result::Both(l, _) => println!(" {}", l),
                diff::Result::Right(r) => println!("+{}", r),
            }
        }

        panic!();
    }
}

#[test]
fn no_system_header_includes() {
    assert!(Command::new("./ci/no-includes.sh")
            .current_dir(env!("CARGO_MANIFEST_DIR"))
            .spawn()
            .expect("should spawn ./ci/no-includes.sh OK")
            .wait()
            .expect("should wait for ./ci/no-includes OK")
            .success());
}

#[test]
fn dump_preprocessed_input() {
    let arg_keyword = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/arg_keyword.hpp");
    let empty_layout = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/cpp-empty-layout.hpp");

    builder()
        .header(arg_keyword)
        .header(empty_layout)
        .dump_preprocessed_input()
        .expect("should dump preprocessed input");

    fn slurp(p: &str) -> String {
        let mut contents = String::new();
        let mut file = fs::File::open(p).unwrap();
        file.read_to_string(&mut contents).unwrap();
        contents
    }

    let bindgen_ii = slurp("__bindgen.ii");
    let arg_keyword = slurp(arg_keyword);
    let empty_layout = slurp(empty_layout);

    assert!(bindgen_ii.find(&arg_keyword).is_some(),
            "arg_keyword.hpp is in the preprocessed file");
    assert!(bindgen_ii.find(&empty_layout).is_some(),
            "cpp-empty-layout.hpp is in the preprocessed file");
}
<|endoftext|>


<commit_before>

// -*- rust -*-
fn main() {
    let a: int = 1;
    let b: int = 2;
    a ^= b;
    b ^= a;
    a = a ^ b;
    log a;
    log b;
    assert (b == 1);
    assert (a == 2);
    assert (!0xf0 & 0xff == 0xf);
    assert (0xf0 | 0xf == 0xff);
    assert (0xf << 4 == 0xf0);
    assert (0xf0 >> 4 == 0xf);
    assert (-16 >>> 2 == -4);
    assert (0b1010_1010 | 0b0101_0101 == 0xff);
    assert (-1000 >> 3 == 536870787);
}
<commit_msg>Make run-pass/bitwise 64-bit compatible<commit_after>// -*- rust -*-

#[cfg(target_arch = "x86")]
fn target() {
    assert (-1000 >> 3 == 536870787);
}

#[cfg(target_arch = "x86_64")]
fn target() {
    // FIXME (974) Can't lex this as a single integer
    assert (-1000 >> 3 == 23058430 * 1000000000 * 100
            + 92 * 100000000 + 13693827);
}

fn general() {
    let a: int = 1;
    let b: int = 2;
    a ^= b;
    b ^= a;
    a = a ^ b;
    log a;
    log b;
    assert (b == 1);
    assert (a == 2);
    assert (!0xf0 & 0xff == 0xf);
    assert (0xf0 | 0xf == 0xff);
    assert (0xf << 4 == 0xf0);
    assert (0xf0 >> 4 == 0xf);
    assert (-16 >>> 2 == -4);
    assert (0b1010_1010 | 0b0101_0101 == 0xff);
}

fn main() {
    general();
    target();
}
<|endoftext|>


<commit_before>// -*- rust -*-

use std;
import std.map;

fn test_simple() {
  log "*** starting test_simple";

  fn eq(&uint x, &uint y) -> bool { ret x == y; }
  fn hash(&uint u) -> uint {
    // FIXME: can't use std.util.id since we'd be capturing a type param,
    // and presently we can't close items over type params.
    ret u;
  }

  let map.hashfn[uint] hasher = hash;
  let map.eqfn[uint] eqer = eq;
  let map.hashmap[uint, uint] hm = map.mk_hashmap[uint, uint](hasher, eqer);
  hm.insert(10u, 12u);
  hm.insert(11u, 13u);
  hm.insert(12u, 14u);

  check (hm.get(11u) == 13u);
  check (hm.get(12u) == 14u);
  check (hm.get(10u) == 12u);

  log "*** finished test_simple";
}

fn main() {
  test_simple();
}
<commit_msg>Test the hashmap for growth and rehashing.<commit_after>// -*- rust -*-

use std;
import std.map;

fn test_simple() {
  log "*** starting test_simple";

  fn eq(&uint x, &uint y) -> bool { ret x == y; }
  fn hash(&uint u) -> uint {
    // FIXME: can't use std.util.id since we'd be capturing a type param,
    // and presently we can't close items over type params.
    ret u;
  }

  // FIXME we don't really want to bind here but if we don't then the
  // hashmap's drop glue UMRs when trying to drop these functions, which
  // it stores internally.
  let map.hashfn[uint] hasher = bind hash(_);
  let map.eqfn[uint] eqer = bind eq(_, _);
  let map.hashmap[uint, uint] hm = map.mk_hashmap[uint, uint](hasher, eqer);

  hm.insert(10u, 12u);
  hm.insert(11u, 13u);
  hm.insert(12u, 14u);

  check (hm.get(11u) == 13u);
  check (hm.get(12u) == 14u);
  check (hm.get(10u) == 12u);

  hm.insert(12u, 14u);
  check (hm.get(12u) == 14u);

  hm.insert(12u, 12u);
  check (hm.get(12u) == 12u);

  log "*** finished test_simple";
}

/**
 * Force map growth and rehashing.
 */
fn test_growth() {
  log "*** starting test_growth";

  let uint map_capacity = 64u;  // Keep in sync with map.mk_hashmap

  fn eq(&uint x, &uint y) -> bool { ret x == y; }
  fn hash(&uint u) -> uint {
    // FIXME: can't use std.util.id since we'd be capturing a type param,
    // and presently we can't close items over type params.
    ret u;
  }

  // FIXME: as in test_simple(), don't really want to bind.
  let map.hashfn[uint] hasher = bind hash(_);
  let map.eqfn[uint] eqer = bind eq(_, _);
  let map.hashmap[uint, uint] hm = map.mk_hashmap[uint, uint](hasher, eqer);

  let uint i = 0u;
  while (i < map_capacity) {
    hm.insert(i, i * i);
    log "inserting " + std._uint.to_str(i, 10u)
      + " -> " + std._uint.to_str(i * i, 10u);
    i += 1u;
  }

  log "-----";

  i = 0u;
  while (i < map_capacity) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 1u;
  }

  hm.insert(map_capacity, 17u);
  check (hm.get(map_capacity) == 17u);

  log "-----";

  hm.rehash();

  i = 0u;
  while (i < map_capacity) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 1u;
  }

  log "*** finished test_growth";
}

fn main() {
  test_simple();
  test_growth();
}
<|endoftext|>


<commit_before>use std;

fn test_init_elt() {
  let vec[uint] v = std._vec.init_elt[uint](uint(5), uint(3));
  check (std._vec.len[uint](v) == uint(3));
  check (v.(0) == uint(5));
  check (v.(1) == uint(5));
  check (v.(2) == uint(5));
}

fn id(uint x) -> uint {
  ret x;
}
fn test_init_fn() {
  let fn(uint)->uint op = id;
  let vec[uint] v = std._vec.init_fn[uint](op, uint(5));
  // FIXME #108: Can't call templated function twice in the same
  // program, at the moment.
  //check (std._vec.len[uint](v) == uint(5));
  check (v.(0) == uint(0));
  check (v.(1) == uint(1));
  check (v.(2) == uint(2));
  check (v.(3) == uint(3));
  check (v.(4) == uint(4));
}

fn test_slice() {
  let vec[int] v = vec(1,2,3,4,5);
  auto v2 = std._vec.slice[int](v, 2, 4);
  // FIXME #108: Can't call templated function twice in the same
  // program, at the moment.
  //check (std._vec.len[int](v2) == uint(2));
  check (v2.(0) == 3);
  check (v2.(1) == 4);
}

fn main() {
  test_init_elt();
  //XFAIL: test_init_fn();  // Segfaults.
  test_slice();
}
<commit_msg>Re-introduce bits of vec-lib test that blocked on now-fixed issue #108.<commit_after>use std;

fn test_init_elt() {
  let vec[uint] v = std._vec.init_elt[uint](uint(5), uint(3));
  check (std._vec.len[uint](v) == uint(3));
  check (v.(0) == uint(5));
  check (v.(1) == uint(5));
  check (v.(2) == uint(5));
}

fn id(uint x) -> uint {
  ret x;
}
fn test_init_fn() {
  let fn(uint)->uint op = id;
  let vec[uint] v = std._vec.init_fn[uint](op, uint(5));
  check (std._vec.len[uint](v) == uint(5));
  check (v.(0) == uint(0));
  check (v.(1) == uint(1));
  check (v.(2) == uint(2));
  check (v.(3) == uint(3));
  check (v.(4) == uint(4));
}

fn test_slice() {
  let vec[int] v = vec(1,2,3,4,5);
  auto v2 = std._vec.slice[int](v, 2, 4);
  check (std._vec.len[int](v2) == uint(2));
  check (v2.(0) == 3);
  check (v2.(1) == 4);
}

fn main() {
  test_init_elt();
  //XFAIL: test_init_fn();  // Segfaults.
  test_slice();
}
<|endoftext|>


<commit_before>#![feature(integer_atomics, i128, i128_type)]
#![allow(blacklisted_name)]
#![deny(replace_consts)]
use std::sync::atomic::*;
use std::sync::{ONCE_INIT, Once};

fn bad() {
    // Once
    { let foo = ONCE_INIT; };
    // Atomic
    { let foo = ATOMIC_BOOL_INIT; };
    { let foo = ATOMIC_ISIZE_INIT; };
    { let foo = ATOMIC_I8_INIT; };
    { let foo = ATOMIC_I16_INIT; };
    { let foo = ATOMIC_I32_INIT; };
    { let foo = ATOMIC_I64_INIT; };
    { let foo = ATOMIC_USIZE_INIT; };
    { let foo = ATOMIC_U8_INIT; };
    { let foo = ATOMIC_U16_INIT; };
    { let foo = ATOMIC_U32_INIT; };
    { let foo = ATOMIC_U64_INIT; };
    // Min
    { let foo = std::isize::MIN; };
    { let foo = std::i8::MIN; };
    { let foo = std::i16::MIN; };
    { let foo = std::i32::MIN; };
    { let foo = std::i64::MIN; };
    { let foo = std::i128::MIN; };
    { let foo = std::usize::MIN; };
    { let foo = std::u8::MIN; };
    { let foo = std::u16::MIN; };
    { let foo = std::u32::MIN; };
    { let foo = std::u64::MIN; };
    { let foo = std::u128::MIN; };
    // Max
    { let foo = std::isize::MAX; };
    { let foo = std::i8::MAX; };
    { let foo = std::i16::MAX; };
    { let foo = std::i32::MAX; };
    { let foo = std::i64::MAX; };
    { let foo = std::i128::MAX; };
    { let foo = std::usize::MAX; };
    { let foo = std::u8::MAX; };
    { let foo = std::u16::MAX; };
    { let foo = std::u32::MAX; };
    { let foo = std::u64::MAX; };
    { let foo = std::u128::MAX; };
}

fn good() {
    // Once
    { let foo = Once::new(); };
    // Atomic
    { let foo = AtomicBool::new(false); };
    { let foo = AtomicIsize::new(0); };
    { let foo = AtomicI8::new(0); };
    { let foo = AtomicI16::new(0); };
    { let foo = AtomicI32::new(0); };
    { let foo = AtomicI64::new(0); };
    { let foo = AtomicUsize::new(0); };
    { let foo = AtomicU8::new(0); };
    { let foo = AtomicU16::new(0); };
    { let foo = AtomicU32::new(0); };
    { let foo = AtomicU64::new(0); };
    // Min
    { let foo = isize::min_value(); };
    { let foo = i8::min_value(); };
    { let foo = i16::min_value(); };
    { let foo = i32::min_value(); };
    { let foo = i64::min_value(); };
    { let foo = i128::min_value(); };
    { let foo = usize::min_value(); };
    { let foo = u8::min_value(); };
    { let foo = u16::min_value(); };
    { let foo = u32::min_value(); };
    { let foo = u64::min_value(); };
    { let foo = u128::min_value(); };
    // Max
    { let foo = isize::max_value(); };
    { let foo = i8::max_value(); };
    { let foo = i16::max_value(); };
    { let foo = i32::max_value(); };
    { let foo = i64::max_value(); };
    { let foo = i128::max_value(); };
    { let foo = usize::max_value(); };
    { let foo = u8::max_value(); };
    { let foo = u16::max_value(); };
    { let foo = u32::max_value(); };
    { let foo = u64::max_value(); };
    { let foo = u128::max_value(); };
}

fn main() {
    bad();
    good();
}
<commit_msg>i128 is stable<commit_after>#![feature(integer_atomics)]
#![allow(blacklisted_name)]
#![deny(replace_consts)]
use std::sync::atomic::*;
use std::sync::{ONCE_INIT, Once};

fn bad() {
    // Once
    { let foo = ONCE_INIT; };
    // Atomic
    { let foo = ATOMIC_BOOL_INIT; };
    { let foo = ATOMIC_ISIZE_INIT; };
    { let foo = ATOMIC_I8_INIT; };
    { let foo = ATOMIC_I16_INIT; };
    { let foo = ATOMIC_I32_INIT; };
    { let foo = ATOMIC_I64_INIT; };
    { let foo = ATOMIC_USIZE_INIT; };
    { let foo = ATOMIC_U8_INIT; };
    { let foo = ATOMIC_U16_INIT; };
    { let foo = ATOMIC_U32_INIT; };
    { let foo = ATOMIC_U64_INIT; };
    // Min
    { let foo = std::isize::MIN; };
    { let foo = std::i8::MIN; };
    { let foo = std::i16::MIN; };
    { let foo = std::i32::MIN; };
    { let foo = std::i64::MIN; };
    { let foo = std::i128::MIN; };
    { let foo = std::usize::MIN; };
    { let foo = std::u8::MIN; };
    { let foo = std::u16::MIN; };
    { let foo = std::u32::MIN; };
    { let foo = std::u64::MIN; };
    { let foo = std::u128::MIN; };
    // Max
    { let foo = std::isize::MAX; };
    { let foo = std::i8::MAX; };
    { let foo = std::i16::MAX; };
    { let foo = std::i32::MAX; };
    { let foo = std::i64::MAX; };
    { let foo = std::i128::MAX; };
    { let foo = std::usize::MAX; };
    { let foo = std::u8::MAX; };
    { let foo = std::u16::MAX; };
    { let foo = std::u32::MAX; };
    { let foo = std::u64::MAX; };
    { let foo = std::u128::MAX; };
}

fn good() {
    // Once
    { let foo = Once::new(); };
    // Atomic
    { let foo = AtomicBool::new(false); };
    { let foo = AtomicIsize::new(0); };
    { let foo = AtomicI8::new(0); };
    { let foo = AtomicI16::new(0); };
    { let foo = AtomicI32::new(0); };
    { let foo = AtomicI64::new(0); };
    { let foo = AtomicUsize::new(0); };
    { let foo = AtomicU8::new(0); };
    { let foo = AtomicU16::new(0); };
    { let foo = AtomicU32::new(0); };
    { let foo = AtomicU64::new(0); };
    // Min
    { let foo = isize::min_value(); };
    { let foo = i8::min_value(); };
    { let foo = i16::min_value(); };
    { let foo = i32::min_value(); };
    { let foo = i64::min_value(); };
    { let foo = i128::min_value(); };
    { let foo = usize::min_value(); };
    { let foo = u8::min_value(); };
    { let foo = u16::min_value(); };
    { let foo = u32::min_value(); };
    { let foo = u64::min_value(); };
    { let foo = u128::min_value(); };
    // Max
    { let foo = isize::max_value(); };
    { let foo = i8::max_value(); };
    { let foo = i16::max_value(); };
    { let foo = i32::max_value(); };
    { let foo = i64::max_value(); };
    { let foo = i128::max_value(); };
    { let foo = usize::max_value(); };
    { let foo = u8::max_value(); };
    { let foo = u16::max_value(); };
    { let foo = u32::max_value(); };
    { let foo = u64::max_value(); };
    { let foo = u128::max_value(); };
}

fn main() {
    bad();
    good();
}
<|endoftext|>