<commit_before>use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use super::parser::{FileHeaderParser, Parser, ParserError};
use storage::file_id::*;

use std::fs::File as FSFile;

#[derive(Debug)]
pub enum FileHeaderSpec {
    Null,
    Bool,
    Integer,
    UInteger,
    Float,
    Text,
    Key { name: &'static str, value_type: Box<FileHeaderSpec> },
    Map { keys: Vec<FileHeaderSpec> },
    Array { allowed_types: Vec<FileHeaderSpec> },
}

#[derive(Debug)]
#[derive(Clone)]
pub enum FileHeaderData {
    Null,
    Bool(bool),
    Integer(i64),
    UInteger(u64),
    Float(f64),
    Text(String),
    Key { name: String, value: Box<FileHeaderData> },
    Map { keys: Vec<FileHeaderData> },
    Array { values: Box<Vec<FileHeaderData>> },
}

impl Display for FileHeaderSpec {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match self {
            &FileHeaderSpec::Null       => write!(fmt, "NULL"),
            &FileHeaderSpec::Bool       => write!(fmt, "Bool"),
            &FileHeaderSpec::Integer    => write!(fmt, "Integer"),
            &FileHeaderSpec::UInteger   => write!(fmt, "UInteger"),
            &FileHeaderSpec::Float      => write!(fmt, "Float"),
            &FileHeaderSpec::Text       => write!(fmt, "Text"),
            &FileHeaderSpec::Key{name: ref n, value_type: ref vt} => {
                write!(fmt, "Key({:?}) -> {:?}", n, vt)
            }
            &FileHeaderSpec::Map{keys: ref ks} => {
                write!(fmt, "Map -> {:?}", ks)
            }
            &FileHeaderSpec::Array{allowed_types: ref at}  => {
                write!(fmt, "Array({:?})", at)
            }
        }
    }

}

pub struct MatchError<'a> {
    summary: String,
    expected: &'a FileHeaderSpec,
    found: &'a FileHeaderData
}

impl<'a> MatchError<'a> {

    pub fn new(s: String,
               ex: &'a FileHeaderSpec,
               found: &'a FileHeaderData) -> MatchError<'a> {
        MatchError {
            summary: s,
            expected: ex,
            found: found,
        }
    }

    pub fn format(&self) -> String {
        format!("MatchError: {:?}\nExpected: {:?}\nFound: {:?}\n",
               self.summary, self.expected, self.found)
    }
}

impl<'a> Error for MatchError<'a> {

    fn description(&self) -> &str {
        &self.summary[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl<'a> Debug for MatchError<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "{}", self.format());
        Ok(())
    }

}

impl<'a> Display for MatchError<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "{}", self.format());
        Ok(())
    }

}

pub fn match_header_spec<'a>(spec: &'a FileHeaderSpec, data: &'a FileHeaderData)
    -> Option<MatchError<'a>>
{
    match (spec, data) {
        (&FileHeaderSpec::Null,     &FileHeaderData::Null)           => { }
        (&FileHeaderSpec::Bool,     &FileHeaderData::Bool(_))        => { }
        (&FileHeaderSpec::Integer,  &FileHeaderData::Integer(_))     => { }
        (&FileHeaderSpec::UInteger, &FileHeaderData::UInteger(_))    => { }
        (&FileHeaderSpec::Float,    &FileHeaderData::Float(_))       => { }
        (&FileHeaderSpec::Text,     &FileHeaderData::Text(_))        => { }

        (
            &FileHeaderSpec::Key{name: ref kname, value_type: ref vtype},
            &FileHeaderData::Key{name: ref n, value: ref val}
        ) => {
            if kname != n {
                unimplemented!();
            }
            return match_header_spec(&*vtype, &*val);
        }

        (
            &FileHeaderSpec::Map{keys: ref sks},
            &FileHeaderData::Map{keys: ref dks}
        ) => {
            for (s, d) in sks.iter().zip(dks.iter()) {
                let res = match_header_spec(s, d);
                if res.is_some() {
                    return res;
                }
            }
        }

        (
            &FileHeaderSpec::Array{allowed_types: ref vtypes},
            &FileHeaderData::Array{values: ref vs}
        ) => {
            for (t, v) in vtypes.iter().zip(vs.iter()) {
                let res = match_header_spec(t, v);
                if res.is_some() {
                    return res;
                }
            }
        }

        (k, v) => {
            return Some(MatchError::new(String::from("Expected type does not match found type"),
                                 k, v
                                 ))
        }
    }
    None
}

/*
 * Internal abstract view on a file. Does not exist on the FS and is just kept
 * internally until it is written to disk.
 */
pub struct File {
    header  : FileHeaderData,
    data    : String,
    id      : FileID,
}

impl File {

    pub fn new() -> File {
        File {
            header: FileHeaderData::Null,
            data: String::from(""),
            id: File::get_new_file_id(),
        }
    }

    pub fn from_parser_result(id: FileID, header: FileHeaderData, data: String) -> File {
        File {
            header: header,
            data: data,
            id: id,
        }
    }

    pub fn new_with_header(h: FileHeaderData) -> File {
        File {
            header: h,
            data: String::from(""),
            id: File::get_new_file_id(),
        }
    }

    pub fn new_with_data(d: String) -> File {
        File {
            header: FileHeaderData::Null,
            data: d,
            id: File::get_new_file_id(),
        }
    }

    pub fn new_with_content(h: FileHeaderData, d: String) -> File {
        File {
            header: h,
            data: d,
            id: File::get_new_file_id(),
        }
    }

    pub fn contents(&self) -> (FileHeaderData, String) {
        (self.header, self.data)
    }

    pub fn id(&self) -> FileID {
        self.id
    }

    fn get_new_file_id() -> FileID {
        use uuid::Uuid;
        Uuid::new_v4().to_hyphenated_string()
    }
}

<commit_msg>Clone these values when returning them<commit_after>use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use super::parser::{FileHeaderParser, Parser, ParserError};
use storage::file_id::*;

use std::fs::File as FSFile;

#[derive(Debug)]
pub enum FileHeaderSpec {
    Null,
    Bool,
    Integer,
    UInteger,
    Float,
    Text,
    Key { name: &'static str, value_type: Box<FileHeaderSpec> },
    Map { keys: Vec<FileHeaderSpec> },
    Array { allowed_types: Vec<FileHeaderSpec> },
}

#[derive(Debug)]
#[derive(Clone)]
pub enum FileHeaderData {
    Null,
    Bool(bool),
    Integer(i64),
    UInteger(u64),
    Float(f64),
    Text(String),
    Key { name: String, value: Box<FileHeaderData> },
    Map { keys: Vec<FileHeaderData> },
    Array { values: Box<Vec<FileHeaderData>> },
}

impl Display for FileHeaderSpec {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match self {
            &FileHeaderSpec::Null       => write!(fmt, "NULL"),
            &FileHeaderSpec::Bool       => write!(fmt, "Bool"),
            &FileHeaderSpec::Integer    => write!(fmt, "Integer"),
            &FileHeaderSpec::UInteger   => write!(fmt, "UInteger"),
            &FileHeaderSpec::Float      => write!(fmt, "Float"),
            &FileHeaderSpec::Text       => write!(fmt, "Text"),
            &FileHeaderSpec::Key{name: ref n, value_type: ref vt} => {
                write!(fmt, "Key({:?}) -> {:?}", n, vt)
            }
            &FileHeaderSpec::Map{keys: ref ks} => {
                write!(fmt, "Map -> {:?}", ks)
            }
            &FileHeaderSpec::Array{allowed_types: ref at}  => {
                write!(fmt, "Array({:?})", at)
            }
        }
    }

}

pub struct MatchError<'a> {
    summary: String,
    expected: &'a FileHeaderSpec,
    found: &'a FileHeaderData
}

impl<'a> MatchError<'a> {

    pub fn new(s: String,
               ex: &'a FileHeaderSpec,
               found: &'a FileHeaderData) -> MatchError<'a> {
        MatchError {
            summary: s,
            expected: ex,
            found: found,
        }
    }

    pub fn format(&self) -> String {
        format!("MatchError: {:?}\nExpected: {:?}\nFound: {:?}\n",
               self.summary, self.expected, self.found)
    }
}

impl<'a> Error for MatchError<'a> {

    fn description(&self) -> &str {
        &self.summary[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl<'a> Debug for MatchError<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "{}", self.format());
        Ok(())
    }

}

impl<'a> Display for MatchError<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "{}", self.format());
        Ok(())
    }

}

pub fn match_header_spec<'a>(spec: &'a FileHeaderSpec, data: &'a FileHeaderData)
    -> Option<MatchError<'a>>
{
    match (spec, data) {
        (&FileHeaderSpec::Null,     &FileHeaderData::Null)           => { }
        (&FileHeaderSpec::Bool,     &FileHeaderData::Bool(_))        => { }
        (&FileHeaderSpec::Integer,  &FileHeaderData::Integer(_))     => { }
        (&FileHeaderSpec::UInteger, &FileHeaderData::UInteger(_))    => { }
        (&FileHeaderSpec::Float,    &FileHeaderData::Float(_))       => { }
        (&FileHeaderSpec::Text,     &FileHeaderData::Text(_))        => { }

        (
            &FileHeaderSpec::Key{name: ref kname, value_type: ref vtype},
            &FileHeaderData::Key{name: ref n, value: ref val}
        ) => {
            if kname != n {
                unimplemented!();
            }
            return match_header_spec(&*vtype, &*val);
        }

        (
            &FileHeaderSpec::Map{keys: ref sks},
            &FileHeaderData::Map{keys: ref dks}
        ) => {
            for (s, d) in sks.iter().zip(dks.iter()) {
                let res = match_header_spec(s, d);
                if res.is_some() {
                    return res;
                }
            }
        }

        (
            &FileHeaderSpec::Array{allowed_types: ref vtypes},
            &FileHeaderData::Array{values: ref vs}
        ) => {
            for (t, v) in vtypes.iter().zip(vs.iter()) {
                let res = match_header_spec(t, v);
                if res.is_some() {
                    return res;
                }
            }
        }

        (k, v) => {
            return Some(MatchError::new(String::from("Expected type does not match found type"),
                                 k, v
                                 ))
        }
    }
    None
}

/*
 * Internal abstract view on a file. Does not exist on the FS and is just kept
 * internally until it is written to disk.
 */
pub struct File {
    header  : FileHeaderData,
    data    : String,
    id      : FileID,
}

impl File {

    pub fn new() -> File {
        File {
            header: FileHeaderData::Null,
            data: String::from(""),
            id: File::get_new_file_id(),
        }
    }

    pub fn from_parser_result(id: FileID, header: FileHeaderData, data: String) -> File {
        File {
            header: header,
            data: data,
            id: id,
        }
    }

    pub fn new_with_header(h: FileHeaderData) -> File {
        File {
            header: h,
            data: String::from(""),
            id: File::get_new_file_id(),
        }
    }

    pub fn new_with_data(d: String) -> File {
        File {
            header: FileHeaderData::Null,
            data: d,
            id: File::get_new_file_id(),
        }
    }

    pub fn new_with_content(h: FileHeaderData, d: String) -> File {
        File {
            header: h,
            data: d,
            id: File::get_new_file_id(),
        }
    }

    pub fn contents(&self) -> (FileHeaderData, String) {
        (self.header.clone(), self.data.clone())
    }

    pub fn id(&self) -> FileID {
        self.id.clone()
    }

    fn get_new_file_id() -> FileID {
        use uuid::Uuid;
        Uuid::new_v4().to_hyphenated_string()
    }
}

<|endoftext|>


<commit_before><commit_msg>Added modified list<commit_after><|endoftext|>


<commit_before>// this module adds some functionality based on the required implementations
// here like: `LinkedList::pop_back` or `Clone for LinkedList<T>`
// You are free to use anything in it, but it's mainly for the test framework.
mod pre_implemented;

pub struct LinkedList<T>(std::marker::PhantomData<T>);

pub struct Cursor<'a, T: 'a>(std::marker::PhantomData<&'a mut T>);

pub struct Iter<'a, T: 'a>(std::marker::PhantomData<&'a T>);

impl<T> LinkedList<T> {
    pub fn new() -> Self {
        unimplemented!()
    }

    pub fn len(&self) -> usize {
        unimplemented!()
    }

    /// Return a cursor positioned on the front element
    pub fn cursor_front(&mut self) -> Cursor<'_, T> {
        unimplemented!()
    }

    /// Return a cursor positioned on the back element
    pub fn cursor_back(&mut self) -> Cursor<'_, T> {
        unimplemented!()
    }

    /// Return an iterator that moves from front to back
    pub fn iter(&self) -> Iter<'_, T> {
        unimplemented!()
    }
}

impl<T> Drop for LinkedList<T> {
    fn drop(&mut self) {
        unimplemented!()
    }
}

// the cursor is expected to act as if it is at the position of a node
impl<'a, T: 'a> Cursor<'a, T> {
    /// Take a mutable reference to the current element
    pub fn peek_mut(&mut self) -> Option<&mut T> {
        unimplemented!()
    }

    /// Move one position forward and return a reference to the new position
    pub fn next(&mut self) -> Option<&mut T> {
        unimplemented!()
    }

    /// Move one position backward and return a reference to the new position
    pub fn prev(&mut self) -> Option<&mut T> {
        unimplemented!()
    }

    /// Remove the element at the current node from the list and return it.
    pub fn take(&mut self) -> Option<T> {
        unimplemented!()
    }

    pub fn insert_after(&mut self, _element: T) {
        unimplemented!()
    }

    pub fn insert_before(&mut self, _element: T) {
        unimplemented!()
    }
}

impl<'a, T: 'a> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        unimplemented!()
    }
}
<commit_msg>linked-list: clarify behaviour of next, prev, take<commit_after>// this module adds some functionality based on the required implementations
// here like: `LinkedList::pop_back` or `Clone for LinkedList<T>`
// You are free to use anything in it, but it's mainly for the test framework.
mod pre_implemented;

pub struct LinkedList<T>(std::marker::PhantomData<T>);

pub struct Cursor<'a, T: 'a>(std::marker::PhantomData<&'a mut T>);

pub struct Iter<'a, T: 'a>(std::marker::PhantomData<&'a T>);

impl<T> LinkedList<T> {
    pub fn new() -> Self {
        unimplemented!()
    }

    pub fn len(&self) -> usize {
        unimplemented!()
    }

    /// Return a cursor positioned on the front element
    pub fn cursor_front(&mut self) -> Cursor<'_, T> {
        unimplemented!()
    }

    /// Return a cursor positioned on the back element
    pub fn cursor_back(&mut self) -> Cursor<'_, T> {
        unimplemented!()
    }

    /// Return an iterator that moves from front to back
    pub fn iter(&self) -> Iter<'_, T> {
        unimplemented!()
    }
}

impl<T> Drop for LinkedList<T> {
    fn drop(&mut self) {
        unimplemented!()
    }
}

// the cursor is expected to act as if it is at the position of an element
impl<'a, T: 'a> Cursor<'a, T> {
    /// Take a mutable reference to the current element
    pub fn peek_mut(&mut self) -> Option<&mut T> {
        unimplemented!()
    }

    /// Move one position forward (towards the back) and
    /// return a reference to the new position
    pub fn next(&mut self) -> Option<&mut T> {
        unimplemented!()
    }

    /// Move one position backward (towards the front) and
    /// return a reference to the new position
    pub fn prev(&mut self) -> Option<&mut T> {
        unimplemented!()
    }

    /// Remove and return the element at the current position and move the cursor
    /// to the neighboring element that's closest to the back. This can be
    /// either the next or previous position.
    pub fn take(&mut self) -> Option<T> {
        unimplemented!()
    }

    pub fn insert_after(&mut self, _element: T) {
        unimplemented!()
    }

    pub fn insert_before(&mut self, _element: T) {
        unimplemented!()
    }
}

impl<'a, T: 'a> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove add_entry.rs<commit_after><|endoftext|>


<commit_before>use std::ptr;

struct TssContext { handle: u32 }
struct TssTpm { handle: u32 }

type TssHContext = u32;
type TssHTPM = u32;
type TssResult = u32;
type TssUnicode = u16;

const TSS_SUCCESS: TssResult = 0;

#[link(name = "tspi")]
extern {
    fn Tspi_Context_Create(phContext: *mut TssHContext) -> TssResult;
    fn Tspi_Context_Connect(phContext: TssHContext, wszDestination: *const TssUnicode) -> TssResult;
    fn Tspi_Context_GetTpmObject(phContext: TssHContext, phTPM: *mut TssHTPM) -> TssResult;
    fn Tspi_Context_Close(phContext: TssHContext) -> TssResult;
    fn Tspi_TPM_PcrRead(hTPM: TssHTPM, ulPcrIndex: u32, pulPcrValueLength: *mut u32, prgbPcrValue: *mut *mut u8) -> TssResult;
}

impl TssContext {
    fn new() -> Result<TssContext, TssResult> {
        unsafe {
            let mut handle = 0;
            let result = Tspi_Context_Create(&mut handle);
            if result != TSS_SUCCESS {
                Err(result)
            } else {
                Ok(TssContext { handle: handle })
            }
        }
    }

    // TODO: support destination
    fn connect(&self) -> Result<(), TssResult> {
        unsafe {
            let result = Tspi_Context_Connect(self.handle, ptr::null());
            if result != TSS_SUCCESS {
                Err(result)
            } else {
                Ok(())
            }
        }
    }

    fn get_tpm_object(&self) -> Result<TssTpm, TssResult> {
        unsafe {
            let mut handle = 0;
            let result = Tspi_Context_GetTpmObject(self.handle, &mut handle);
            if result != TSS_SUCCESS {
                Err(result)
            } else {
                Ok(TssTpm { handle: handle })
            }
        }
    }
}

impl Drop for TssContext {
    fn drop(&mut self) {
        unsafe {
            Tspi_Context_Close(self.handle);
        }
    }
}

impl TssTpm {
    fn pcr_read(&self, pcr_index: u32) -> Result<Vec<u8>, TssResult> {
        unsafe {
            let mut ulPcrValueLength = -1;
            let mut pRgbPcrValue = 0 as *mut u8;
            let result = Tspi_TPM_PcrRead(self.handle, pcr_index, &mut ulPcrValueLength, &mut pRgbPcrValue);
            if result != TSS_SUCCESS {
                Err(result)
            } else {
                let mut vec = Vec::new();
                for i in 0..ulPcrValueLength {
                    vec.push(*pRgbPcrValue.offset(i as isize));
                }
                Ok(vec)
                // Need to free
            }
        }
    }
}

fn main() {
    // TODO: Any cleaner way to write this?
    let contextresult = TssContext::new();
    if let Ok(context) = contextresult {
        if let Ok(_) = context.connect() {
            if let Ok(tpm) = context.get_tpm_object() {
                println!("I'M IN UR TPM READING UR PCRZ (From Rust!)");
                println!("TPM handle: {:?}", tpm.handle);
                for i in 0..24 {
                    if let Ok(vec) = tpm.pcr_read(i) {
                        print!("PCR {:02}", i);
                        for j in 0..19 {
                            print!(" {:02X}", vec[j]);
                        }
                        print!("\n");
                    }
                }
            } else {
                println!("Failed to get TPM handle :(")
            }
        } else {
            println!("Failed to connect :(");
        }
    } else {
        println!("Failed :(");
    }

    /*
    match blah {
        Ok(context) => println!("Context created! {:?}", context.handle),
        Err(e) => println!("Context failed with err {:?}", e),
    }
    println!("Hello world!");
    */
}
<commit_msg>Add Tspi_Context_FreeMemory, TPM context lifetime<commit_after>use std::ptr;

struct TssContext { handle: u32 }
struct TssTpm<'context> { context: &'context TssContext, handle: u32 }

type TssHContext = u32;
type TssHTPM = u32;
type TssResult = u32;
type TssUnicode = u16;

const TSS_SUCCESS: TssResult = 0;

#[link(name = "tspi")]
extern {
    fn Tspi_Context_Create(phContext: *mut TssHContext) -> TssResult;
    fn Tspi_Context_Connect(phContext: TssHContext, wszDestination: *const TssUnicode) -> TssResult;
    fn Tspi_Context_GetTpmObject(phContext: TssHContext, phTPM: *mut TssHTPM) -> TssResult;
    fn Tspi_Context_FreeMemory(phContext: TssHContext, rgbMemory: *mut u8) -> TssResult;
    fn Tspi_Context_Close(phContext: TssHContext) -> TssResult;
    fn Tspi_TPM_PcrRead(hTPM: TssHTPM, ulPcrIndex: u32, pulPcrValueLength: *mut u32, prgbPcrValue: *mut *mut u8) -> TssResult;
}

impl TssContext {
    fn new() -> Result<TssContext, TssResult> {
        unsafe {
            let mut handle = 0;
            let result = Tspi_Context_Create(&mut handle);
            if result != TSS_SUCCESS {
                Err(result)
            } else {
                Ok(TssContext { handle: handle })
            }
        }
    }

    // TODO: support destination
    fn connect(&self) -> Result<(), TssResult> {
        unsafe {
            let result = Tspi_Context_Connect(self.handle, ptr::null());
            if result != TSS_SUCCESS {
                Err(result)
            } else {
                Ok(())
            }
        }
    }

    fn get_tpm_object(&self) -> Result<TssTpm, TssResult> {
        unsafe {
            let mut handle = 0;
            let result = Tspi_Context_GetTpmObject(self.handle, &mut handle);
            if result != TSS_SUCCESS {
                Err(result)
            } else {
                Ok(TssTpm { context: self, handle: handle })
            }
        }
    }
}

impl Drop for TssContext {
    fn drop(&mut self) {
        unsafe {
            Tspi_Context_Close(self.handle);
        }
    }
}

impl<'context> TssTpm<'context> {
    fn pcr_read(&self, pcr_index: u32) -> Result<Vec<u8>, TssResult> {
        unsafe {
            let mut ulPcrValueLength = -1;
            let mut pRgbPcrValue = 0 as *mut u8;
            let result = Tspi_TPM_PcrRead(self.handle, pcr_index, &mut ulPcrValueLength, &mut pRgbPcrValue);
            if result != TSS_SUCCESS {
                Err(result)
            } else {
                let mut vec = Vec::new();
                for i in 0..ulPcrValueLength {
                    vec.push(*pRgbPcrValue.offset(i as isize));
                }
                Tspi_Context_FreeMemory(self.context.handle, pRgbPcrValue);
                Ok(vec)
            }
        }
    }
}

fn main() {
    // TODO: Any cleaner way to write this?
    let contextresult = TssContext::new();
    if let Ok(context) = contextresult {
        if let Ok(_) = context.connect() {
            if let Ok(tpm) = context.get_tpm_object() {
                println!("I'M IN UR TPM READING UR PCRZ (From Rust!)");
                println!("TPM handle: {:?}", tpm.handle);
                for i in 0..24 {
                    if let Ok(vec) = tpm.pcr_read(i) {
                        print!("PCR {:02}", i);
                        for j in 0..19 {
                            print!(" {:02X}", vec[j]);
                        }
                        print!("\n");
                    }
                }
            } else {
                println!("Failed to get TPM handle :(")
            }
        } else {
            println!("Failed to connect :(");
        }
    } else {
        println!("Failed :(");
    }

    /*
    match blah {
        Ok(context) => println!("Context created! {:?}", context.handle),
        Err(e) => println!("Context failed with err {:?}", e),
    }
    println!("Hello world!");
    */
}
<|endoftext|>


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

// The config holds the options that define the testing environment.
// A config entry starts with "//!", differentiating it from a directive.

use crate::errors::*;
use std::{
    collections::{btree_map, BTreeMap},
    str::FromStr,
};
use vm_runtime_tests::account::AccountData;

// unit: microlibra
const DEFAULT_BALANCE: u64 = 1_000_000;

/// Struct that specifies the initial setup of an account.
#[derive(Debug)]
pub struct AccountDefinition {
    /// Name of the account. The name is case insensitive.
    pub name: String,
    /// The initial balance of the account.
    pub balance: Option<u64>,
    /// The initial sequence number  of the account.
    pub sequence_number: Option<u64>,
}

/// A raw entry extracted from the input. Used to build the global config table.
#[derive(Debug)]
pub enum Entry {
    /// Defines an account that can be used in tests.
    AccountDefinition(AccountDefinition),
}

impl FromStr for Entry {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        let s1 = s.trim_start().trim_end();
        if !s1.starts_with("//!") {
            return Err(
                ErrorKind::Other("global config entry must start with //!".to_string()).into(),
            );
        }
        let s2 = s1[3..].trim_start();
        if s2.starts_with("account:") {
            let v: Vec<_> = s2[8..]
                .split(|c: char| c == ',' || c.is_whitespace())
                .filter(|s| !s.is_empty())
                .collect();
            if v.is_empty() || v.len() > 3 {
                return Err(ErrorKind::Other(
                    "config 'account' takes 1 to 3 parameters".to_string(),
                )
                .into());
            }
            let balance = match v.get(1) {
                Some(s) => Some(s.parse::<u64>()?),
                None => None,
            };
            let sequence_number = match v.get(2) {
                Some(s) => Some(s.parse::<u64>()?),
                None => None,
            };
            return Ok(Entry::AccountDefinition(AccountDefinition {
                name: v[0].to_string(),
                balance,
                sequence_number,
            }));
        }
        Err(ErrorKind::Other(format!("failed to parse '{}' as global config entry", s)).into())
    }
}

/// A table of options either shared by all transactions or used to define the testing environment.
#[derive(Debug)]
pub struct Config {
    /// A map from account names to account data
    pub accounts: BTreeMap<String, AccountData>,
}

impl Config {
    pub fn build(entries: &[Entry]) -> Result<Self> {
        let mut accounts = BTreeMap::new();
        for entry in entries {
            match entry {
                Entry::AccountDefinition(def) => {
                    let account_data = AccountData::new(
                        def.balance.unwrap_or(DEFAULT_BALANCE),
                        def.sequence_number.unwrap_or(0),
                    );
                    let name = def.name.to_ascii_lowercase();
                    let entry = accounts.entry(name);
                    match entry {
                        btree_map::Entry::Vacant(entry) => {
                            entry.insert(account_data);
                        }
                        btree_map::Entry::Occupied(_) => {
                            return Err(ErrorKind::Other(format!(
                                "already has account '{}'",
                                def.name,
                            ))
                            .into());
                        }
                    }
                }
            }
        }

        if let btree_map::Entry::Vacant(entry) = accounts.entry("default".to_string()) {
            entry.insert(AccountData::new(DEFAULT_BALANCE, 0));
        }
        println!("{:?}", accounts);
        Ok(Config { accounts })
    }
}
<commit_msg>[functional tests] remove println!<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

// The config holds the options that define the testing environment.
// A config entry starts with "//!", differentiating it from a directive.

use crate::errors::*;
use std::{
    collections::{btree_map, BTreeMap},
    str::FromStr,
};
use vm_runtime_tests::account::AccountData;

// unit: microlibra
const DEFAULT_BALANCE: u64 = 1_000_000;

/// Struct that specifies the initial setup of an account.
#[derive(Debug)]
pub struct AccountDefinition {
    /// Name of the account. The name is case insensitive.
    pub name: String,
    /// The initial balance of the account.
    pub balance: Option<u64>,
    /// The initial sequence number  of the account.
    pub sequence_number: Option<u64>,
}

/// A raw entry extracted from the input. Used to build the global config table.
#[derive(Debug)]
pub enum Entry {
    /// Defines an account that can be used in tests.
    AccountDefinition(AccountDefinition),
}

impl FromStr for Entry {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        let s1 = s.trim_start().trim_end();
        if !s1.starts_with("//!") {
            return Err(
                ErrorKind::Other("global config entry must start with //!".to_string()).into(),
            );
        }
        let s2 = s1[3..].trim_start();
        if s2.starts_with("account:") {
            let v: Vec<_> = s2[8..]
                .split(|c: char| c == ',' || c.is_whitespace())
                .filter(|s| !s.is_empty())
                .collect();
            if v.is_empty() || v.len() > 3 {
                return Err(ErrorKind::Other(
                    "config 'account' takes 1 to 3 parameters".to_string(),
                )
                .into());
            }
            let balance = match v.get(1) {
                Some(s) => Some(s.parse::<u64>()?),
                None => None,
            };
            let sequence_number = match v.get(2) {
                Some(s) => Some(s.parse::<u64>()?),
                None => None,
            };
            return Ok(Entry::AccountDefinition(AccountDefinition {
                name: v[0].to_string(),
                balance,
                sequence_number,
            }));
        }
        Err(ErrorKind::Other(format!("failed to parse '{}' as global config entry", s)).into())
    }
}

/// A table of options either shared by all transactions or used to define the testing environment.
#[derive(Debug)]
pub struct Config {
    /// A map from account names to account data
    pub accounts: BTreeMap<String, AccountData>,
}

impl Config {
    pub fn build(entries: &[Entry]) -> Result<Self> {
        let mut accounts = BTreeMap::new();
        for entry in entries {
            match entry {
                Entry::AccountDefinition(def) => {
                    let account_data = AccountData::new(
                        def.balance.unwrap_or(DEFAULT_BALANCE),
                        def.sequence_number.unwrap_or(0),
                    );
                    let name = def.name.to_ascii_lowercase();
                    let entry = accounts.entry(name);
                    match entry {
                        btree_map::Entry::Vacant(entry) => {
                            entry.insert(account_data);
                        }
                        btree_map::Entry::Occupied(_) => {
                            return Err(ErrorKind::Other(format!(
                                "already has account '{}'",
                                def.name,
                            ))
                            .into());
                        }
                    }
                }
            }
        }

        if let btree_map::Entry::Vacant(entry) = accounts.entry("default".to_string()) {
            entry.insert(AccountData::new(DEFAULT_BALANCE, 0));
        }
        Ok(Config { accounts })
    }
}
<|endoftext|>


<commit_before>extern crate r6;
extern crate env_logger;

use std::old_io::BufReader;
use std::sync::{Once, ONCE_INIT};
use r6::runtime::Runtime;
use r6::compiler::Compiler;
use r6::base::libbase;
use r6::parser::Parser;

static START: Once = ONCE_INIT;

macro_rules! assert_evaluates_to {
    ($src:expr, $expected:expr) => (
        {
            START.call_once(|| {
                env_logger::init().unwrap();
            });
            let mut src_reader = BufReader::new($src.as_bytes());
            let mut src_parser = Parser::new(&mut src_reader);
            let sourcecode = match src_parser.parse_datum() {
                Ok(code) => code,
                Err(e) => panic!("failed to parse source: {:?}", e)
            };

            let mut res_reader = BufReader::new($expected.as_bytes());
            let mut res_parser = Parser::new(&mut res_reader);
            let expected = match res_parser.parse_datum() {
                Ok(val) => val,
                Err(e) => panic!("failed to parse result: {:?}", e)
            };

            let base = libbase();
            let compiler = Compiler::new(&base);
            let bytecode = match compiler.compile(&sourcecode) {
                Ok(code) => code,
                Err(e) => panic!("compile failure: {:?}", e)
            };
            let mut runtime = Runtime::new(bytecode);
            let result = runtime.run();
            if !((result == expected) && (expected == result)) {
                panic!("test failed: expected `{:?}` but got `{:?}`", expected, result);
            }
        }
    )
}

macro_rules! assert_evaluates_datum {
    ($src:expr, $expected:expr) => (
        {
            let mut src_reader = BufReader::new($src.as_bytes());
            let mut src_parser = Parser::new(&mut src_reader);
            let sourcecode = match src_parser.parse_datum() {
                Ok(code) => code,
                Err(e) => panic!("failed to parse source: {:?}", e)
            };

            let base = libbase();
            let compiler = Compiler::new(&base);
            let bytecode = match compiler.compile(&sourcecode) {
                Ok(code) => code,
                Err(e) => panic!("compile failure: {:?}", e)
            };
            let mut runtime = Runtime::new(bytecode);
            let result = runtime.run();
            if !((result == $expected) && ($expected == result)) {
                panic!("test failed: expected `{:?}` but got `{:?}`", $expected, result);
            }
        }
    )
}

#[test]
fn lexical_scoping() {
    // (\y f -> f 2) #f ((\y -> (\x -> y)) #t)
    // If it's dynamic scope, it should return 0
    // If it's static scope, it should return 1
    assert_evaluates_to!("((lambda (y f) (f 2)) #f ((lambda (y) (lambda (x) y)) #t))", "#t")
}

#[test]
fn lambda_test() {
    assert_evaluates_to!("((lambda (x) (+ x x)) 4)", "8");
}

#[test]
fn var_arg_test() {
    assert_evaluates_to!("((lambda (x y . z) z) 3 4 5 6)", "(5 6)");
}

#[test]
fn local_define_test() {
    assert_evaluates_to!("(let ((x 5)) (define (foo y) (bar x y)) (define (bar a b) (+ (* a b) a)) (foo (+ x 3)))", "45");
}

#[test]
fn if_expression_test() {
    assert_evaluates_to!("(if #t 1 0)", "1");
    assert_evaluates_to!("(if #f 1 0)", "0");
}

#[test]
fn eval_to_self_test() {
    assert_evaluates_to!("#t", "#t");
    assert_evaluates_to!("23", "23");
}

#[test]
fn numeric_expressions_test() {
    assert_evaluates_to!("(+ 23 42)", "65");
    assert_evaluates_to!("(+ 14 (* 23 42))", "980");
    assert_evaluates_to!("(- 3 1)", "2");
    assert_evaluates_to!("(- 3)", "-3");
    assert_evaluates_to!("(/ 3 2)", "3/2");
    assert_evaluates_to!("(/ 3.0 2)", "1.5");
}

#[test]
fn let_test() {
    assert_evaluates_to!("(let ((x 23) (y 42)) (+ x y))", "65");
}

#[test]
fn override_syntax_test() {
    assert_evaluates_to!("(let ((if (lambda (x) x))) (if 3))", "3");
}

#[test]
fn let_star_test() {
    assert_evaluates_to!("(let ((x 2) (y 3)) (let* ((x 7) (z (+ x y))) (* z x)))", "70");
}

#[test]
fn letrec_test() {
    assert_evaluates_to!("(letrec ((even? (lambda (n) (if (zero? n) #t (odd? (- n 1))))) (odd? (lambda (n) (if (zero? n) #f (even? (- n 1)))))) (even? 8))", "#t");
}

#[test]
fn letrec_undefined_test() {
    use r6::datum::Datum;
    use r6::runtime::RuntimeData;

    assert_evaluates_datum!(
        "(letrec ((quicksand quicksand)) quicksand)",
        Datum::Ext(RuntimeData::Undefined)
    );
}

#[test]
fn set_test() {
    assert_evaluates_to!("(let ((x 23)) (set! x 24) x)", "24");
}

#[test]
fn list_test() {
    assert_evaluates_to!("(list 1 2 3)", "(1 2 3)");
    assert_evaluates_to!("(list)", "()");
}

#[test]
fn quote_test() {
    assert_evaluates_to!(r#"(quote a)"#, "a");
    assert_evaluates_to!(r#"(quote (1 2 3))"#, "(1 2 3)");
    assert_evaluates_to!(r#"(quote #\a)"#, r#"#\a"#);
}

#[test]
fn quote_abbrev_test() {
    assert_evaluates_to!(r#"'a"#, "a");
    assert_evaluates_to!(r#"'(1 2 3)"#, "(1 2 3)");
    assert_evaluates_to!(r#"'#\a"#, r#"#\a"#);
}

#[test]
fn typecheck_test() {
    assert_evaluates_to!("(boolean? #t)", "#t");
    assert_evaluates_to!("(boolean? #f)", "#t");
    assert_evaluates_to!("(boolean? 1)", "#f");

    assert_evaluates_to!("(pair? (list 1 2))", "#t");
    assert_evaluates_to!("(pair? (list))", "#f");
    assert_evaluates_to!("(pair? 1)", "#f");

    assert_evaluates_to!(r#"(symbol? #\a)"#, "#f");
    assert_evaluates_to!(r#"(symbol? 'a)"#, "#t");

    assert_evaluates_to!(r#"(char? #\a)"#, "#t");
    assert_evaluates_to!(r#"(char? 'a)"#, "#f");

    assert_evaluates_to!(r#"(string? "a")"#, "#t");
    assert_evaluates_to!(r#"(string? 'a)"#, "#f");

    assert_evaluates_to!(r#"(procedure? +)"#, "#t");
    assert_evaluates_to!(r#"(procedure? '+)"#, "#f");

    assert_evaluates_to!(r#"(null? (list))"#, "#t");
    assert_evaluates_to!(r#"(null? (list 1 2))"#, "#f");

    assert_evaluates_to!(r#"(vector? #(a b c))"#, "#t");
    assert_evaluates_to!(r#"(vector? (list 1 2))"#, "#f");
}

#[test]
fn car_test() {
    assert_evaluates_to!("(car '(a b))", "a");
}

#[test]
fn cdr_test() {
    assert_evaluates_to!("(cdr '(a b))", "(b)");
}

#[test]
fn number_predicates_test() {
    assert_evaluates_to!("(zero? 0)", "#t");
    assert_evaluates_to!("(zero? +0.0)", "#t");
    assert_evaluates_to!("(zero? -0.0)", "#t");
    assert_evaluates_to!("(zero? +nan.0)", "#f");
}

#[test]
fn number_type_test() {
    assert_evaluates_to!("(complex? 3+4i)", "#t");
    assert_evaluates_to!("(complex? 3)", "#t");
    assert_evaluates_to!("(real? 3)", "#t");
    assert_evaluates_to!("(real? -2.5+0.0i)", "#f");
    assert_evaluates_to!("(real? -2.5+0i)", "#t");
    assert_evaluates_to!("(real? -2.5)", "#t");
    assert_evaluates_to!("(real? #e1e10)", "#t");
    assert_evaluates_to!("(rational? 6/10)", "#t");
    assert_evaluates_to!("(rational? 6/3)", "#t");
    assert_evaluates_to!("(rational? 2)", "#t");
    assert_evaluates_to!("(integer? 3+0i)", "#t");
    assert_evaluates_to!("(integer? 3.0)", "#t");
    assert_evaluates_to!("(integer? 8/4)", "#t");
    assert_evaluates_to!("(number? +nan.0)", "#t");
    assert_evaluates_to!("(complex? +nan.0)", "#t");
    assert_evaluates_to!("(real? +nan.0)", "#t");
    assert_evaluates_to!("(rational? +nan.0)", "#f");
    assert_evaluates_to!("(complex? +inf.0)", "#t");
    assert_evaluates_to!("(real? -inf.0)", "#t");
    assert_evaluates_to!("(rational? -inf.0)", "#f");
    assert_evaluates_to!("(integer? -inf.0)", "#f");
}

#[test]
fn number_eq_test() {
    assert_evaluates_to!("(= 2 2)", "#t");
    assert_evaluates_to!("(= +inf.0 +inf.0)", "#t");
    assert_evaluates_to!("(= -inf.0 +inf.0)", "#f");
    assert_evaluates_to!("(= -inf.0 -inf.0)", "#t");

    assert_evaluates_to!("(< -inf.0 2 +inf.0)", "#t");
    assert_evaluates_to!("(> +inf.0 2 -inf.0)", "#t");

    assert_evaluates_to!("(= +nan.0 2)", "#f");
    assert_evaluates_to!("(= +nan.0 +nan.0)", "#f");

    assert_evaluates_to!("(< +nan.0 2)", "#f");
    assert_evaluates_to!("(< +nan.0 +nan.0)", "#f");

    assert_evaluates_to!("(> +nan.0 2)", "#f");
    assert_evaluates_to!("(> +nan.0 +nan.0)", "#f");
}

#[test]
fn and_or_test() {
    assert_evaluates_to!("(and (= 2 2) (> 2 1))", "#t");
    assert_evaluates_to!("(and (= 2 2) (< 2 1))", "#f");
    assert_evaluates_to!("(and 1 2 'c '(f g))", "(f g)");
    assert_evaluates_to!("(and)", "#t");
}
<commit_msg>Rust changes: Add feature gating to io<commit_after>#![feature(io)]

extern crate r6;
extern crate env_logger;

use std::old_io::BufReader;
use std::sync::{Once, ONCE_INIT};
use r6::runtime::Runtime;
use r6::compiler::Compiler;
use r6::base::libbase;
use r6::parser::Parser;

static START: Once = ONCE_INIT;

macro_rules! assert_evaluates_to {
    ($src:expr, $expected:expr) => (
        {
            START.call_once(|| {
                env_logger::init().unwrap();
            });
            let mut src_reader = BufReader::new($src.as_bytes());
            let mut src_parser = Parser::new(&mut src_reader);
            let sourcecode = match src_parser.parse_datum() {
                Ok(code) => code,
                Err(e) => panic!("failed to parse source: {:?}", e)
            };

            let mut res_reader = BufReader::new($expected.as_bytes());
            let mut res_parser = Parser::new(&mut res_reader);
            let expected = match res_parser.parse_datum() {
                Ok(val) => val,
                Err(e) => panic!("failed to parse result: {:?}", e)
            };

            let base = libbase();
            let compiler = Compiler::new(&base);
            let bytecode = match compiler.compile(&sourcecode) {
                Ok(code) => code,
                Err(e) => panic!("compile failure: {:?}", e)
            };
            let mut runtime = Runtime::new(bytecode);
            let result = runtime.run();
            if !((result == expected) && (expected == result)) {
                panic!("test failed: expected `{:?}` but got `{:?}`", expected, result);
            }
        }
    )
}

macro_rules! assert_evaluates_datum {
    ($src:expr, $expected:expr) => (
        {
            let mut src_reader = BufReader::new($src.as_bytes());
            let mut src_parser = Parser::new(&mut src_reader);
            let sourcecode = match src_parser.parse_datum() {
                Ok(code) => code,
                Err(e) => panic!("failed to parse source: {:?}", e)
            };

            let base = libbase();
            let compiler = Compiler::new(&base);
            let bytecode = match compiler.compile(&sourcecode) {
                Ok(code) => code,
                Err(e) => panic!("compile failure: {:?}", e)
            };
            let mut runtime = Runtime::new(bytecode);
            let result = runtime.run();
            if !((result == $expected) && ($expected == result)) {
                panic!("test failed: expected `{:?}` but got `{:?}`", $expected, result);
            }
        }
    )
}

#[test]
fn lexical_scoping() {
    // (\y f -> f 2) #f ((\y -> (\x -> y)) #t)
    // If it's dynamic scope, it should return 0
    // If it's static scope, it should return 1
    assert_evaluates_to!("((lambda (y f) (f 2)) #f ((lambda (y) (lambda (x) y)) #t))", "#t")
}

#[test]
fn lambda_test() {
    assert_evaluates_to!("((lambda (x) (+ x x)) 4)", "8");
}

#[test]
fn var_arg_test() {
    assert_evaluates_to!("((lambda (x y . z) z) 3 4 5 6)", "(5 6)");
}

#[test]
fn local_define_test() {
    assert_evaluates_to!("(let ((x 5)) (define (foo y) (bar x y)) (define (bar a b) (+ (* a b) a)) (foo (+ x 3)))", "45");
}

#[test]
fn if_expression_test() {
    assert_evaluates_to!("(if #t 1 0)", "1");
    assert_evaluates_to!("(if #f 1 0)", "0");
}

#[test]
fn eval_to_self_test() {
    assert_evaluates_to!("#t", "#t");
    assert_evaluates_to!("23", "23");
}

#[test]
fn numeric_expressions_test() {
    assert_evaluates_to!("(+ 23 42)", "65");
    assert_evaluates_to!("(+ 14 (* 23 42))", "980");
    assert_evaluates_to!("(- 3 1)", "2");
    assert_evaluates_to!("(- 3)", "-3");
    assert_evaluates_to!("(/ 3 2)", "3/2");
    assert_evaluates_to!("(/ 3.0 2)", "1.5");
}

#[test]
fn let_test() {
    assert_evaluates_to!("(let ((x 23) (y 42)) (+ x y))", "65");
}

#[test]
fn override_syntax_test() {
    assert_evaluates_to!("(let ((if (lambda (x) x))) (if 3))", "3");
}

#[test]
fn let_star_test() {
    assert_evaluates_to!("(let ((x 2) (y 3)) (let* ((x 7) (z (+ x y))) (* z x)))", "70");
}

#[test]
fn letrec_test() {
    assert_evaluates_to!("(letrec ((even? (lambda (n) (if (zero? n) #t (odd? (- n 1))))) (odd? (lambda (n) (if (zero? n) #f (even? (- n 1)))))) (even? 8))", "#t");
}

#[test]
fn letrec_undefined_test() {
    use r6::datum::Datum;
    use r6::runtime::RuntimeData;

    assert_evaluates_datum!(
        "(letrec ((quicksand quicksand)) quicksand)",
        Datum::Ext(RuntimeData::Undefined)
    );
}

#[test]
fn set_test() {
    assert_evaluates_to!("(let ((x 23)) (set! x 24) x)", "24");
}

#[test]
fn list_test() {
    assert_evaluates_to!("(list 1 2 3)", "(1 2 3)");
    assert_evaluates_to!("(list)", "()");
}

#[test]
fn quote_test() {
    assert_evaluates_to!(r#"(quote a)"#, "a");
    assert_evaluates_to!(r#"(quote (1 2 3))"#, "(1 2 3)");
    assert_evaluates_to!(r#"(quote #\a)"#, r#"#\a"#);
}

#[test]
fn quote_abbrev_test() {
    assert_evaluates_to!(r#"'a"#, "a");
    assert_evaluates_to!(r#"'(1 2 3)"#, "(1 2 3)");
    assert_evaluates_to!(r#"'#\a"#, r#"#\a"#);
}

#[test]
fn typecheck_test() {
    assert_evaluates_to!("(boolean? #t)", "#t");
    assert_evaluates_to!("(boolean? #f)", "#t");
    assert_evaluates_to!("(boolean? 1)", "#f");

    assert_evaluates_to!("(pair? (list 1 2))", "#t");
    assert_evaluates_to!("(pair? (list))", "#f");
    assert_evaluates_to!("(pair? 1)", "#f");

    assert_evaluates_to!(r#"(symbol? #\a)"#, "#f");
    assert_evaluates_to!(r#"(symbol? 'a)"#, "#t");

    assert_evaluates_to!(r#"(char? #\a)"#, "#t");
    assert_evaluates_to!(r#"(char? 'a)"#, "#f");

    assert_evaluates_to!(r#"(string? "a")"#, "#t");
    assert_evaluates_to!(r#"(string? 'a)"#, "#f");

    assert_evaluates_to!(r#"(procedure? +)"#, "#t");
    assert_evaluates_to!(r#"(procedure? '+)"#, "#f");

    assert_evaluates_to!(r#"(null? (list))"#, "#t");
    assert_evaluates_to!(r#"(null? (list 1 2))"#, "#f");

    assert_evaluates_to!(r#"(vector? #(a b c))"#, "#t");
    assert_evaluates_to!(r#"(vector? (list 1 2))"#, "#f");
}

#[test]
fn car_test() {
    assert_evaluates_to!("(car '(a b))", "a");
}

#[test]
fn cdr_test() {
    assert_evaluates_to!("(cdr '(a b))", "(b)");
}

#[test]
fn number_predicates_test() {
    assert_evaluates_to!("(zero? 0)", "#t");
    assert_evaluates_to!("(zero? +0.0)", "#t");
    assert_evaluates_to!("(zero? -0.0)", "#t");
    assert_evaluates_to!("(zero? +nan.0)", "#f");
}

#[test]
fn number_type_test() {
    assert_evaluates_to!("(complex? 3+4i)", "#t");
    assert_evaluates_to!("(complex? 3)", "#t");
    assert_evaluates_to!("(real? 3)", "#t");
    assert_evaluates_to!("(real? -2.5+0.0i)", "#f");
    assert_evaluates_to!("(real? -2.5+0i)", "#t");
    assert_evaluates_to!("(real? -2.5)", "#t");
    assert_evaluates_to!("(real? #e1e10)", "#t");
    assert_evaluates_to!("(rational? 6/10)", "#t");
    assert_evaluates_to!("(rational? 6/3)", "#t");
    assert_evaluates_to!("(rational? 2)", "#t");
    assert_evaluates_to!("(integer? 3+0i)", "#t");
    assert_evaluates_to!("(integer? 3.0)", "#t");
    assert_evaluates_to!("(integer? 8/4)", "#t");
    assert_evaluates_to!("(number? +nan.0)", "#t");
    assert_evaluates_to!("(complex? +nan.0)", "#t");
    assert_evaluates_to!("(real? +nan.0)", "#t");
    assert_evaluates_to!("(rational? +nan.0)", "#f");
    assert_evaluates_to!("(complex? +inf.0)", "#t");
    assert_evaluates_to!("(real? -inf.0)", "#t");
    assert_evaluates_to!("(rational? -inf.0)", "#f");
    assert_evaluates_to!("(integer? -inf.0)", "#f");
}

#[test]
fn number_eq_test() {
    assert_evaluates_to!("(= 2 2)", "#t");
    assert_evaluates_to!("(= +inf.0 +inf.0)", "#t");
    assert_evaluates_to!("(= -inf.0 +inf.0)", "#f");
    assert_evaluates_to!("(= -inf.0 -inf.0)", "#t");

    assert_evaluates_to!("(< -inf.0 2 +inf.0)", "#t");
    assert_evaluates_to!("(> +inf.0 2 -inf.0)", "#t");

    assert_evaluates_to!("(= +nan.0 2)", "#f");
    assert_evaluates_to!("(= +nan.0 +nan.0)", "#f");

    assert_evaluates_to!("(< +nan.0 2)", "#f");
    assert_evaluates_to!("(< +nan.0 +nan.0)", "#f");

    assert_evaluates_to!("(> +nan.0 2)", "#f");
    assert_evaluates_to!("(> +nan.0 +nan.0)", "#f");
}

#[test]
fn and_or_test() {
    assert_evaluates_to!("(and (= 2 2) (> 2 1))", "#t");
    assert_evaluates_to!("(and (= 2 2) (< 2 1))", "#f");
    assert_evaluates_to!("(and 1 2 'c '(f g))", "(f g)");
    assert_evaluates_to!("(and)", "#t");
}
<|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/. */

use cssparser::{Parser, SourcePosition};
use parking_lot::RwLock;
use rayon;
use servo_url::ServoUrl;
use std::sync::Arc;
use style::error_reporting::ParseErrorReporter;
use style::media_queries::MediaList;
use style::parser::ParserContextExtraData;
use style::properties::{longhands, DeclaredValue, Importance, PropertyDeclaration, PropertyDeclarationBlock};
use style::rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
use style::stylesheets::{Origin, Stylesheet, CssRule};
use test::{self, Bencher};

struct ErrorringErrorReporter;
impl ParseErrorReporter for ErrorringErrorReporter {
    fn report_error(&self, input: &mut Parser, position: SourcePosition, message: &str,
        url: &ServoUrl) {
        panic!("CSS error: {}\t\n{:?} {}", url.as_str(), position, message);
    }

    fn clone(&self) -> Box<ParseErrorReporter + Send + Sync> {
        Box::new(ErrorringErrorReporter)
    }
}

struct AutoGCRuleTree<'a>(&'a RuleTree);

impl<'a> AutoGCRuleTree<'a> {
    fn new(r: &'a RuleTree) -> Self {
        AutoGCRuleTree(r)
    }
}

impl<'a> Drop for AutoGCRuleTree<'a> {
    fn drop(&mut self) {
        unsafe { self.0.gc() }
    }
}

fn parse_rules(css: &str) -> Vec<(StyleSource, CascadeLevel)> {
    let s = Stylesheet::from_str(css,
                                 ServoUrl::parse("http://localhost").unwrap(),
                                 Origin::Author,
                                 MediaList {
                                     media_queries: vec![],
                                 },
                                 None,
                                 Box::new(ErrorringErrorReporter),
                                 ParserContextExtraData {});
    let rules = s.rules.read();
    rules.0.iter().filter_map(|rule| {
        match *rule {
            CssRule::Style(ref style_rule) => Some(style_rule),
            _ => None,
        }
    }).cloned().map(StyleSource::Style).map(|s| {
        (s, CascadeLevel::UserNormal)
    }).collect()
}

fn test_insertion(rule_tree: &RuleTree, rules: Vec<(StyleSource, CascadeLevel)>) -> StrongRuleNode {
    rule_tree.insert_ordered_rules(rules.into_iter())
}

fn test_insertion_style_attribute(rule_tree: &RuleTree, rules: &[(StyleSource, CascadeLevel)]) -> StrongRuleNode {
    let mut rules = rules.to_vec();
    rules.push((StyleSource::Declarations(Arc::new(RwLock::new(PropertyDeclarationBlock {
        declarations: vec![
            (PropertyDeclaration::Display(DeclaredValue::Value(
                longhands::display::SpecifiedValue::block)),
            Importance::Normal),
        ],
        important_count: 0,
    }))), CascadeLevel::UserNormal));
    test_insertion(rule_tree, rules)
}

#[bench]
fn bench_insertion_basic(b: &mut Bencher) {
    let r = RuleTree::new();

    let rules_matched = parse_rules(
        ".foo { width: 200px; } \
         .bar { height: 500px; } \
         .baz { display: block; }");

    b.iter(|| {
        let _gc = AutoGCRuleTree::new(&r);

        for _ in 0..(4000 + 400) {
            test::black_box(test_insertion(&r, rules_matched.clone()));
        }
    })
}

#[bench]
fn bench_insertion_basic_per_element(b: &mut Bencher) {
    let r = RuleTree::new();

    let rules_matched = parse_rules(
        ".foo { width: 200px; } \
         .bar { height: 500px; } \
         .baz { display: block; }");

    b.iter(|| {
        let _gc = AutoGCRuleTree::new(&r);

        test::black_box(test_insertion(&r, rules_matched.clone()));
    });
}

#[bench]
fn bench_expensive_insertion(b: &mut Bencher) {
    let r = RuleTree::new();

    // This test case tests a case where you style a bunch of siblings
    // matching the same rules, with a different style attribute each
    // one.
    let rules_matched = parse_rules(
        ".foo { width: 200px; } \
         .bar { height: 500px; } \
         .baz { display: block; }");

    b.iter(|| {
        let _gc = AutoGCRuleTree::new(&r);

        for _ in 0..(4000 + 400) {
            test::black_box(test_insertion_style_attribute(&r, &rules_matched));
        }
    });
}

#[bench]
fn bench_insertion_basic_parallel(b: &mut Bencher) {
    let r = RuleTree::new();

    let rules_matched = parse_rules(
        ".foo { width: 200px; } \
         .bar { height: 500px; } \
         .baz { display: block; }");

    b.iter(|| {
        let _gc = AutoGCRuleTree::new(&r);

        rayon::scope(|s| {
            for _ in 0..4 {
                s.spawn(|s| {
                    for _ in 0..1000 {
                        test::black_box(test_insertion(&r,
                                                       rules_matched.clone()));
                    }
                    s.spawn(|_| {
                        for _ in 0..100 {
                            test::black_box(test_insertion(&r,
                                                           rules_matched.clone()));
                        }
                    })
                })
            }
        });
    });
}

#[bench]
fn bench_expensive_insersion_parallel(b: &mut Bencher) {
    let r = RuleTree::new();

    let rules_matched = parse_rules(
        ".foo { width: 200px; } \
         .bar { height: 500px; } \
         .baz { display: block; }");

    b.iter(|| {
        let _gc = AutoGCRuleTree::new(&r);

        rayon::scope(|s| {
            for _ in 0..4 {
                s.spawn(|s| {
                    for _ in 0..1000 {
                        test::black_box(test_insertion_style_attribute(&r,
                                                                       &rules_matched));
                    }
                    s.spawn(|_| {
                        for _ in 0..100 {
                            test::black_box(test_insertion_style_attribute(&r,
                                                                           &rules_matched));
                        }
                    })
                })
            }
        });
    });
}
<commit_msg>Fix a warning<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/. */

use cssparser::{Parser, SourcePosition};
use parking_lot::RwLock;
use rayon;
use servo_url::ServoUrl;
use std::sync::Arc;
use style::error_reporting::ParseErrorReporter;
use style::media_queries::MediaList;
use style::parser::ParserContextExtraData;
use style::properties::{longhands, DeclaredValue, Importance, PropertyDeclaration, PropertyDeclarationBlock};
use style::rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
use style::stylesheets::{Origin, Stylesheet, CssRule};
use test::{self, Bencher};

struct ErrorringErrorReporter;
impl ParseErrorReporter for ErrorringErrorReporter {
    fn report_error(&self, _input: &mut Parser, position: SourcePosition, message: &str,
        url: &ServoUrl) {
        panic!("CSS error: {}\t\n{:?} {}", url.as_str(), position, message);
    }

    fn clone(&self) -> Box<ParseErrorReporter + Send + Sync> {
        Box::new(ErrorringErrorReporter)
    }
}

struct AutoGCRuleTree<'a>(&'a RuleTree);

impl<'a> AutoGCRuleTree<'a> {
    fn new(r: &'a RuleTree) -> Self {
        AutoGCRuleTree(r)
    }
}

impl<'a> Drop for AutoGCRuleTree<'a> {
    fn drop(&mut self) {
        unsafe { self.0.gc() }
    }
}

fn parse_rules(css: &str) -> Vec<(StyleSource, CascadeLevel)> {
    let s = Stylesheet::from_str(css,
                                 ServoUrl::parse("http://localhost").unwrap(),
                                 Origin::Author,
                                 MediaList {
                                     media_queries: vec![],
                                 },
                                 None,
                                 Box::new(ErrorringErrorReporter),
                                 ParserContextExtraData {});
    let rules = s.rules.read();
    rules.0.iter().filter_map(|rule| {
        match *rule {
            CssRule::Style(ref style_rule) => Some(style_rule),
            _ => None,
        }
    }).cloned().map(StyleSource::Style).map(|s| {
        (s, CascadeLevel::UserNormal)
    }).collect()
}

fn test_insertion(rule_tree: &RuleTree, rules: Vec<(StyleSource, CascadeLevel)>) -> StrongRuleNode {
    rule_tree.insert_ordered_rules(rules.into_iter())
}

fn test_insertion_style_attribute(rule_tree: &RuleTree, rules: &[(StyleSource, CascadeLevel)]) -> StrongRuleNode {
    let mut rules = rules.to_vec();
    rules.push((StyleSource::Declarations(Arc::new(RwLock::new(PropertyDeclarationBlock {
        declarations: vec![
            (PropertyDeclaration::Display(DeclaredValue::Value(
                longhands::display::SpecifiedValue::block)),
            Importance::Normal),
        ],
        important_count: 0,
    }))), CascadeLevel::UserNormal));
    test_insertion(rule_tree, rules)
}

#[bench]
fn bench_insertion_basic(b: &mut Bencher) {
    let r = RuleTree::new();

    let rules_matched = parse_rules(
        ".foo { width: 200px; } \
         .bar { height: 500px; } \
         .baz { display: block; }");

    b.iter(|| {
        let _gc = AutoGCRuleTree::new(&r);

        for _ in 0..(4000 + 400) {
            test::black_box(test_insertion(&r, rules_matched.clone()));
        }
    })
}

#[bench]
fn bench_insertion_basic_per_element(b: &mut Bencher) {
    let r = RuleTree::new();

    let rules_matched = parse_rules(
        ".foo { width: 200px; } \
         .bar { height: 500px; } \
         .baz { display: block; }");

    b.iter(|| {
        let _gc = AutoGCRuleTree::new(&r);

        test::black_box(test_insertion(&r, rules_matched.clone()));
    });
}

#[bench]
fn bench_expensive_insertion(b: &mut Bencher) {
    let r = RuleTree::new();

    // This test case tests a case where you style a bunch of siblings
    // matching the same rules, with a different style attribute each
    // one.
    let rules_matched = parse_rules(
        ".foo { width: 200px; } \
         .bar { height: 500px; } \
         .baz { display: block; }");

    b.iter(|| {
        let _gc = AutoGCRuleTree::new(&r);

        for _ in 0..(4000 + 400) {
            test::black_box(test_insertion_style_attribute(&r, &rules_matched));
        }
    });
}

#[bench]
fn bench_insertion_basic_parallel(b: &mut Bencher) {
    let r = RuleTree::new();

    let rules_matched = parse_rules(
        ".foo { width: 200px; } \
         .bar { height: 500px; } \
         .baz { display: block; }");

    b.iter(|| {
        let _gc = AutoGCRuleTree::new(&r);

        rayon::scope(|s| {
            for _ in 0..4 {
                s.spawn(|s| {
                    for _ in 0..1000 {
                        test::black_box(test_insertion(&r,
                                                       rules_matched.clone()));
                    }
                    s.spawn(|_| {
                        for _ in 0..100 {
                            test::black_box(test_insertion(&r,
                                                           rules_matched.clone()));
                        }
                    })
                })
            }
        });
    });
}

#[bench]
fn bench_expensive_insersion_parallel(b: &mut Bencher) {
    let r = RuleTree::new();

    let rules_matched = parse_rules(
        ".foo { width: 200px; } \
         .bar { height: 500px; } \
         .baz { display: block; }");

    b.iter(|| {
        let _gc = AutoGCRuleTree::new(&r);

        rayon::scope(|s| {
            for _ in 0..4 {
                s.spawn(|s| {
                    for _ in 0..1000 {
                        test::black_box(test_insertion_style_attribute(&r,
                                                                       &rules_matched));
                    }
                    s.spawn(|_| {
                        for _ in 0..100 {
                            test::black_box(test_insertion_style_attribute(&r,
                                                                           &rules_matched));
                        }
                    })
                })
            }
        });
    });
}
<|endoftext|>


<commit_before>use lfsr::fibonacci::FibonacciLFSR;
use lfsr::galois::GaloisLFSR;

use support::eq_mod_rotation;

#[test]
fn iter_works_for_fibonacci() {
    iter_works_for!(FibonacciLFSR);
}

#[test]
fn iter_works_for_galois() {
    iter_works_for!(GaloisLFSR);
}

#[test]
fn same_connection_polynomial_produce_output_equal_mod_rotation() {
    let taps = vec![2, 3];

    let mut galois = GaloisLFSR::from_iter(taps.iter());
    let galois_output: Vec<bool> = galois.iter().take(7).collect();

    let mut fibonacci = FibonacciLFSR::from_iter(taps.iter());
    let fibonacci_output: Vec<bool> = fibonacci.iter().take(7).collect();

    assert!(eq_mod_rotation(&fibonacci_output, &galois_output));
}

#[test]
fn primitive_connection_polynomial_yields_a_maximum_sequence_for_fibonacci() {
    primitive_connection_polynomial_yields_a_maximum_sequence!(FibonacciLFSR);
}

#[test]
fn primitive_connection_polynomial_yields_a_maximum_sequence_for_galois() {
    primitive_connection_polynomial_yields_a_maximum_sequence!(GaloisLFSR);
}
<commit_msg>Add specialized tests for LFSR IntoIterator impls<commit_after>use lfsr::fibonacci::FibonacciLFSR;
use lfsr::galois::GaloisLFSR;

use support::eq_mod_rotation;

#[test]
fn iter_works_for_fibonacci() {
    iter_works_for!(FibonacciLFSR);
}

#[test]
fn iter_works_for_galois() {
    iter_works_for!(GaloisLFSR);
}

#[test]
fn same_connection_polynomial_produce_output_equal_mod_rotation() {
    let taps = vec![2, 3];

    let mut galois = GaloisLFSR::from_iter(taps.iter());
    let galois_output: Vec<bool> = galois.iter().take(7).collect();

    let mut fibonacci = FibonacciLFSR::from_iter(taps.iter());
    let fibonacci_output: Vec<bool> = fibonacci.iter().take(7).collect();

    assert!(eq_mod_rotation(&fibonacci_output, &galois_output));
}

#[test]
fn primitive_connection_polynomial_yields_a_maximum_sequence_for_fibonacci() {
    primitive_connection_polynomial_yields_a_maximum_sequence!(FibonacciLFSR);
}

#[test]
fn primitive_connection_polynomial_yields_a_maximum_sequence_for_galois() {
    primitive_connection_polynomial_yields_a_maximum_sequence!(GaloisLFSR);
}

#[test]
fn implements_iter() {
    let taps = vec![2, 3];
    let mut lfsr = GaloisLFSR::from_iter(taps.iter());

    let output: Vec<bool> = lfsr.iter().take(8).collect();

    let expected = vec![true, false, false, true, false, true, true, true];

    assert!(eq_mod_rotation(&output, &expected))
}

#[test]
fn implements_into_iterator() {
    let taps = vec![2, 3];
    let lfsr = GaloisLFSR::from_iter(taps.iter());

    let mut counter = 0;
    for _b in lfsr {
        if counter == 3 {
            break;
        }
        counter += 1;
    }
}

#[test]
fn implements_into_iterator_for_mut_refs() {
    use lfsr::LFSR;

    let taps = vec![2, 3];
    let mut lfsr = GaloisLFSR::from_iter(taps.iter());

    let mut counter = 0;
    for _b in &mut lfsr {
        if counter == 3 {
            break;
        }
        counter += 1;
    }

    lfsr.step();
}
<|endoftext|>


<commit_before>extern crate rfc6238;

fn format_hex(s: &[u8]) -> String {
    let mut human_representation: Vec<String> = Vec::new();

    for c in s.iter() {
        human_representation.push(format!("{:02x}", c))
    }
    format!("0x{}", human_representation.join(""))
}

#[test]
fn it_works() {
    let counter : &[u8] = &[ 0x00; 8 ];
    println!("HMAC-SHA-1:");
    println!("================================================================================");
    let example : &[u8] = &[
        0x1f,
        0x86,
        0x98,
        0x69,
        0x0e,
        0x02,
        0xca,
        0x16,
        0x61,
        0x85,
        0x50,
        0xef,
        0x7f,
        0x19,
        0xda,
        0x8e,
        0x94,
        0x5b,
        0x55,
        0x5a
    ];

    println!("HMAC SHA-1: {}", format_hex(example));
    println!("================================================================================");

    println!("Offset index: {}", rfc6238::offset(example));
    println!("================================================================================");

    println!("P: {:x}", rfc6238::sbits(example));
    println!("================================================================================");

    println!("HOTP Value: {}", rfc6238::hotp(rfc6238::sbits(example)));
    println!("================================================================================");
    assert!(false);
}
<commit_msg>Write an actual test.<commit_after>extern crate rfc6238;

fn format_hex(s: &[u8]) -> String {
    let mut human_representation: Vec<String> = Vec::new();

    for c in s.iter() {
        human_representation.push(format!("{:02x}", c))
    }
    format!("0x{}", human_representation.join(""))
}

#[test]
fn it_conforms_to_example_given_in_rfc6238() {
    let counter : &[u8] = &[ 0x00; 8 ];
    println!("HMAC-SHA-1:");
    println!("================================================================================");
    let example : &[u8] = &[
        0x1f,
        0x86,
        0x98,
        0x69,
        0x0e,
        0x02,
        0xca,
        0x16,
        0x61,
        0x85,
        0x50,
        0xef,
        0x7f,
        0x19,
        0xda,
        0x8e,
        0x94,
        0x5b,
        0x55,
        0x5a
    ];

    println!("HMAC SHA-1: {}", format_hex(example));
    println!("================================================================================");

    println!("Offset index: {}", rfc6238::offset(example));
    println!("================================================================================");

    println!("P: {:x}", rfc6238::sbits(example));
    println!("================================================================================");

    let hotp_value = rfc6238::hotp(rfc6238::sbits(example));
    println!("HOTP Value: {}", hotp_value);
    println!("================================================================================");
    assert!(hotp_value == 872921);
}
<|endoftext|>


<commit_before>// run-pass
// ignore-cross-compile

// The general idea of this test is to enumerate all "interesting" expressions and check that
// `parse(print(e)) == e` for all `e`. Here's what's interesting, for the purposes of this test:
//
// 1. The test focuses on expression nesting, because interactions between different expression
//    types are harder to test manually than single expression types in isolation.
//
// 2. The test only considers expressions of at most two nontrivial nodes. So it will check `x +
//    x` and `x + (x - x)` but not `(x * x) + (x - x)`. The assumption here is that the correct
//    handling of an expression might depend on the expression's parent, but doesn't depend on its
//    siblings or any more distant ancestors.
//
// 3. The test only checks certain expression kinds. The assumption is that similar expression
//    types, such as `if` and `while` or `+` and `-`, will be handled identically in the printer
//    and parser. So if all combinations of exprs involving `if` work correctly, then combinations
//    using `while`, `if let`, and so on will likely work as well.

#![feature(rustc_private)]

extern crate rustc_data_structures;
extern crate syntax;

use rustc_data_structures::thin_vec::ThinVec;
use syntax::ast::*;
use syntax::source_map::{Spanned, DUMMY_SP, FileName};
use syntax::source_map::FilePathMapping;
use syntax::mut_visit::{self, MutVisitor, visit_clobber};
use syntax::parse::{self, ParseSess};
use syntax::print::pprust;
use syntax::ptr::P;

fn parse_expr(ps: &ParseSess, src: &str) -> P<Expr> {
    let src_as_string = src.to_string();

    let mut p = parse::new_parser_from_source_str(ps,
                                                  FileName::Custom(src_as_string.clone()),
                                                  src_as_string);
    p.parse_expr().unwrap()
}

// Helper functions for building exprs
fn expr(kind: ExprKind) -> P<Expr> {
    P(Expr {
        id: DUMMY_NODE_ID,
        node: kind,
        span: DUMMY_SP,
        attrs: ThinVec::new(),
    })
}

fn make_x() -> P<Expr> {
    let seg = PathSegment::from_ident(Ident::from_str("x"));
    let path = Path { segments: vec![seg], span: DUMMY_SP };
    expr(ExprKind::Path(None, path))
}

/// Iterate over exprs of depth up to `depth`. The goal is to explore all "interesting"
/// combinations of expression nesting. For example, we explore combinations using `if`, but not
/// `while` or `match`, since those should print and parse in much the same way as `if`.
fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
    if depth == 0 {
        f(make_x());
        return;
    }

    let mut g = |e| f(expr(e));

    for kind in 0..=19 {
        match kind {
            0 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Box(e))),
            1 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))),
            2 => {
                let seg = PathSegment::from_ident(Ident::from_str("x"));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
                            seg.clone(), vec![e, make_x()])));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
                            seg.clone(), vec![make_x(), e])));
            },
            3..=8 => {
                let op = Spanned {
                    span: DUMMY_SP,
                    node: match kind {
                        3 => BinOpKind::Add,
                        4 => BinOpKind::Mul,
                        5 => BinOpKind::Shl,
                        6 => BinOpKind::And,
                        7 => BinOpKind::Or,
                        8 => BinOpKind::Lt,
                        _ => unreachable!(),
                    }
                };
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
            },
            9 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Unary(UnOp::Deref, e)));
            },
            10 => {
                let block = P(Block {
                    stmts: Vec::new(),
                    id: DUMMY_NODE_ID,
                    rules: BlockCheckMode::Default,
                    span: DUMMY_SP,
                });
                iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
            },
            11 => {
                let decl = P(FnDecl {
                    inputs: vec![],
                    output: FunctionRetTy::Default(DUMMY_SP),
                    c_variadic: false,
                });
                iter_exprs(depth - 1, &mut |e| g(
                        ExprKind::Closure(CaptureBy::Value,
                                          IsAsync::NotAsync,
                                          Movability::Movable,
                                          decl.clone(),
                                          e,
                                          DUMMY_SP)));
            },
            12 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(make_x(), e)));
            },
            13 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Field(e, Ident::from_str("f"))));
            },
            14 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
                            Some(e), Some(make_x()), RangeLimits::HalfOpen)));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
                            Some(make_x()), Some(e), RangeLimits::HalfOpen)));
            },
            15 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::AddrOf(Mutability::Immutable, e)));
            },
            16 => {
                g(ExprKind::Ret(None));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Ret(Some(e))));
            },
            17 => {
                let path = Path::from_ident(Ident::from_str("S"));
                g(ExprKind::Struct(path, vec![], Some(make_x())));
            },
            18 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e)));
            },
            19 => {
                let ps = vec![P(Pat {
                    id: DUMMY_NODE_ID,
                    node: PatKind::Wild,
                    span: DUMMY_SP,
                })];
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(ps.clone(), e)))
            },
            _ => panic!("bad counter value in iter_exprs"),
        }
    }
}

// Folders for manipulating the placement of `Paren` nodes. See below for why this is needed.

/// `MutVisitor` that removes all `ExprKind::Paren` nodes.
struct RemoveParens;

impl MutVisitor for RemoveParens {
    fn visit_expr(&mut self, e: &mut P<Expr>) {
        match e.node.clone() {
            ExprKind::Paren(inner) => *e = inner,
            _ => {}
        };
        mut_visit::noop_visit_expr(e, self);
    }
}

/// `MutVisitor` that inserts `ExprKind::Paren` nodes around every `Expr`.
struct AddParens;

impl MutVisitor for AddParens {
    fn visit_expr(&mut self, e: &mut P<Expr>) {
        mut_visit::noop_visit_expr(e, self);
        visit_clobber(e, |e| {
            P(Expr {
                id: DUMMY_NODE_ID,
                node: ExprKind::Paren(e),
                span: DUMMY_SP,
                attrs: ThinVec::new(),
            })
        });
    }
}

fn main() {
    syntax::with_default_globals(|| run());
}

fn run() {
    let ps = ParseSess::new(FilePathMapping::empty());

    iter_exprs(2, &mut |mut e| {
        // If the pretty printer is correct, then `parse(print(e))` should be identical to `e`,
        // modulo placement of `Paren` nodes.
        let printed = pprust::expr_to_string(&e);
        println!("printed: {}", printed);

        let mut parsed = parse_expr(&ps, &printed);

        // We want to know if `parsed` is structurally identical to `e`, ignoring trivial
        // differences like placement of `Paren`s or the exact ranges of node spans.
        // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s
        // everywhere we can, then pretty-print. This should give an unambiguous representation of
        // each `Expr`, and it bypasses nearly all of the parenthesization logic, so we aren't
        // relying on the correctness of the very thing we're testing.
        RemoveParens.visit_expr(&mut e);
        AddParens.visit_expr(&mut e);
        let text1 = pprust::expr_to_string(&e);
        RemoveParens.visit_expr(&mut parsed);
        AddParens.visit_expr(&mut parsed);
        let text2 = pprust::expr_to_string(&parsed);
        assert!(text1 == text2,
                "exprs are not equal:\n  e =      {:?}\n  parsed = {:?}",
                text1, text2);
    });
}
<commit_msg>or-patterns: fix pprust-expr-roundtrip due to AST change.<commit_after>// run-pass
// ignore-cross-compile

// The general idea of this test is to enumerate all "interesting" expressions and check that
// `parse(print(e)) == e` for all `e`. Here's what's interesting, for the purposes of this test:
//
// 1. The test focuses on expression nesting, because interactions between different expression
//    types are harder to test manually than single expression types in isolation.
//
// 2. The test only considers expressions of at most two nontrivial nodes. So it will check `x +
//    x` and `x + (x - x)` but not `(x * x) + (x - x)`. The assumption here is that the correct
//    handling of an expression might depend on the expression's parent, but doesn't depend on its
//    siblings or any more distant ancestors.
//
// 3. The test only checks certain expression kinds. The assumption is that similar expression
//    types, such as `if` and `while` or `+` and `-`, will be handled identically in the printer
//    and parser. So if all combinations of exprs involving `if` work correctly, then combinations
//    using `while`, `if let`, and so on will likely work as well.

#![feature(rustc_private)]

extern crate rustc_data_structures;
extern crate syntax;

use rustc_data_structures::thin_vec::ThinVec;
use syntax::ast::*;
use syntax::source_map::{Spanned, DUMMY_SP, FileName};
use syntax::source_map::FilePathMapping;
use syntax::mut_visit::{self, MutVisitor, visit_clobber};
use syntax::parse::{self, ParseSess};
use syntax::print::pprust;
use syntax::ptr::P;

fn parse_expr(ps: &ParseSess, src: &str) -> P<Expr> {
    let src_as_string = src.to_string();

    let mut p = parse::new_parser_from_source_str(ps,
                                                  FileName::Custom(src_as_string.clone()),
                                                  src_as_string);
    p.parse_expr().unwrap()
}

// Helper functions for building exprs
fn expr(kind: ExprKind) -> P<Expr> {
    P(Expr {
        id: DUMMY_NODE_ID,
        node: kind,
        span: DUMMY_SP,
        attrs: ThinVec::new(),
    })
}

fn make_x() -> P<Expr> {
    let seg = PathSegment::from_ident(Ident::from_str("x"));
    let path = Path { segments: vec![seg], span: DUMMY_SP };
    expr(ExprKind::Path(None, path))
}

/// Iterate over exprs of depth up to `depth`. The goal is to explore all "interesting"
/// combinations of expression nesting. For example, we explore combinations using `if`, but not
/// `while` or `match`, since those should print and parse in much the same way as `if`.
fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
    if depth == 0 {
        f(make_x());
        return;
    }

    let mut g = |e| f(expr(e));

    for kind in 0..=19 {
        match kind {
            0 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Box(e))),
            1 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))),
            2 => {
                let seg = PathSegment::from_ident(Ident::from_str("x"));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
                            seg.clone(), vec![e, make_x()])));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
                            seg.clone(), vec![make_x(), e])));
            },
            3..=8 => {
                let op = Spanned {
                    span: DUMMY_SP,
                    node: match kind {
                        3 => BinOpKind::Add,
                        4 => BinOpKind::Mul,
                        5 => BinOpKind::Shl,
                        6 => BinOpKind::And,
                        7 => BinOpKind::Or,
                        8 => BinOpKind::Lt,
                        _ => unreachable!(),
                    }
                };
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
            },
            9 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Unary(UnOp::Deref, e)));
            },
            10 => {
                let block = P(Block {
                    stmts: Vec::new(),
                    id: DUMMY_NODE_ID,
                    rules: BlockCheckMode::Default,
                    span: DUMMY_SP,
                });
                iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
            },
            11 => {
                let decl = P(FnDecl {
                    inputs: vec![],
                    output: FunctionRetTy::Default(DUMMY_SP),
                    c_variadic: false,
                });
                iter_exprs(depth - 1, &mut |e| g(
                        ExprKind::Closure(CaptureBy::Value,
                                          IsAsync::NotAsync,
                                          Movability::Movable,
                                          decl.clone(),
                                          e,
                                          DUMMY_SP)));
            },
            12 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(e, make_x())));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(make_x(), e)));
            },
            13 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Field(e, Ident::from_str("f"))));
            },
            14 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
                            Some(e), Some(make_x()), RangeLimits::HalfOpen)));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
                            Some(make_x()), Some(e), RangeLimits::HalfOpen)));
            },
            15 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::AddrOf(Mutability::Immutable, e)));
            },
            16 => {
                g(ExprKind::Ret(None));
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Ret(Some(e))));
            },
            17 => {
                let path = Path::from_ident(Ident::from_str("S"));
                g(ExprKind::Struct(path, vec![], Some(make_x())));
            },
            18 => {
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e)));
            },
            19 => {
                let pat = P(Pat {
                    id: DUMMY_NODE_ID,
                    node: PatKind::Wild,
                    span: DUMMY_SP,
                });
                iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(pat.clone(), e)))
            },
            _ => panic!("bad counter value in iter_exprs"),
        }
    }
}

// Folders for manipulating the placement of `Paren` nodes. See below for why this is needed.

/// `MutVisitor` that removes all `ExprKind::Paren` nodes.
struct RemoveParens;

impl MutVisitor for RemoveParens {
    fn visit_expr(&mut self, e: &mut P<Expr>) {
        match e.node.clone() {
            ExprKind::Paren(inner) => *e = inner,
            _ => {}
        };
        mut_visit::noop_visit_expr(e, self);
    }
}

/// `MutVisitor` that inserts `ExprKind::Paren` nodes around every `Expr`.
struct AddParens;

impl MutVisitor for AddParens {
    fn visit_expr(&mut self, e: &mut P<Expr>) {
        mut_visit::noop_visit_expr(e, self);
        visit_clobber(e, |e| {
            P(Expr {
                id: DUMMY_NODE_ID,
                node: ExprKind::Paren(e),
                span: DUMMY_SP,
                attrs: ThinVec::new(),
            })
        });
    }
}

fn main() {
    syntax::with_default_globals(|| run());
}

fn run() {
    let ps = ParseSess::new(FilePathMapping::empty());

    iter_exprs(2, &mut |mut e| {
        // If the pretty printer is correct, then `parse(print(e))` should be identical to `e`,
        // modulo placement of `Paren` nodes.
        let printed = pprust::expr_to_string(&e);
        println!("printed: {}", printed);

        let mut parsed = parse_expr(&ps, &printed);

        // We want to know if `parsed` is structurally identical to `e`, ignoring trivial
        // differences like placement of `Paren`s or the exact ranges of node spans.
        // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s
        // everywhere we can, then pretty-print. This should give an unambiguous representation of
        // each `Expr`, and it bypasses nearly all of the parenthesization logic, so we aren't
        // relying on the correctness of the very thing we're testing.
        RemoveParens.visit_expr(&mut e);
        AddParens.visit_expr(&mut e);
        let text1 = pprust::expr_to_string(&e);
        RemoveParens.visit_expr(&mut parsed);
        AddParens.visit_expr(&mut parsed);
        let text2 = pprust::expr_to_string(&parsed);
        assert!(text1 == text2,
                "exprs are not equal:\n  e =      {:?}\n  parsed = {:?}",
                text1, text2);
    });
}
<|endoftext|>


<commit_before>// Copyright 2020 The Tink-Rust Authors
//
// 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.
//
////////////////////////////////////////////////////////////////////////////////

//! Deterministic authenticated encryption with associated data.

/// `DeterministicAead` is the interface for deterministic authenticated encryption with associated
/// data.
///
/// ## Warning
////
/// Unlike AEAD, implementations of this trait are not semantically secure, because
/// encrypting the same plaintex always yields the same ciphertext.
///
/// ## Security guarantees
///
/// Implementations of this trait provide 128-bit security level against multi-user attacks
/// with up to 2^32 keys. That means if an adversary obtains 2^32 ciphertexts of the same message
/// encrypted under 2^32 keys, they need to do 2^128 computations to obtain a single key.
///
/// Encryption with associated data ensures authenticity (who the sender is) and integrity (the
/// data has not been tampered with) of that data, but not its secrecy.
///
/// ## References
///
/// - [RFC 5116](https://tools.ietf.org/html/rfc5116_
/// - [RFC 5297 s1.3](https://tools.ietf.org/html/rfc5297#section-1.3)
pub trait DeterministicAead: DeterministicAeadBoxClone {
    /// Deterministical encrypt plaintext with `additional_data` as additional authenticated data.
    /// The resulting ciphertext allows for checking authenticity and integrity of additional
    /// data `additional_data`, but there are no guarantees wrt. secrecy of that data.
    fn encrypt_deterministically(
        &self,
        plaintext: &[u8],
        additional_data: &[u8],
    ) -> Result<Vec<u8>, crate::TinkError>;

    /// Deterministically decrypt ciphertext with `additional_data` as
    /// additional authenticated data. The decryption verifies the authenticity and integrity
    /// of the additional data, but there are no guarantees wrt. secrecy of that data.
    fn decrypt_deterministically(
        &self,
        ciphertext: &[u8],
        additional_data: &[u8],
    ) -> Result<Vec<u8>, crate::TinkError>;
}

/// Trait bound to indicate that primitive trait objects should support cloning
/// themselves as trait objects.
pub trait DeterministicAeadBoxClone {
    fn box_clone(&self) -> Box<dyn DeterministicAead>;
}

/// Default implementation of the box-clone trait bound for any underlying
/// concrete type that implements [`Clone`].
impl<T> DeterministicAeadBoxClone for T
where
    T: 'static + DeterministicAead + Clone,
{
    fn box_clone(&self) -> Box<dyn DeterministicAead> {
        Box::new(self.clone())
    }
}
<commit_msg>tink-core: fix typo<commit_after>// Copyright 2020 The Tink-Rust Authors
//
// 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.
//
////////////////////////////////////////////////////////////////////////////////

//! Deterministic authenticated encryption with associated data.

/// `DeterministicAead` is the interface for deterministic authenticated encryption with associated
/// data.
///
/// ## Warning
////
/// Unlike AEAD, implementations of this trait are not semantically secure, because
/// encrypting the same plaintext always yields the same ciphertext.
///
/// ## Security guarantees
///
/// Implementations of this trait provide 128-bit security level against multi-user attacks
/// with up to 2^32 keys. That means if an adversary obtains 2^32 ciphertexts of the same message
/// encrypted under 2^32 keys, they need to do 2^128 computations to obtain a single key.
///
/// Encryption with associated data ensures authenticity (who the sender is) and integrity (the
/// data has not been tampered with) of that data, but not its secrecy.
///
/// ## References
///
/// - [RFC 5116](https://tools.ietf.org/html/rfc5116_
/// - [RFC 5297 s1.3](https://tools.ietf.org/html/rfc5297#section-1.3)
pub trait DeterministicAead: DeterministicAeadBoxClone {
    /// Deterministical encrypt plaintext with `additional_data` as additional authenticated data.
    /// The resulting ciphertext allows for checking authenticity and integrity of additional
    /// data `additional_data`, but there are no guarantees wrt. secrecy of that data.
    fn encrypt_deterministically(
        &self,
        plaintext: &[u8],
        additional_data: &[u8],
    ) -> Result<Vec<u8>, crate::TinkError>;

    /// Deterministically decrypt ciphertext with `additional_data` as
    /// additional authenticated data. The decryption verifies the authenticity and integrity
    /// of the additional data, but there are no guarantees wrt. secrecy of that data.
    fn decrypt_deterministically(
        &self,
        ciphertext: &[u8],
        additional_data: &[u8],
    ) -> Result<Vec<u8>, crate::TinkError>;
}

/// Trait bound to indicate that primitive trait objects should support cloning
/// themselves as trait objects.
pub trait DeterministicAeadBoxClone {
    fn box_clone(&self) -> Box<dyn DeterministicAead>;
}

/// Default implementation of the box-clone trait bound for any underlying
/// concrete type that implements [`Clone`].
impl<T> DeterministicAeadBoxClone for T
where
    T: 'static + DeterministicAead + Clone,
{
    fn box_clone(&self) -> Box<dyn DeterministicAead> {
        Box::new(self.clone())
    }
}
<|endoftext|>