<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/.

//! This module is the main module for the Ligature project.
//! It represents to common types and traits used by Ligature.

#![deny(missing_docs)]
//#![deny(missing_doc_example)] <-- for later, when I'm swole

#[macro_use]
extern crate lazy_static;

use regex::Regex;

/// A string that represents a Dataset by name.
/// Currently can only be ASCII text separated by /
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Dataset(String);

impl Dataset {
    /// Creates a new Dataset and returns a Result based on if it is valid or not.
    pub fn new(name: &str) -> Result<Dataset, LigatureError> {
        lazy_static! {
            static ref RE: Regex = Regex::new(r"^[a-zA-Z_]+(/[a-zA-Z0-9_]+)*$").unwrap();
        }

        if RE.is_match(name) {
            Ok(Dataset(name.to_string()))
        } else {
            Err(LigatureError(format!("Invalid Dataset name {}", name)))
        }
    }

    /// Returns the name of the given Dataset.
    pub fn name(&self) -> &str {
        &self.0
    }
}

/// A node that is only identified by a unique u64 id.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct BlankNode(u64);

/// An IRI is represented via https://www.ietf.org/rfc/rfc3987.txt
/// TODO add validator and tests
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct IRI(String);

/// A unit struct used to represent the concept of a Default Graph in a quad store.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct DefaultGraph;

/// A wrapper type that represents a language tag.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct LangTag(String);

impl LangTag {
    /// Create a new LangTag from a &str and returns a Result based on if it is valid or not.
    pub fn new(tag: &str) -> Result<LangTag, LigatureError> {
        lazy_static! {
            static ref RE: Regex = Regex::new(r"^[a-zA-Z]+(\-[a-zA-Z0-9]+)*$").unwrap();
        }

        if RE.is_match(tag) {
            Ok(LangTag(tag.to_string()))
        } else {
            Err(LigatureError(format!("Invalid LangTag value {}", tag)))
        }
    }

    /// Returns the value of the LangTag.
    pub fn value(&self) -> &str {
        &self.0
    }
}

/// A struct containing text and a language tag that denotes what language the text is expressed in.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct LangLiteral {
    /// The String literal that is represented by this LangLiteral
    pub value: String,
    /// The LangTag that represents the language used to express the value.
    pub lang_tag: LangTag,
}

/// A struct containing a value represented as a String and the type of the value represented by an IRI.
/// TODO probably need a function that double checks a given UnknownLiteral is actually unknown
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct UnknownLiteral {
    /// The value of this literal represented as a String.
    pub value: String,
    /// The IRI that represents this type.
    pub r#type: IRI,
}

/// An enum that represents all the currently supported literal types.
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum Literal {
    /// A tagged LangLiteral used for an RDF literal
    LangLiteral(LangLiteral),
    /// A tagged String used for an RDF literal
    StringLiteral(String),
    /// A tagged bool used for an RDF literal
    BooleanLiteral(bool),
    /// A tagged i64 used for an RDF literal
    LongLiteral(i64),
    /// A tagged f64 used for an RDF literal
    DoubleLiteral(f64),
    /// A tagged UnknownLiteral used for an RDF literal
    UnknownLiteral(UnknownLiteral),
}

/// A set of enums used to express range queries when it makes sense for that type (ie no support for BooleanLiteralRange or UnknownLiteralRange since they don't make sense).
#[derive(Debug)]
pub enum Range {
    /// Represents a range of LangLiterals
    /// Note: LangTag needs to match for any comparison to take place.
    LangLiteralRange {
        /// The starting LangLiteral (inclusive)
        start: LangLiteral,
        /// The end LangLiteral (exclusive)
        end: LangLiteral,
    },
    /// Represents a String range using basic String comparisons.
    StringLiteralRange {
        /// The starting String (inclusive)
        start: String,
        /// The end String (exclusive)
        end: String,
    },
    /// Represents a String range using basic i64 comparisons.
    LongLiteralRange {
        /// The starting i64 (inclusive)
        start: i64,
        /// The end i64 (exclusive)
        end: i64,
    },
    /// Represents a String range using basic f64 comparisons.
    DoubleLiteralRange {
        /// The starting f64 (inclusive)
        start: f64,
        /// The end f64 (exclusive)
        end: f64,
    },
}

/// The set of valid types that can be used as a Subject.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub enum Subject {
    /// A tagged IRI used as a Subject.
    IRI(IRI),
    /// A tagged BlankNode used as a Subject.
    BlankNode(BlankNode),
    /// A tagged DefaultGraph used as a Subject.
    DefaultGraph(DefaultGraph),
}

/// The set of valid types that can be used as a Predicate.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub enum Predicate {
    /// A tagged IRI used as a Predicate.
    IRI(IRI),
}

/// The set of valid types that can be used as an Object.
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum Object {
    /// A tagged Subject used as an Object.
    Subject(Subject),
    /// A tagged Literal used as an Object.
    Literal(Literal),
}

/// The set of valid types that can be used as a Graph name.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub enum Graph {
    /// A tagged IRI used as a Graph.
    IRI(IRI),
    /// A tagged BlankNode used as a Graph.
    BlankNode(BlankNode),
    /// A tagged DefaultGraph used as a Graph.
    DefaultGraph(DefaultGraph),
}

/// A Statement is a grouping of Subject, Predicate, and Object.
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Statement {
    /// The Subject of a Statement
    pub subject: Subject,
    /// The Predicate of a Statement
    pub predicate: Predicate,
    /// The Object of a Statement
    pub object: Object,
    /// The Graph this Statement is in
    pub graph: Graph,
}

//val a: IRI = IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").getOrElse(???)

/// A general struct for representing errors involving Ligature.
/// TODO should probably be an enum with a bunch of specific cases
#[derive(Debug)]
pub struct LigatureError(String);

/// A struct that is returned from SPAQRL and wander queries.
pub struct QueryResult {
    /// A Vec of headers for the results.
    pub headers: Vec<String>,
    /// A stream of results, the inner Vec has the same lenth as the headers Vec.
    pub results: Box<dyn Iterator<Item = Vec<Object>>>,
}

/// A trait that all Ligature implementations implement.
pub trait Ligature {
    /// Returns all Datasets in a Ligature instance.
    fn all_datasets(&self) -> Box<dyn Iterator<Item = Dataset>>;

    /// Returns all Datasets in a Ligature instance that start with the given prefix.
    fn match_datasets(&self, prefix: &str) -> Box<dyn Iterator<Item = Dataset>>;

    /// Returns all Datasets in a Ligature instance that are in a given range (inclusive, exclusive].
    fn match_datasets_range(&self, start: &str, end: &str) -> Box<dyn Iterator<Item = Dataset>>;

    /// Creates a dataset with the given name.
    /// TODO should probably return its own error type { InvalidDataset, DatasetExists, CouldNotCreateDataset }
    fn create_dataset(&self, dataset: Dataset) -> Result<(), LigatureError>;

    /// Deletes a dataset with the given name.
    /// TODO should probably return its own error type { InvalidDataset, CouldNotDeleteDataset }
    fn delete_dataset(&self, dataset: Dataset) -> Result<(), LigatureError>;

    /// Initiazes a QueryTx
    /// TODO should probably return its own error type CouldNotInitializeQueryTx
    fn query(&self, dataset: Dataset) -> Result<Box<dyn QueryTx>, LigatureError>;

    /// Initiazes a WriteTx
    /// TODO should probably return its own error type CouldNotInitializeWriteTx
    fn write(&self, dataset: Dataset) -> Result<Box<dyn WriteTx>, LigatureError>;
}

/// Represents a QueryTx within the context of a Ligature instance and a single Dataset
pub trait QueryTx {
    /// Returns all Statements in this Dataset as Statements.
    /// TODO should probably return a Result
    fn all_statements(&self) -> Box<dyn Iterator<Item = Statement>>;

    /// Run a SPARQL query.
    fn sparql_query(&self, query: String) -> Result<QueryResult, LigatureError>;

    /// Run a wander query.
    fn wander_query(&self, query: String) -> Result<QueryResult, LigatureError>;
}

/// Represents a WriteTx within the context of a Ligature instance and a single Dataset
pub trait WriteTx {
    /// Creates a new, unique BlankNode within this Dataset.
    /// Note: BlankNodes are shared across named graphs in a given Dataset.
    fn new_blank_node(&self) -> Result<BlankNode, LigatureError>;

    /// Adds a given Statement to this Dataset.
    /// If the Statement already exists nothing happens.
    /// Note: Potentally could trigger a ValidationError
    fn add_statement(&self, statement: Statement) -> Result<Statement, LigatureError>;

    /// Removes a given Statement from this Dataset.
    /// If the Statement doesn't exist nothing happens.
    /// Note: Potentally could trigger a ValidationError.
    fn remove_statement(&self, statement: Statement) -> Result<Statement, LigatureError>;

    /// Cancels this transaction so that none of the changes made so far will be stored.
    /// This also closes this transaction so no other methods can be called.
    fn cancel(&self) -> Result<(), LigatureError>;

    /// Commits this transaction.
    /// This also closes this transaction so no other methods can be called.
    fn commit(&self) -> Result<(), LigatureError>;
}
<commit_msg>making message in LigatureError public<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/.

//! This module is the main module for the Ligature project.
//! It represents to common types and traits used by Ligature.

#![deny(missing_docs)]
//#![deny(missing_doc_example)] <-- for later, when I'm swole

#[macro_use]
extern crate lazy_static;

use regex::Regex;

/// A string that represents a Dataset by name.
/// Currently can only be ASCII text separated by /
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Dataset(String);

impl Dataset {
    /// Creates a new Dataset and returns a Result based on if it is valid or not.
    pub fn new(name: &str) -> Result<Dataset, LigatureError> {
        lazy_static! {
            static ref RE: Regex = Regex::new(r"^[a-zA-Z_]+(/[a-zA-Z0-9_]+)*$").unwrap();
        }

        if RE.is_match(name) {
            Ok(Dataset(name.to_string()))
        } else {
            Err(LigatureError(format!("Invalid Dataset name {}", name)))
        }
    }

    /// Returns the name of the given Dataset.
    pub fn name(&self) -> &str {
        &self.0
    }
}

/// A node that is only identified by a unique u64 id.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct BlankNode(u64);

/// An IRI is represented via https://www.ietf.org/rfc/rfc3987.txt
/// TODO add validator and tests
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct IRI(String);

/// A unit struct used to represent the concept of a Default Graph in a quad store.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct DefaultGraph;

/// A wrapper type that represents a language tag.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct LangTag(String);

impl LangTag {
    /// Create a new LangTag from a &str and returns a Result based on if it is valid or not.
    pub fn new(tag: &str) -> Result<LangTag, LigatureError> {
        lazy_static! {
            static ref RE: Regex = Regex::new(r"^[a-zA-Z]+(\-[a-zA-Z0-9]+)*$").unwrap();
        }

        if RE.is_match(tag) {
            Ok(LangTag(tag.to_string()))
        } else {
            Err(LigatureError(format!("Invalid LangTag value {}", tag)))
        }
    }

    /// Returns the value of the LangTag.
    pub fn value(&self) -> &str {
        &self.0
    }
}

/// A struct containing text and a language tag that denotes what language the text is expressed in.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct LangLiteral {
    /// The String literal that is represented by this LangLiteral
    pub value: String,
    /// The LangTag that represents the language used to express the value.
    pub lang_tag: LangTag,
}

/// A struct containing a value represented as a String and the type of the value represented by an IRI.
/// TODO probably need a function that double checks a given UnknownLiteral is actually unknown
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct UnknownLiteral {
    /// The value of this literal represented as a String.
    pub value: String,
    /// The IRI that represents this type.
    pub r#type: IRI,
}

/// An enum that represents all the currently supported literal types.
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum Literal {
    /// A tagged LangLiteral used for an RDF literal
    LangLiteral(LangLiteral),
    /// A tagged String used for an RDF literal
    StringLiteral(String),
    /// A tagged bool used for an RDF literal
    BooleanLiteral(bool),
    /// A tagged i64 used for an RDF literal
    LongLiteral(i64),
    /// A tagged f64 used for an RDF literal
    DoubleLiteral(f64),
    /// A tagged UnknownLiteral used for an RDF literal
    UnknownLiteral(UnknownLiteral),
}

/// A set of enums used to express range queries when it makes sense for that type (ie no support for BooleanLiteralRange or UnknownLiteralRange since they don't make sense).
#[derive(Debug)]
pub enum Range {
    /// Represents a range of LangLiterals
    /// Note: LangTag needs to match for any comparison to take place.
    LangLiteralRange {
        /// The starting LangLiteral (inclusive)
        start: LangLiteral,
        /// The end LangLiteral (exclusive)
        end: LangLiteral,
    },
    /// Represents a String range using basic String comparisons.
    StringLiteralRange {
        /// The starting String (inclusive)
        start: String,
        /// The end String (exclusive)
        end: String,
    },
    /// Represents a String range using basic i64 comparisons.
    LongLiteralRange {
        /// The starting i64 (inclusive)
        start: i64,
        /// The end i64 (exclusive)
        end: i64,
    },
    /// Represents a String range using basic f64 comparisons.
    DoubleLiteralRange {
        /// The starting f64 (inclusive)
        start: f64,
        /// The end f64 (exclusive)
        end: f64,
    },
}

/// The set of valid types that can be used as a Subject.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub enum Subject {
    /// A tagged IRI used as a Subject.
    IRI(IRI),
    /// A tagged BlankNode used as a Subject.
    BlankNode(BlankNode),
    /// A tagged DefaultGraph used as a Subject.
    DefaultGraph(DefaultGraph),
}

/// The set of valid types that can be used as a Predicate.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub enum Predicate {
    /// A tagged IRI used as a Predicate.
    IRI(IRI),
}

/// The set of valid types that can be used as an Object.
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum Object {
    /// A tagged Subject used as an Object.
    Subject(Subject),
    /// A tagged Literal used as an Object.
    Literal(Literal),
}

/// The set of valid types that can be used as a Graph name.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub enum Graph {
    /// A tagged IRI used as a Graph.
    IRI(IRI),
    /// A tagged BlankNode used as a Graph.
    BlankNode(BlankNode),
    /// A tagged DefaultGraph used as a Graph.
    DefaultGraph(DefaultGraph),
}

/// A Statement is a grouping of Subject, Predicate, and Object.
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct Statement {
    /// The Subject of a Statement
    pub subject: Subject,
    /// The Predicate of a Statement
    pub predicate: Predicate,
    /// The Object of a Statement
    pub object: Object,
    /// The Graph this Statement is in
    pub graph: Graph,
}

//val a: IRI = IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").getOrElse(???)

/// A general struct for representing errors involving Ligature.
/// TODO should probably be an enum with a bunch of specific cases
#[derive(Debug)]
pub struct LigatureError(pub String);

/// A struct that is returned from SPAQRL and wander queries.
pub struct QueryResult {
    /// A Vec of headers for the results.
    pub headers: Vec<String>,
    /// A stream of results, the inner Vec has the same lenth as the headers Vec.
    pub results: Box<dyn Iterator<Item = Vec<Object>>>,
}

/// A trait that all Ligature implementations implement.
pub trait Ligature {
    /// Returns all Datasets in a Ligature instance.
    fn all_datasets(&self) -> Box<dyn Iterator<Item = Dataset>>;

    /// Returns all Datasets in a Ligature instance that start with the given prefix.
    fn match_datasets(&self, prefix: &str) -> Box<dyn Iterator<Item = Dataset>>;

    /// Returns all Datasets in a Ligature instance that are in a given range (inclusive, exclusive].
    fn match_datasets_range(&self, start: &str, end: &str) -> Box<dyn Iterator<Item = Dataset>>;

    /// Creates a dataset with the given name.
    /// TODO should probably return its own error type { InvalidDataset, DatasetExists, CouldNotCreateDataset }
    fn create_dataset(&self, dataset: Dataset) -> Result<(), LigatureError>;

    /// Deletes a dataset with the given name.
    /// TODO should probably return its own error type { InvalidDataset, CouldNotDeleteDataset }
    fn delete_dataset(&self, dataset: Dataset) -> Result<(), LigatureError>;

    /// Initiazes a QueryTx
    /// TODO should probably return its own error type CouldNotInitializeQueryTx
    fn query(&self, dataset: Dataset) -> Result<Box<dyn QueryTx>, LigatureError>;

    /// Initiazes a WriteTx
    /// TODO should probably return its own error type CouldNotInitializeWriteTx
    fn write(&self, dataset: Dataset) -> Result<Box<dyn WriteTx>, LigatureError>;
}

/// Represents a QueryTx within the context of a Ligature instance and a single Dataset
pub trait QueryTx {
    /// Returns all Statements in this Dataset as Statements.
    /// TODO should probably return a Result
    fn all_statements(&self) -> Box<dyn Iterator<Item = Statement>>;

    /// Run a SPARQL query.
    fn sparql_query(&self, query: String) -> Result<QueryResult, LigatureError>;

    /// Run a wander query.
    fn wander_query(&self, query: String) -> Result<QueryResult, LigatureError>;
}

/// Represents a WriteTx within the context of a Ligature instance and a single Dataset
pub trait WriteTx {
    /// Creates a new, unique BlankNode within this Dataset.
    /// Note: BlankNodes are shared across named graphs in a given Dataset.
    fn new_blank_node(&self) -> Result<BlankNode, LigatureError>;

    /// Adds a given Statement to this Dataset.
    /// If the Statement already exists nothing happens.
    /// Note: Potentally could trigger a ValidationError
    fn add_statement(&self, statement: Statement) -> Result<Statement, LigatureError>;

    /// Removes a given Statement from this Dataset.
    /// If the Statement doesn't exist nothing happens.
    /// Note: Potentally could trigger a ValidationError.
    fn remove_statement(&self, statement: Statement) -> Result<Statement, LigatureError>;

    /// Cancels this transaction so that none of the changes made so far will be stored.
    /// This also closes this transaction so no other methods can be called.
    fn cancel(&self) -> Result<(), LigatureError>;

    /// Commits this transaction.
    /// This also closes this transaction so no other methods can be called.
    fn commit(&self) -> Result<(), LigatureError>;
}
<|endoftext|>


<commit_before>extern crate nix;
extern crate cargo;
extern crate gimli;
extern crate object;
extern crate memmap;
extern crate coveralls_api;
extern crate fallible_iterator;
extern crate rustc_demangle;
extern crate regex;
#[macro_use]
extern crate clap;
extern crate serde;
extern crate serde_json;

use std::env;
use std::io;
use std::process;
use std::io::{Error, ErrorKind};
use std::ffi::CString;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::collections::HashMap;
use nix::Error as NixErr;
use nix::unistd::*;
use nix::libc::pid_t;
use nix::sys::signal;
use nix::sys::wait::*;
use cargo::util::Config as CargoConfig;
use cargo::core::Workspace;
use cargo::ops;

pub mod config;
pub mod tracer;
pub mod breakpoint;
pub mod report;
/// Should be unnecessary with a future nix crate release.
mod personality;
mod ptrace_control;

use config::*;
use tracer::*;
use breakpoint::*;
use ptrace_control::*;

const PIE_ERROR: &'static str = "ERROR: Tarpaulin cannot find code addresses check that \
pie is disabled for your linker. If linking with gcc try adding -C link-args=-no-pie \
to your rust flags";

/// Launches tarpaulin with the given configuration.
pub fn launch_tarpaulin(config: Config) {
    let cargo_config = CargoConfig::default().unwrap();
    let flag_quiet = if config.verbose {
        None
    } else {
        Some(true)
    };
    // This shouldn't fail so no checking the error.
    let _ = cargo_config.configure(0u32,
                                   flag_quiet,
                                   &None,
                                   false,
                                   false);

    let workspace = match Workspace::new(config.manifest.as_path(), &cargo_config) {
        Ok(w) => w,
        Err(_) => panic!("Invalid project directory specified"),
    };

    let filter = ops::CompileFilter::Everything;
    let rustflags = "RUSTFLAGS";
    let mut value = "-C relocation-model=dynamic-no-pic -C link-dead-code ".to_string();
    {
        let host = get_target_path(&cargo_config, &cargo_config.rustc().unwrap().host);
        let target_linker = match cargo_config.get_string("build.target").unwrap().map(|s| s.val) {
            Some(triple) => get_target_path(&cargo_config, &triple),
            None => host,
        };

        fn get_target_path(cargo_config: &CargoConfig, triple: &str) -> Option<PathBuf> {
            cargo_config.get_path(&format!("target.{}.linker", triple)).unwrap().map(|v| v.val)
        }

        // For Linux (and most everything that isn't Windows) it is fair to
        // assume the default linker is `cc` and that `cc` is GCC based.
        let mut linker_cmd = Command::new(&target_linker.unwrap_or(PathBuf::from("cc")));
        linker_cmd.arg("-v");
        if let Ok(linker_output) = linker_cmd.output() {
            if String::from_utf8_lossy(&linker_output.stderr).contains("--enable-default-pie") {
                value.push_str("-C link-args=-no-pie ");
            }
        }
    }
    if let Ok(vtemp) = env::var(rustflags) {
        value.push_str(vtemp.as_ref());
    }
    env::set_var(rustflags, value);

    let clean_opt = ops::CleanOptions {
        config: &cargo_config,
        spec: &[],
        target: None,
        release: false,
    };

    let copt = ops::CompileOptions {
        config: &cargo_config,
        jobs: None,
        target: None,
        features: &[],
        all_features: true,
        no_default_features:false ,
        spec: ops::Packages::All,
        release: false,
        mode: ops::CompileMode::Test,
        filter: filter,
        message_format: ops::MessageFormat::Human,
        target_rustdoc_args: None,
        target_rustc_args: None,
    };
    let mut result:Vec<TracerData> = Vec::new();
    if config.verbose {
        println!("Running Tarpaulin");
    }
    // Clean isn't expected to fail and if it does it likely won't have an effect
    let _ = ops::clean(&workspace, &clean_opt);
    let compilation = ops::compile(&workspace, &copt);
    match compilation {
        Ok(comp) => {
            for c in comp.tests.iter() {
                if config.verbose {
                    println!("Processing {}", c.1);
                }
                let res = get_test_coverage(workspace.root(), c.2.as_path(), false)
                    .unwrap_or(vec![]);
                merge_test_results(&mut result, &res);
                if config.run_ignored {
                    let res = get_test_coverage(workspace.root(), c.2.as_path(), true)
                        .unwrap_or(vec![]);
                    merge_test_results(&mut result, &res);
                }
            }
        },
        Err(e) => {
            if config.verbose{
                println!("Error: failed to compile: {}", e);
            }
        },
    }
    report_coverage(&config, &result);
}

/// Test artefacts may have different lines visible to them therefore for
/// each test artefact covered we need to merge the TracerData entries to get
/// the overall coverage.
pub fn merge_test_results(master: &mut Vec<TracerData>, new: &Vec<TracerData>) {
    let mut unmerged:Vec<TracerData> = Vec::new();
    for t in new.iter() {
        let mut update = master.iter_mut()
                               .filter(|x| x.path== t.path && x.line == t.line)
                               .collect::<Vec<_>>();
        for ref mut u in update.iter_mut() {
            u.hits += t.hits;
        }

        if update.iter().count() == 0 {
            unmerged.push(t.clone());
        }
    }
    master.append(&mut unmerged);
}

/// Strips the directory the project manifest is in from the path. Provides a
/// nicer path for printing to the user.
fn strip_project_path<'a>(config: &'a Config, path: &'a Path) -> &'a Path {
    if let Some(root) = config.manifest.parent() {
        &path.strip_prefix(root).unwrap_or(path)
    } else {
        path
    }
}

/// Reports the test coverage using the users preferred method. See config.rs
/// or help text for details.
pub fn report_coverage(config: &Config, result: &Vec<TracerData>) {
    if result.len() > 0 {
        println!("Coverage Results");
        if config.verbose {
            for r in result.iter() {
                let path = strip_project_path(config, r.path.as_path());
                println!("{}:{} - hits: {}", path.display(), r.line, r.hits);
            }
            println!("");
        }
        // Hash map of files with the value (lines covered, total lines)
        let mut file_map: HashMap<&Path, (u64, u64)> = HashMap::new();
        for r in result.iter() {
            if file_map.contains_key(r.path.as_path()) {
                if let Some(v) = file_map.get_mut(r.path.as_path()) {
                    (*v).0 += (r.hits > 0) as u64;
                    (*v).1 += 1u64;
                }
            } else {
                file_map.insert(r.path.as_path(), ((r.hits > 0) as u64, 1));
            }
        }
        for (k, v) in file_map.iter() {
            let path = strip_project_path(config, k);
            println!("{}: {}/{}", path.display(), v.0, v.1);
        }
        let covered = result.iter().filter(|&x| (x.hits > 0 )).count();
        let total = result.iter().count();
        let percent = (covered as f64)/(total as f64) * 100.0f64;
        // Put file filtering here
        println!("\n{:.2}% coverage, {}/{} lines covered", percent, covered, total);
        if config.is_coveralls() {
            println!("Sending coverage data to coveralls.io");
            report::coveralls::export(&result, config);
            println!("Coverage data sent");
        }
    } else {
        println!("No coverage results collected.");
    }

}

/// Returns the coverage statistics for a test executable in the given workspace
pub fn get_test_coverage(root: &Path, test: &Path, ignored: bool) -> Option<Vec<TracerData>> {
    if !test.exists() {
        return None;
    }
    match fork() {
        Ok(ForkResult::Parent{ child }) => {
            match collect_coverage(root, test, child) {
                Ok(t) => {
                    Some(t)
                },
                Err(e) => {
                    println!("Error occurred: {}", e);
                    None
                },
            }
        }
        Ok(ForkResult::Child) => {
            println!("Launching test");
            execute_test(test, ignored, true);
            None
        }
        Err(err) => {
            println!("Failed to run {}", test.display());
            println!("Error {}", err);
            None
        }
    }

}

/// Collects the coverage data from the launched test
fn collect_coverage(project_path: &Path,
                    test_path: &Path,
                    test: pid_t) -> io::Result<Vec<TracerData>> {
    let mut traces = generate_tracer_data(project_path, test_path)?;
    let mut bps: HashMap<u64, Breakpoint> = HashMap::new();
    match waitpid(test, None) {
        Ok(WaitStatus::Stopped(child, signal::SIGTRAP)) => {
            let child_trace = trace_children(child);
            if let Err(c) = child_trace {
                println!("Failed to trace child threads: {}", c);
            }
            for trace in traces.iter() {
                match Breakpoint::new(child, trace.address) {
                    Ok(bp) => {
                        let _ = bps.insert(trace.address, bp);
                    },
                    Err(e) if e == NixErr::Sys(nix::Errno::EIO) => {
                        println!("{}", PIE_ERROR);
                        process::exit(1);
                    },
                    Err(e) => println!("Failed to instrument {}", e),
                }
            }
        },
        Ok(_) => println!("Unexpected grab"),
        Err(err) => println!("Error on start: {}", err)
    }
    // Now we start hitting lines!
    //run_coverage_on_all_tests(test, &mut traces, &mut bps);
    match run_function(test, u64::max_value(), &mut traces, &mut bps) {
        Err(e) => println!("Error while collecting coverage. {}", e),
        _ => {},
    }
    Ok(traces)
}

/// Starts running a test. Child must have signalled STOP or SIGNALED to show
/// the parent it is not executing or it will be killed.
fn run_function(pid: pid_t,
                end: u64,
                mut traces: &mut Vec<TracerData>,
                mut breakpoints: &mut HashMap<u64, Breakpoint>) -> Result<i8, Error> {
    let mut res = 0i8;
    // Start the function running.
    continue_exec(pid)?;
    loop {
        match waitpid(-1, Some(__WALL)) {
            Ok(WaitStatus::Exited(child, sig)) => {
                res = sig;
                // If test executable exiting break, else continue the program
                // to launch the next test function
                if child == pid {
                    break;
                } else {
                    // The err will be no child process and means test is over.
                    let _ =continue_exec(pid);
                }
            },
            Ok(WaitStatus::Stopped(child, signal::SIGTRAP)) => {
                if let Ok(rip) = current_instruction_pointer(child) {
                    let rip = (rip - 1) as u64;
                    if  breakpoints.contains_key(&rip) {
                        let ref mut bp = breakpoints.get_mut(&rip).unwrap();
                        let updated = if let Ok(x) = bp.process(Some(child)) {
                            x
                        } else {
                            rip == end
                        };
                        if updated {
                            for mut t in traces.iter_mut()
                                               .filter(|ref x| x.address == rip) {
                                (*t).hits += 1;
                            }
                        }
                    } else {
                        continue_exec(child)?;
                    }
                }
            },
            Ok(WaitStatus::Stopped(child, signal::SIGSTOP)) => {
                continue_exec(child)?;
            },
            Ok(WaitStatus::Stopped(child, sig)) => {
                println!("Unexpected signal {:?}", sig);
                continue_exec(child)?;
            },
            Ok(WaitStatus::PtraceEvent(child, signal::SIGTRAP, 3)) => {
                if let Ok(_) = get_event_data(child) {
                    continue_exec(child)?;
                }
            },
            Ok(WaitStatus::Signaled(_, signal::SIGTRAP, true)) => break,
            Ok(_) => {
                println!("Unexpected stop");
                break;
            },
            Err(e) => {
                return Err(Error::new(ErrorKind::Other, e))
            },
        }
    }
    Ok(res)
}

/// Launches the test executable
fn execute_test(test: &Path, ignored: bool, backtrace_on: bool) {
    let exec_path = CString::new(test.to_str().unwrap()).unwrap();
    match personality::disable_aslr() {
        Ok(_) => {},
        Err(e) => println!("ASLR disable failed: {}", e),
    }
    request_trace().ok()
                   .expect("Failed to trace");

    let mut envars: Vec<CString> = vec![CString::new("RUST_TEST_THREADS=1").unwrap()];
    for (key, value) in env::vars() {
        let mut temp = String::new();
        temp.push_str(key.as_str());
        temp.push('=');
        temp.push_str(value.as_str());
        envars.push(CString::new(temp).unwrap());
    }
    if backtrace_on {
        envars.push(CString::new("RUST_BACKTRACE=1").unwrap());
    }
    let argv = if ignored {
        vec![exec_path.clone(), CString::new("--ignored").unwrap()]
    } else {
        vec![exec_path.clone()]
    };
    execve(&exec_path, &argv, envars.as_slice())
        .unwrap();
}

#[cfg(test)]
mod tests {
    use std::path::PathBuf;
    use ::*;

    #[test]
    fn result_merge_test() {
        let mut master:Vec<TracerData> = vec![];

        master.push(TracerData {
            path: PathBuf::from("testing/test.rs"),
            line: 2,
            address: 0,
            trace_type: LineType::Unknown,
            hits: 1
        });
        master.push(TracerData {
            path: PathBuf::from("testing/test.rs"),
            line: 3,
            address: 1,
            trace_type: LineType::Unknown,
            hits: 1
        });
        master.push(TracerData {
            path: PathBuf::from("testing/not.rs"),
            line: 2,
            address: 0,
            trace_type: LineType::Unknown,
            hits: 7
        });

        let other:Vec<TracerData> = vec![
            TracerData {
                path:PathBuf::from("testing/test.rs"),
                line: 2,
                address: 0,
                trace_type: LineType::Unknown,
                hits: 2
            }];

        merge_test_results(&mut master, &other);
        let expected = vec![3, 1, 7];
        for (act, exp) in master.iter().zip(expected) {
            assert_eq!(act.hits, exp);
        }
    }

}
<commit_msg>Check RUSTFLAGS for a linker before going to the cargo configs<commit_after>extern crate nix;
extern crate cargo;
extern crate gimli;
extern crate object;
extern crate memmap;
extern crate coveralls_api;
extern crate fallible_iterator;
extern crate rustc_demangle;
extern crate regex;
#[macro_use]
extern crate clap;
extern crate serde;
extern crate serde_json;

use std::env;
use std::io;
use std::process;
use std::io::{Error, ErrorKind};
use std::ffi::CString;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::collections::HashMap;
use nix::Error as NixErr;
use nix::unistd::*;
use nix::libc::pid_t;
use nix::sys::signal;
use nix::sys::wait::*;
use cargo::util::Config as CargoConfig;
use cargo::core::Workspace;
use cargo::ops;

pub mod config;
pub mod tracer;
pub mod breakpoint;
pub mod report;
/// Should be unnecessary with a future nix crate release.
mod personality;
mod ptrace_control;

use config::*;
use tracer::*;
use breakpoint::*;
use ptrace_control::*;

const PIE_ERROR: &'static str = "ERROR: Tarpaulin cannot find code addresses check that \
pie is disabled for your linker. If linking with gcc try adding -C link-args=-no-pie \
to your rust flags";

/// Launches tarpaulin with the given configuration.
pub fn launch_tarpaulin(config: Config) {
    let cargo_config = CargoConfig::default().unwrap();
    let flag_quiet = if config.verbose {
        None
    } else {
        Some(true)
    };
    // This shouldn't fail so no checking the error.
    let _ = cargo_config.configure(0u32,
                                   flag_quiet,
                                   &None,
                                   false,
                                   false);

    let workspace = match Workspace::new(config.manifest.as_path(), &cargo_config) {
        Ok(w) => w,
        Err(_) => panic!("Invalid project directory specified"),
    };

    let filter = ops::CompileFilter::Everything;
    let rustflags = "RUSTFLAGS";
    let mut value = "-C relocation-model=dynamic-no-pic -C link-dead-code ".to_string();
    {
        let env_linker = env::var(rustflags)
                            .ok()
                            .and_then(|flags| flags.split(" ")
                                                   .map(str::trim)
                                                   .filter(|s| !s.is_empty())
                                                   .skip_while(|s| !s.contains("linker="))
                                                   .next()
                                                   .map(|s| s.trim_left_matches("linker="))
                                                   .map(|s| PathBuf::from(s)));

        let target_linker = env_linker.or_else(|| {
            fn get_target_path(cargo_config: &CargoConfig, triple: &str) -> Option<PathBuf> {
                cargo_config.get_path(&format!("target.{}.linker", triple)).unwrap().map(|v| v.val)
            }

            let host = get_target_path(&cargo_config, &cargo_config.rustc().unwrap().host);
            match cargo_config.get_string("build.target").unwrap().map(|s| s.val) {
                Some(triple) => get_target_path(&cargo_config, &triple),
                None => host,
            }
        });

        // For Linux (and most everything that isn't Windows) it is fair to
        // assume the default linker is `cc` and that `cc` is GCC based.
        let mut linker_cmd = Command::new(&target_linker.unwrap_or(PathBuf::from("cc")));
        linker_cmd.arg("-v");
        if let Ok(linker_output) = linker_cmd.output() {
            if String::from_utf8_lossy(&linker_output.stderr).contains("--enable-default-pie") {
                value.push_str("-C link-args=-no-pie ");
            }
        }
    }
    if let Ok(vtemp) = env::var(rustflags) {
        value.push_str(vtemp.as_ref());
    }
    env::set_var(rustflags, value);

    let clean_opt = ops::CleanOptions {
        config: &cargo_config,
        spec: &[],
        target: None,
        release: false,
    };

    let copt = ops::CompileOptions {
        config: &cargo_config,
        jobs: None,
        target: None,
        features: &[],
        all_features: true,
        no_default_features:false ,
        spec: ops::Packages::All,
        release: false,
        mode: ops::CompileMode::Test,
        filter: filter,
        message_format: ops::MessageFormat::Human,
        target_rustdoc_args: None,
        target_rustc_args: None,
    };
    let mut result:Vec<TracerData> = Vec::new();
    if config.verbose {
        println!("Running Tarpaulin");
    }
    // Clean isn't expected to fail and if it does it likely won't have an effect
    let _ = ops::clean(&workspace, &clean_opt);
    let compilation = ops::compile(&workspace, &copt);
    match compilation {
        Ok(comp) => {
            for c in comp.tests.iter() {
                if config.verbose {
                    println!("Processing {}", c.1);
                }
                let res = get_test_coverage(workspace.root(), c.2.as_path(), false)
                    .unwrap_or(vec![]);
                merge_test_results(&mut result, &res);
                if config.run_ignored {
                    let res = get_test_coverage(workspace.root(), c.2.as_path(), true)
                        .unwrap_or(vec![]);
                    merge_test_results(&mut result, &res);
                }
            }
        },
        Err(e) => {
            if config.verbose{
                println!("Error: failed to compile: {}", e);
            }
        },
    }
    report_coverage(&config, &result);
}

/// Test artefacts may have different lines visible to them therefore for
/// each test artefact covered we need to merge the TracerData entries to get
/// the overall coverage.
pub fn merge_test_results(master: &mut Vec<TracerData>, new: &Vec<TracerData>) {
    let mut unmerged:Vec<TracerData> = Vec::new();
    for t in new.iter() {
        let mut update = master.iter_mut()
                               .filter(|x| x.path== t.path && x.line == t.line)
                               .collect::<Vec<_>>();
        for ref mut u in update.iter_mut() {
            u.hits += t.hits;
        }

        if update.iter().count() == 0 {
            unmerged.push(t.clone());
        }
    }
    master.append(&mut unmerged);
}

/// Strips the directory the project manifest is in from the path. Provides a
/// nicer path for printing to the user.
fn strip_project_path<'a>(config: &'a Config, path: &'a Path) -> &'a Path {
    if let Some(root) = config.manifest.parent() {
        &path.strip_prefix(root).unwrap_or(path)
    } else {
        path
    }
}

/// Reports the test coverage using the users preferred method. See config.rs
/// or help text for details.
pub fn report_coverage(config: &Config, result: &Vec<TracerData>) {
    if result.len() > 0 {
        println!("Coverage Results");
        if config.verbose {
            for r in result.iter() {
                let path = strip_project_path(config, r.path.as_path());
                println!("{}:{} - hits: {}", path.display(), r.line, r.hits);
            }
            println!("");
        }
        // Hash map of files with the value (lines covered, total lines)
        let mut file_map: HashMap<&Path, (u64, u64)> = HashMap::new();
        for r in result.iter() {
            if file_map.contains_key(r.path.as_path()) {
                if let Some(v) = file_map.get_mut(r.path.as_path()) {
                    (*v).0 += (r.hits > 0) as u64;
                    (*v).1 += 1u64;
                }
            } else {
                file_map.insert(r.path.as_path(), ((r.hits > 0) as u64, 1));
            }
        }
        for (k, v) in file_map.iter() {
            let path = strip_project_path(config, k);
            println!("{}: {}/{}", path.display(), v.0, v.1);
        }
        let covered = result.iter().filter(|&x| (x.hits > 0 )).count();
        let total = result.iter().count();
        let percent = (covered as f64)/(total as f64) * 100.0f64;
        // Put file filtering here
        println!("\n{:.2}% coverage, {}/{} lines covered", percent, covered, total);
        if config.is_coveralls() {
            println!("Sending coverage data to coveralls.io");
            report::coveralls::export(&result, config);
            println!("Coverage data sent");
        }
    } else {
        println!("No coverage results collected.");
    }

}

/// Returns the coverage statistics for a test executable in the given workspace
pub fn get_test_coverage(root: &Path, test: &Path, ignored: bool) -> Option<Vec<TracerData>> {
    if !test.exists() {
        return None;
    }
    match fork() {
        Ok(ForkResult::Parent{ child }) => {
            match collect_coverage(root, test, child) {
                Ok(t) => {
                    Some(t)
                },
                Err(e) => {
                    println!("Error occurred: {}", e);
                    None
                },
            }
        }
        Ok(ForkResult::Child) => {
            println!("Launching test");
            execute_test(test, ignored, true);
            None
        }
        Err(err) => {
            println!("Failed to run {}", test.display());
            println!("Error {}", err);
            None
        }
    }

}

/// Collects the coverage data from the launched test
fn collect_coverage(project_path: &Path,
                    test_path: &Path,
                    test: pid_t) -> io::Result<Vec<TracerData>> {
    let mut traces = generate_tracer_data(project_path, test_path)?;
    let mut bps: HashMap<u64, Breakpoint> = HashMap::new();
    match waitpid(test, None) {
        Ok(WaitStatus::Stopped(child, signal::SIGTRAP)) => {
            let child_trace = trace_children(child);
            if let Err(c) = child_trace {
                println!("Failed to trace child threads: {}", c);
            }
            for trace in traces.iter() {
                match Breakpoint::new(child, trace.address) {
                    Ok(bp) => {
                        let _ = bps.insert(trace.address, bp);
                    },
                    Err(e) if e == NixErr::Sys(nix::Errno::EIO) => {
                        println!("{}", PIE_ERROR);
                        process::exit(1);
                    },
                    Err(e) => println!("Failed to instrument {}", e),
                }
            }
        },
        Ok(_) => println!("Unexpected grab"),
        Err(err) => println!("Error on start: {}", err)
    }
    // Now we start hitting lines!
    //run_coverage_on_all_tests(test, &mut traces, &mut bps);
    match run_function(test, u64::max_value(), &mut traces, &mut bps) {
        Err(e) => println!("Error while collecting coverage. {}", e),
        _ => {},
    }
    Ok(traces)
}

/// Starts running a test. Child must have signalled STOP or SIGNALED to show
/// the parent it is not executing or it will be killed.
fn run_function(pid: pid_t,
                end: u64,
                mut traces: &mut Vec<TracerData>,
                mut breakpoints: &mut HashMap<u64, Breakpoint>) -> Result<i8, Error> {
    let mut res = 0i8;
    // Start the function running.
    continue_exec(pid)?;
    loop {
        match waitpid(-1, Some(__WALL)) {
            Ok(WaitStatus::Exited(child, sig)) => {
                res = sig;
                // If test executable exiting break, else continue the program
                // to launch the next test function
                if child == pid {
                    break;
                } else {
                    // The err will be no child process and means test is over.
                    let _ =continue_exec(pid);
                }
            },
            Ok(WaitStatus::Stopped(child, signal::SIGTRAP)) => {
                if let Ok(rip) = current_instruction_pointer(child) {
                    let rip = (rip - 1) as u64;
                    if  breakpoints.contains_key(&rip) {
                        let ref mut bp = breakpoints.get_mut(&rip).unwrap();
                        let updated = if let Ok(x) = bp.process(Some(child)) {
                            x
                        } else {
                            rip == end
                        };
                        if updated {
                            for mut t in traces.iter_mut()
                                               .filter(|ref x| x.address == rip) {
                                (*t).hits += 1;
                            }
                        }
                    } else {
                        continue_exec(child)?;
                    }
                }
            },
            Ok(WaitStatus::Stopped(child, signal::SIGSTOP)) => {
                continue_exec(child)?;
            },
            Ok(WaitStatus::Stopped(child, sig)) => {
                println!("Unexpected signal {:?}", sig);
                continue_exec(child)?;
            },
            Ok(WaitStatus::PtraceEvent(child, signal::SIGTRAP, 3)) => {
                if let Ok(_) = get_event_data(child) {
                    continue_exec(child)?;
                }
            },
            Ok(WaitStatus::Signaled(_, signal::SIGTRAP, true)) => break,
            Ok(_) => {
                println!("Unexpected stop");
                break;
            },
            Err(e) => {
                return Err(Error::new(ErrorKind::Other, e))
            },
        }
    }
    Ok(res)
}

/// Launches the test executable
fn execute_test(test: &Path, ignored: bool, backtrace_on: bool) {
    let exec_path = CString::new(test.to_str().unwrap()).unwrap();
    match personality::disable_aslr() {
        Ok(_) => {},
        Err(e) => println!("ASLR disable failed: {}", e),
    }
    request_trace().ok()
                   .expect("Failed to trace");

    let mut envars: Vec<CString> = vec![CString::new("RUST_TEST_THREADS=1").unwrap()];
    for (key, value) in env::vars() {
        let mut temp = String::new();
        temp.push_str(key.as_str());
        temp.push('=');
        temp.push_str(value.as_str());
        envars.push(CString::new(temp).unwrap());
    }
    if backtrace_on {
        envars.push(CString::new("RUST_BACKTRACE=1").unwrap());
    }
    let argv = if ignored {
        vec![exec_path.clone(), CString::new("--ignored").unwrap()]
    } else {
        vec![exec_path.clone()]
    };
    execve(&exec_path, &argv, envars.as_slice())
        .unwrap();
}

#[cfg(test)]
mod tests {
    use std::path::PathBuf;
    use ::*;

    #[test]
    fn result_merge_test() {
        let mut master:Vec<TracerData> = vec![];

        master.push(TracerData {
            path: PathBuf::from("testing/test.rs"),
            line: 2,
            address: 0,
            trace_type: LineType::Unknown,
            hits: 1
        });
        master.push(TracerData {
            path: PathBuf::from("testing/test.rs"),
            line: 3,
            address: 1,
            trace_type: LineType::Unknown,
            hits: 1
        });
        master.push(TracerData {
            path: PathBuf::from("testing/not.rs"),
            line: 2,
            address: 0,
            trace_type: LineType::Unknown,
            hits: 7
        });

        let other:Vec<TracerData> = vec![
            TracerData {
                path:PathBuf::from("testing/test.rs"),
                line: 2,
                address: 0,
                trace_type: LineType::Unknown,
                hits: 2
            }];

        merge_test_results(&mut master, &other);
        let expected = vec![3, 1, 7];
        for (act, exp) in master.iter().zip(expected) {
            assert_eq!(act.hits, exp);
        }
    }

}
<|endoftext|>


<commit_before>
extern crate libc;
extern crate errno;
#[macro_use]
extern crate bitflags;

mod device;
mod frontend;

pub use device::ReadWriteMode;
pub use device::BlockMode;
pub use frontend::Frontend;
pub use frontend::properties::*;

#[test]
fn it_works() {
}
<commit_msg>Re-export everything in module frontend.<commit_after>
extern crate libc;
extern crate errno;
#[macro_use]
extern crate bitflags;

mod device;
mod frontend;

pub use device::ReadWriteMode;
pub use device::BlockMode;
pub use frontend::*;
pub use frontend::properties::*;

#[test]
fn it_works() {
}
<|endoftext|>


<commit_before>
#![allow(dead_code)]

pub extern crate crypto;

use crypto::digest::Digest;

pub trait Hashable {
    fn to_bytes(&self) -> Vec<u8>;
}

impl Hashable for String {
    fn to_bytes(&self) -> Vec<u8> {
        self.clone().into_bytes()
    }
}

impl Hashable for u8 {
    fn to_bytes(&self) -> Vec<u8> {
        vec![*self]
    }
}

pub trait MerkleDigest {
    fn hash_bytes(&mut self, bytes: &Vec<u8>) -> Vec<u8>;
    fn combine_hashes(&mut self, left: &Vec<u8>, right: &Vec<u8>) -> Vec<u8>;
}

impl <D> MerkleDigest for D where D: Digest {

    fn hash_bytes(&mut self, bytes: &Vec<u8>) -> Vec<u8> {
        let mut hash = vec![0; self.output_bytes()];

        self.reset();
        self.input(bytes);
        self.result(&mut hash);
        self.reset();

        hash
    }

    fn combine_hashes(&mut self, left: &Vec<u8>, right: &Vec<u8>) -> Vec<u8> {
        let mut hash = vec![0; self.output_bytes()];

        self.reset();
        self.input(left);
        self.input(right);
        self.result(&mut hash);
        self.reset();

        hash
    }

}

enum Tree<T> {
    Leaf {
        hash: Vec<u8>,
        value: T
    },

    Node {
        hash: Vec<u8>,
        left: Box<Tree<T>>,
        right: Box<Tree<T>>
    }
}

impl <T> Tree<T> where T: Hashable {

    fn new(hash: Vec<u8>, value: T) -> Self {
        Tree::Leaf {
            hash: hash,
            value: value
        }
    }

    fn get_hash(&self) -> &Vec<u8> {
        match *self {
            Tree::Leaf { ref hash, value: _ }          => hash,
            Tree::Node { ref hash, left: _, right: _ } => hash
        }
    }
}

fn make_leaf<D, T>(digest: &mut D, value: T) -> Tree<T> where D: Digest, T: Hashable {
    let hash = digest.hash_bytes(&value.to_bytes());
    Tree::new(hash, value)
}

pub struct MerkleTree<D, T> where D: Digest, T: Hashable {
    digest: D,
    tree: Tree<T>,
    height: usize,
    count: usize
}

impl <D, T> MerkleTree<D, T> where D: Digest, T: Hashable {

    pub fn from_vec(mut digest: D, values: Vec<T>) -> Self {
        if values.is_empty() {
            panic!("Cannot build a Merkle tree from an empty vector.");
        }

        let count  = values.len();
        let height = (count as f32 + 1.0).log2().ceil() as usize;

        let mut cur = Vec::with_capacity(count);

        for v in values.into_iter().rev() {
            let leaf = make_leaf(&mut digest, v);
            cur.push(leaf);
        }

        for i in 0 .. height {
            let mut next = Vec::with_capacity(height / 2 << i);

            while cur.len() > 0 {
                if cur.len() == 1 {
                    next.push(cur.pop().unwrap());
                }
                else {
                    let right = cur.pop().unwrap();
                    let left  = cur.pop().unwrap();

                    let combined_hash = digest.combine_hashes(
                        left.get_hash(),
                        right.get_hash()
                    );

                    let node = Tree::Node {
                       hash: combined_hash,
                       left: Box::new(left),
                       right: Box::new(right)
                    };

                    next.push(node);
                }
            }

            cur = next;
        }

        assert!(cur.len() == 1);

        let tree = cur.remove(0);

        MerkleTree {
            digest: digest,
            tree: tree,
            height: height,
            count: count
        }
    }

    fn root_hash(&self) -> &Vec<u8> {
        self.tree.get_hash()
    }

}

#[cfg(test)]
mod tests;

<commit_msg>Fix tree construction.<commit_after>
#![allow(dead_code)]

pub extern crate crypto;

use crypto::digest::Digest;

pub trait Hashable {
    fn to_bytes(&self) -> Vec<u8>;
}

impl Hashable for String {
    fn to_bytes(&self) -> Vec<u8> {
        self.clone().into_bytes()
    }
}

impl Hashable for u8 {
    fn to_bytes(&self) -> Vec<u8> {
        vec![*self]
    }
}

pub trait MerkleDigest {
    fn hash_bytes(&mut self, bytes: &Vec<u8>) -> Vec<u8>;
    fn combine_hashes(&mut self, left: &Vec<u8>, right: &Vec<u8>) -> Vec<u8>;
}

impl <D> MerkleDigest for D where D: Digest {

    fn hash_bytes(&mut self, bytes: &Vec<u8>) -> Vec<u8> {
        let mut hash = vec![0; self.output_bytes()];

        self.reset();
        self.input(bytes);
        self.result(&mut hash);
        self.reset();

        hash
    }

    fn combine_hashes(&mut self, left: &Vec<u8>, right: &Vec<u8>) -> Vec<u8> {
        let mut hash = vec![0; self.output_bytes()];

        self.reset();
        self.input(left);
        self.input(right);
        self.result(&mut hash);
        self.reset();

        hash
    }

}

enum Tree<T> {
    Leaf {
        hash: Vec<u8>,
        value: T
    },

    Node {
        hash: Vec<u8>,
        left: Box<Tree<T>>,
        right: Box<Tree<T>>
    }
}

impl <T> Tree<T> where T: Hashable {

    fn new(hash: Vec<u8>, value: T) -> Self {
        Tree::Leaf {
            hash: hash,
            value: value
        }
    }

    fn get_hash(&self) -> &Vec<u8> {
        match *self {
            Tree::Leaf { ref hash, value: _ }          => hash,
            Tree::Node { ref hash, left: _, right: _ } => hash
        }
    }
}

fn make_leaf<D, T>(digest: &mut D, value: T) -> Tree<T> where D: Digest, T: Hashable {
    let hash = digest.hash_bytes(&value.to_bytes());
    Tree::new(hash, value)
}

pub struct MerkleTree<D, T> where D: Digest, T: Hashable {
    digest: D,
    tree: Tree<T>,
    height: usize,
    count: usize
}

impl <D, T> MerkleTree<D, T> where D: Digest, T: Hashable {

    pub fn from_vec(mut digest: D, values: Vec<T>) -> Self {
        if values.is_empty() {
            panic!("Cannot build a Merkle tree from an empty vector.");
        }

        let count  = values.len();
        let height = (count as f32 + 1.0).log2().ceil() as usize;

        let mut cur = Vec::with_capacity(count);

        for v in values.into_iter().rev() {
            let leaf = make_leaf(&mut digest, v);
            cur.push(leaf);
        }

        cur.reverse();

        for i in 0 .. height {
            let mut next = Vec::with_capacity(height / 2 << i);

            while cur.len() > 0 {
                if cur.len() == 1 {
                    next.push(cur.remove(0));
                }
                else {
                    let left  = cur.remove(0);
                    let right = cur.remove(0);

                    let combined_hash = digest.combine_hashes(
                        left.get_hash(),
                        right.get_hash()
                    );

                    let node = Tree::Node {
                       hash: combined_hash,
                       left: Box::new(left),
                       right: Box::new(right)
                    };

                    next.push(node);
                }
            }

            cur = next;
        }

        assert!(cur.len() == 1);

        let tree = cur.remove(0);

        MerkleTree {
            digest: digest,
            tree: tree,
            height: height,
            count: count
        }
    }

    fn root_hash(&self) -> &Vec<u8> {
        self.tree.get_hash()
    }

}

#[cfg(test)]
mod tests;

<|endoftext|>


<commit_before>use std::net::{SocketAddr, TcpListener, ToSocketAddrs};
use std::ops::Range;

/// Scan a port and return true if it's open.
///
/// # Example
/// ```no_run
/// use port_scanner::scan_port;
/// println!("Port 8000 open? {}", scan_port(8000));
/// ```
pub fn scan_port(port: u16) -> bool {
    match TcpListener::bind(("0.0.0.0", port)) {
        Ok(_) => true,
        Err(_) => false,
    }
}

/// Scan port of an address and return true if it's open.
///
/// # Example
/// ```no_run
/// use port_scanner::scan_port_addr;
/// println!("IP 192.168.1.1 has port 8000 open? {}", scan_port_addr("192.168.1.1:8000"));
/// ```
pub fn scan_port_addr<A: ToSocketAddrs>(addr: A) -> bool {
    match TcpListener::bind(addr) {
        Ok(_) => true,
        Err(_) => false,
    }
}

/// Scan specified ports and return a list of all open ports.
///
/// # Example
/// ```no_run
/// use port_scanner::scan_ports;
/// for open_port in scan_ports(vec![8000, 9000, 8888]) {
///     println!("Port {} is open", open_port);
/// }
/// ```
pub fn scan_ports(ports: Vec<u16>) -> Vec<u16> {
    let mut open_ports = Vec::new();
    for port in ports {
        if scan_port(port) {
            open_ports.push(port);
        }
    }
    open_ports
}

/// Scan specified ports of addresses and return a list of all addresses with open ports.
///
/// # Example
/// ```no_run
/// use port_scanner::scan_ports_addrs;
/// for open_addr in scan_ports_addrs(vec!["192.168.1.1:8000", "192.168.1.2:8000"]) {
///     println!("IP {} has port {} open.", open_addr.ip(), open_addr.port());
/// }
/// ```
pub fn scan_ports_addrs<A: ToSocketAddrs>(addrs: Vec<A>) -> Vec<SocketAddr> {
    let mut open_addrs = Vec::new();
    for addr in addrs {
        if scan_port_addr(&addr) {
            let addr = addr.to_socket_addrs().unwrap().next().unwrap();
            open_addrs.push(addr);
        }
    }
    open_addrs
}

/// Scan a port range and return a list of all open ports.
///
/// # Example
/// ```no_run
/// use port_scanner::scan_ports_range;
/// for open_port in scan_ports_range(8000..9000) {
///     println!("Port {} is open", open_port);
/// }
/// ```
pub fn scan_ports_range(port_range: Range<u16>) -> Vec<u16> {
    let mut open_ports = Vec::new();
    for port in port_range {
        if scan_port(port) {
            open_ports.push(port);
        }
    }
    open_ports
}

/// Request to the os the next open port.
///
/// # Example
/// ```no_run
/// use port_scanner::request_open_port;
/// println!("Port {}", request_open_port().unwrap_or(0));
/// ```
pub fn request_open_port() -> Option<u16> {
    match TcpListener::bind("0.0.0.0:0") {
        Ok(a) => {
            match a.local_addr() {
                Ok(a) => Some(a.port()),
                Err(_) => None,
            }
        }
        Err(_) => None,
    }
}
<commit_msg>Fix port scanner<commit_after>use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs};
use std::ops::Range;

/// Scan a port and return true if it's open.
///
/// # Example
/// ```no_run
/// use port_scanner::scan_port;
/// println!("Port 8000 open? {}", scan_port(8000));
/// ```
pub fn scan_port(port: u16) -> bool {
    match TcpStream::connect(("0.0.0.0", port)) {
        Ok(_) => true,
        Err(_) => false,
    }
}

/// Scan port of an address and return true if it's open.
///
/// # Example
/// ```no_run
/// use port_scanner::scan_port_addr;
/// println!("IP 192.168.1.1 has port 8000 open? {}", scan_port_addr("192.168.1.1:8000"));
/// ```
pub fn scan_port_addr<A: ToSocketAddrs>(addr: A) -> bool {
    match TcpStream::connect(addr) {
        Ok(_) => true,
        Err(_) => false,
    }
}

/// Scan specified ports and return a list of all open ports.
///
/// # Example
/// ```no_run
/// use port_scanner::scan_ports;
/// for open_port in scan_ports(vec![8000, 9000, 8888]) {
///     println!("Port {} is open", open_port);
/// }
/// ```
pub fn scan_ports(ports: Vec<u16>) -> Vec<u16> {
    let mut open_ports = Vec::new();
    for port in ports {
        if scan_port(port) {
            open_ports.push(port);
        }
    }
    open_ports
}

/// Scan specified ports of addresses and return a list of all addresses with open ports.
///
/// # Example
/// ```no_run
/// use port_scanner::scan_ports_addrs;
/// for open_addr in scan_ports_addrs(vec!["192.168.1.1:8000", "192.168.1.2:8000"]) {
///     println!("IP {} has port {} open.", open_addr.ip(), open_addr.port());
/// }
/// ```
pub fn scan_ports_addrs<A: ToSocketAddrs>(addrs: Vec<A>) -> Vec<SocketAddr> {
    let mut open_addrs = Vec::new();
    for addr in addrs {
        if scan_port_addr(&addr) {
            let addr = addr.to_socket_addrs().unwrap().next().unwrap();
            open_addrs.push(addr);
        }
    }
    open_addrs
}

/// Scan a port range and return a list of all open ports.
///
/// # Example
/// ```no_run
/// use port_scanner::scan_ports_range;
/// for open_port in scan_ports_range(8000..9000) {
///     println!("Port {} is open", open_port);
/// }
/// ```
pub fn scan_ports_range(port_range: Range<u16>) -> Vec<u16> {
    let mut open_ports = Vec::new();
    for port in port_range {
        if scan_port(port) {
            open_ports.push(port);
        }
    }
    open_ports
}

/// Request to the os the next open port.
///
/// # Example
/// ```no_run
/// use port_scanner::request_open_port;
/// println!("Port {}", request_open_port().unwrap_or(0));
/// ```
pub fn request_open_port() -> Option<u16> {
    match TcpListener::bind("0.0.0.0:0") {
        Ok(a) => {
            match a.local_addr() {
                Ok(a) => Some(a.port()),
                Err(_) => None,
            }
        }
        Err(_) => None,
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate serde_json;

use hyper::{Client, Error as HttpError};
use serde_json::StreamDeserializer;
use std::io::Read;
use std::sync::mpsc::{channel, Receiver};
use std::thread;

include!(concat!(env!("OUT_DIR"), "/main.rs"));

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    Transport(HttpError),
}

impl From<HttpError> for Error {
    fn from(error: HttpError) -> Error {
        Error::Transport(error)
    }
}

pub struct Cluster {
    host: String,
}

pub trait Events {
    fn events(&mut self) -> Result<Receiver<Event>>;

    fn generator<Iter>(&self, iter: Iter) -> Result<Receiver<Event>>
        where Iter: Iterator<Item = std::io::Result<u8>>,
              Iter: Send + 'static
    {
        let (tx, rx) = channel();
        let src: StreamDeserializer<Event, _> = StreamDeserializer::new(iter);
        thread::spawn(move || {
            for e in src {
                match e {
                    Ok(event) => match tx.send(event) {
                        Err(e) => {
                            println!("{:#?}", e);
                            break
                        },_ => ()
                    },
                    Err(e) => {
                        println!("{:#?}", e);
                        break
                    }
                }
            }
        });
        Ok(rx)
    }
}

impl Cluster {
    pub fn new() -> Cluster {
        Cluster { host: "http://localhost:8001".to_owned() }
    }
}

impl Events for Cluster {
    fn events(&mut self) -> Result<Receiver<Event>> {
        let res = try!(Client::new()
            .get(&format!("{}/api/v1/events?watch=true", self.host))
            .send());
        self.generator(res.bytes())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::mpsc::Receiver;
    use std::io::Read;
    #[test]
    fn events_generator() {
        impl Events for &'static str {
            fn events(&mut self) -> Result<Receiver<Event>> {
                self.generator(self.bytes().into_iter().map(|b| Ok(b)))
            }
        }
        let events = r#"{
            "object":{
                "apiVersion": "1",
                "count": 1,
                "firstTimestamp": "...",
                "lastTimestamp": "...",
                "kind":"POD",
                "message":"test",
                "involvedObject": {
                    "apiVersion": "1",
                    "kind": "POD",
                    "name": "test_name",
                    "namespace": "test_namespace"
                }
            },
            "type":"ADDED"
        }"#.events();
        assert!(
            events.unwrap()
                .into_iter()
                .map(|e| e.object.involved_object.namespace)
                .nth(0)
                    == Some("test_namespace".to_owned())
        )
    }
}
<commit_msg>better use of types<commit_after>extern crate hyper;
extern crate serde_json;

use hyper::{Client, Error as HttpError, Url};
use serde_json::StreamDeserializer;
use std::io::Read;
use std::sync::mpsc::{channel, Receiver};
use std::thread;

include!(concat!(env!("OUT_DIR"), "/main.rs"));

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    Transport(HttpError),
}

impl From<HttpError> for Error {
    fn from(error: HttpError) -> Error {
        Error::Transport(error)
    }
}

pub struct Cluster {
    host: Url,
}

pub trait Events {
    fn events(&mut self) -> Result<Receiver<Event>>;

    fn generator<Iter>(&self, iter: Iter) -> Result<Receiver<Event>>
        where Iter: Iterator<Item = std::io::Result<u8>>,
              Iter: Send + 'static
    {
        let (tx, rx) = channel();
        let src: StreamDeserializer<Event, _> = StreamDeserializer::new(iter);
        thread::spawn(move || {
            for e in src {
                match e {
                    Ok(event) => match tx.send(event) {
                        Err(e) => {
                            println!("{:#?}", e);
                            break
                        },_ => ()
                    },
                    Err(e) => {
                        println!("{:#?}", e);
                        break
                    }
                }
            }
        });
        Ok(rx)
    }
}

impl Cluster {
    pub fn new() -> Cluster {
        Cluster { host: Url::parse("http://localhost:8001").unwrap() }
    }
}

impl Events for Cluster {
    fn events(&mut self) -> Result<Receiver<Event>> {
        let res = try!(Client::new()
            .get(self.host.join("/api/v1/events?watch=true").unwrap())
            .send());
        self.generator(res.bytes())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::mpsc::Receiver;
    use std::io::Read;
    #[test]
    fn events_generator() {
        impl Events for &'static str {
            fn events(&mut self) -> Result<Receiver<Event>> {
                self.generator(self.bytes().into_iter().map(|b| Ok(b)))
            }
        }
        let events = r#"{
            "object":{
                "apiVersion": "1",
                "count": 1,
                "firstTimestamp": "...",
                "lastTimestamp": "...",
                "kind":"POD",
                "message":"test",
                "involvedObject": {
                    "apiVersion": "1",
                    "kind": "POD",
                    "name": "test_name",
                    "namespace": "test_namespace"
                }
            },
            "type":"ADDED"
        }"#.events();
        assert!(
            events.unwrap()
                .into_iter()
                .map(|e| e.object.involved_object.namespace)
                .nth(0)
                    == Some("test_namespace".to_owned())
        )
    }
}
<|endoftext|>


<commit_before>extern crate regex;
#[macro_use]
extern crate lazy_static;

pub mod lexer;
pub mod parser;

#[cfg(test)]
mod tests {
    use parser;
    #[test]
    fn addition() {
        let input = String::from("1 + 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1+2) as f64);
    }
    #[test]
    fn subtraction() {
        let input = String::from("18 - 4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (18-4) as f64);
    }
    #[test]
    fn multiplication() {
        let input = String::from("3 * 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (3*6) as f64);
    }
    #[test]
    fn divide() {
        let input = String::from("15 / 3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (15.0/3.0) as f64);
    }
    #[test]
    fn end() {
        let input = String::from("");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn ignore_whitespace() {
        let input = String::from("   12        -  8   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (12-8) as f64);
        let input = String::from("142        -9   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (142-9) as f64);
        let input = String::from("72+  15");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (72+15) as f64);
        let input = String::from(" 12*  4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (12*4) as f64);
        let input = String::from(" 50/10");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (50.0/10.0) as f64);
    }
    #[test]
    fn long_add_expressions() {
        let input = String::from("2 -4 +6 -1 -1- 0 +8");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2-4+6-1-1-0+8) as f64);
        let input = String::from("1 -1   + 2   - 2   +  4 - 4 +    6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1-1+2-2+4-4+6) as f64);
    }
    #[test]
    fn long_mult_expressions() {
        let input = String::from("2 *4 *6 *1 *1* 0 *8");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2*4*6*1*1*0*8) as f64);
        let input = String::from("1 *1   * 2   * 2   *  4 * 4 *    6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1*1*2*2*4*4*6) as f64);
    }
    #[test]
    fn long_mixed() {
        let input = String::from(" 2*3 - 4*5 + 6/3 ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0-4.0*5.0+6.0/3.0) as f64);
        let input = String::from("2*3*4/8 -   5/2*4 +  6 + 0/3   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0*4.0/8.0-5.0/2.0*4.0+6.0+0.0/3.0) as f64);
    }
    #[test]
    fn floating() {
        let input = String::from("10/4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (10.0/4.0) as f64);
        let input = String::from("5/3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (5.0/3.0) as f64);
        let input = String::from("3 + 8/5 -1 -2*5");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (3.0+8.0/5.0-1.0-2.0*5.0) as f64);
    }
    #[test]
    fn bad_tokens() {
        let input = String::from("  6 + c");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from("  7 & 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from("  %");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn syntax_error() {
        let input = String::from(" 5 + + 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from(" 5 * / 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn divide_zero() {
        let input = String::from("5/0");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap().is_infinite());
        let input = String::from(" 2 - 1 + 14/0 + 7");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap().is_infinite());
    }
    #[test]
    fn unused_parens() {
        let input = String::from(" (2) ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2) as f64);
    }
    #[test]
    fn enclosing_parens() {
        let input = String::from("(5 + 2*3 - 1 + 7 * 8)");
        let mut my_parser = parser::Parser::new(input);
        let r = my_parser.parse().unwrap();
        let result = (5.0+2.0*3.0-1.0+7.0*8.0) as f64;
        assert!(r == result, "{}\t{}", r, result);
        let input = String::from("(67 + 2 * 3 - 67 + 2/1 - 7)");
        let mut my_parser = parser::Parser::new(input);
        let r = my_parser.parse().unwrap();
        let result = (67.0+2.0*3.0-67.0+2.0/1.0-7.0) as f64;
        assert!(r == result, "{}\t{}", r, result);
    }
    #[test]
    fn sub_expressions() {
        let input = String::from("(2) + (17*2-30) * (5)+2 - (8/2)*4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((2.0)+(17.0*2.0-30.0)*(5.0)+2.0-(8.0/2.0)*4.0) as f64);
        let input = String::from("(5*7/5) + (23) - 5 * (98-4)/(6*7-42)");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((5.0*7.0/5.0)+(23.0)-5.0*(98.0-4.0)/(6.0*7.0-42.0)) as f64);
    }
    #[test]
    fn nested_parens() {
        let input = String::from("(((((5)))))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((((((5)))))) as f64);
        let input = String::from("(( ((2)) + 4))*((5))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (((((2.0))+4.0))*((5.0))) as f64);
    }
    #[test]
    fn unbalanced_parens() {
        let input = String::from("2 + (5 * 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0+(5.0*2.0)) as f64);
        let input = String::from("(((((4))))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (4.0) as f64);
        let input = String::from("((2)) * ((3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0) as f64);
        let input = String::from("((9)) * ((1)");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (9.0*1.0) as f64);
    }
}
<commit_msg>Added some exponent tests<commit_after>extern crate regex;
#[macro_use]
extern crate lazy_static;

pub mod lexer;
pub mod parser;

#[cfg(test)]
mod tests {
    use parser;
    use std::f64;
    #[test]
    fn addition() {
        let input = String::from("1 + 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1+2) as f64);
    }
    #[test]
    fn subtraction() {
        let input = String::from("18 - 4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (18-4) as f64);
    }
    #[test]
    fn multiplication() {
        let input = String::from("3 * 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (3*6) as f64);
    }
    #[test]
    fn divide() {
        let input = String::from("15 / 3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (15.0/3.0) as f64);
    }
    #[test]
    fn power() {
        let input = String::from("4 ^ 7");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (f64::powf(4.0, 7.0)) as f64);
        let input = String::from("4 ^ 7 ^ 8");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (f64::powf(f64::powf(4.0, 7.0), 8.0) as f64));
    }
    #[test]
    fn end() {
        let input = String::from("");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn ignore_whitespace() {
        let input = String::from("   12        -  8   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (12-8) as f64);
        let input = String::from("142        -9   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (142-9) as f64);
        let input = String::from("72+  15");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (72+15) as f64);
        let input = String::from(" 12*  4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (12*4) as f64);
        let input = String::from(" 50/10");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (50.0/10.0) as f64);
    }
    #[test]
    fn long_add_expressions() {
        let input = String::from("2 -4 +6 -1 -1- 0 +8");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2-4+6-1-1-0+8) as f64);
        let input = String::from("1 -1   + 2   - 2   +  4 - 4 +    6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1-1+2-2+4-4+6) as f64);
    }
    #[test]
    fn long_mult_expressions() {
        let input = String::from("2 *4 *6 *1 *1* 0 *8");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2*4*6*1*1*0*8) as f64);
        let input = String::from("1 *1   * 2   * 2   *  4 * 4 *    6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1*1*2*2*4*4*6) as f64);
    }
    #[test]
    fn long_mixed() {
        let input = String::from(" 2*3 - 4*5 + 6/3 ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0-4.0*5.0+6.0/3.0) as f64);
        let input = String::from("2*3*4/8 -   5/2*4 +  6 + 0/3   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0*4.0/8.0-5.0/2.0*4.0+6.0+0.0/3.0) as f64);
    }
    #[test]
    fn floating() {
        let input = String::from("10/4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (10.0/4.0) as f64);
        let input = String::from("5/3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (5.0/3.0) as f64);
        let input = String::from("3 + 8/5 -1 -2*5");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (3.0+8.0/5.0-1.0-2.0*5.0) as f64);
    }
    #[test]
    fn bad_tokens() {
        let input = String::from("  6 + c");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from("  7 & 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from("  %");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn syntax_error() {
        let input = String::from(" 5 + + 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from(" 5 * / 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn divide_zero() {
        let input = String::from("5/0");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap().is_infinite());
        let input = String::from(" 2 - 1 + 14/0 + 7");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap().is_infinite());
    }
    #[test]
    fn unused_parens() {
        let input = String::from(" (2) ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2) as f64);
    }
    #[test]
    fn enclosing_parens() {
        let input = String::from("(5 + 2*3 - 1 + 7 * 8)");
        let mut my_parser = parser::Parser::new(input);
        let r = my_parser.parse().unwrap();
        let result = (5.0+2.0*3.0-1.0+7.0*8.0) as f64;
        assert!(r == result, "{}\t{}", r, result);
        let input = String::from("(67 + 2 * 3 - 67 + 2/1 - 7)");
        let mut my_parser = parser::Parser::new(input);
        let r = my_parser.parse().unwrap();
        let result = (67.0+2.0*3.0-67.0+2.0/1.0-7.0) as f64;
        assert!(r == result, "{}\t{}", r, result);
    }
    #[test]
    fn sub_expressions() {
        let input = String::from("(2) + (17*2-30) * (5)+2 - (8/2)*4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((2.0)+(17.0*2.0-30.0)*(5.0)+2.0-(8.0/2.0)*4.0) as f64);
        let input = String::from("(5*7/5) + (23) - 5 * (98-4)/(6*7-42)");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((5.0*7.0/5.0)+(23.0)-5.0*(98.0-4.0)/(6.0*7.0-42.0)) as f64);
    }
    #[test]
    fn nested_parens() {
        let input = String::from("(((((5)))))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((((((5)))))) as f64);
        let input = String::from("(( ((2)) + 4))*((5))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (((((2.0))+4.0))*((5.0))) as f64);
    }
    #[test]
    fn unbalanced_parens() {
        let input = String::from("2 + (5 * 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0+(5.0*2.0)) as f64);
        let input = String::from("(((((4))))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (4.0) as f64);
        let input = String::from("((2)) * ((3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0) as f64);
        let input = String::from("((9)) * ((1)");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (9.0*1.0) as f64);
    }
}
<|endoftext|>


<commit_before>#![crate_name="postgres_macros"]
#![crate_type="dylib"]
#![feature(plugin_registrar)]

extern crate libc;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use std::c_str::CString;
use std::mem;
use syntax::ast::{TokenTree, ExprLit, LitStr, Expr, Ident};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::token;
use syntax::parse::token::{InternedString, Comma, Eof};
use syntax::parse;
use syntax::parse::parser::Parser;
use syntax::ptr::P;

mod ffi {
    use libc::{c_char, c_int};

    #[repr(C)]
    pub struct ParseResult {
        pub success: c_int,
        pub error_message: *const c_char,
        pub index: c_int,
        pub num_params: c_int,
    }

    extern {
        pub fn init_parser();
        pub fn parse_query(query: *const c_char, result: *mut ParseResult);
    }
}

struct ParseInfo {
    num_params: uint,
}

struct ParseError {
    message: CString,
    index: uint,
}

#[plugin_registrar]
#[doc(hidden)]
pub fn registrar(reg: &mut Registry) {
    reg.register_macro("sql", expand_sql);
    reg.register_macro("execute", expand_execute);
    unsafe { ffi::init_parser() }
}

fn expand_sql(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
              -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp)
    };

    match parse(query.get()) {
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    MacExpr::new(query_expr)
}

fn expand_execute(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                  -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let conn = parser.parse_expr();

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp),
    };

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let args = match parse_args(cx, &mut parser) {
        Some(args) => args,
        None => return DummyResult::expr(sp),
    };

    match parse(query.get()) {
        Ok(ref info) if info.num_params != args.len() =>
            cx.span_err(sp, format!("Expected {} query parameters but got {}",
                                    info.num_params, args.len()).as_slice()),
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    let ident = Ident::new(token::intern("execute"));
    let args = cx.expr_vec(sp, args);
    MacExpr::new(cx.expr_method_call(sp, conn, ident, vec![query_expr, args]))
}

fn parse_error(cx: &mut ExtCtxt, sp: Span, err: ParseError) {
    cx.span_err(sp, format!("Invalid syntax at position {}: {}",
                            err.index,
                            err.message.as_str().unwrap()).as_slice());
}

fn parse_str_lit(cx: &mut ExtCtxt, e: &Expr) -> Option<InternedString> {
    match e.node {
        ExprLit(ref lit) => {
            match lit.node {
                LitStr(ref s, _) => Some(s.clone()),
                _ => {
                    cx.span_err(e.span, "expected string literal");
                    None
                }
            }
        }
        _ => {
            cx.span_err(e.span, "expected string literal");
            None
        }
    }
}

fn parse_args(cx: &mut ExtCtxt, parser: &mut Parser) -> Option<Vec<P<Expr>>> {
    let mut args = Vec::new();

    while parser.token != Eof {
        args.push(parser.parse_expr());

        if !parser.eat(&Comma) && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    Some(args)
}

fn parse(query: &str) -> Result<ParseInfo, ParseError> {
    unsafe {
        let mut result = mem::uninitialized();
        query.with_c_str(|query| ffi::parse_query(query, &mut result));
        if result.success != 0 {
            Ok(ParseInfo {
                num_params: result.num_params as uint,
            })
        } else {
            Err(ParseError {
                message: CString::new(result.error_message, true),
                index: result.index as uint,
            })
        }
    }
}
<commit_msg>Update for latest rustc<commit_after>#![crate_name="postgres_macros"]
#![crate_type="dylib"]
#![feature(plugin_registrar)]

#![allow(unstable)]

extern crate libc;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use std::ffi::CString;
use std::mem;
use std::str;
use syntax::ast::{TokenTree, ExprLit, LitStr, Expr, Ident};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::token;
use syntax::parse::token::{InternedString, Comma, Eof};
use syntax::parse;
use syntax::parse::parser::Parser;
use syntax::ptr::P;

mod ffi {
    use libc::{c_char, c_int};

    #[repr(C)]
    pub struct ParseResult {
        pub success: c_int,
        pub error_message: *const c_char,
        pub index: c_int,
        pub num_params: c_int,
    }

    extern {
        pub fn init_parser();
        pub fn parse_query(query: *const c_char, result: *mut ParseResult);
    }
}

struct ParseInfo {
    num_params: usize,
}

struct ParseError {
    message: String,
    index: usize,
}

#[plugin_registrar]
#[doc(hidden)]
pub fn registrar(reg: &mut Registry) {
    reg.register_macro("sql", expand_sql);
    reg.register_macro("execute", expand_execute);
    unsafe { ffi::init_parser() }
}

fn expand_sql(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
              -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp)
    };

    match parse(query.get()) {
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    MacExpr::new(query_expr)
}

fn expand_execute(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                  -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let conn = parser.parse_expr();

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp),
    };

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let args = match parse_args(cx, &mut parser) {
        Some(args) => args,
        None => return DummyResult::expr(sp),
    };

    match parse(query.get()) {
        Ok(ref info) if info.num_params != args.len() =>
            cx.span_err(sp, format!("Expected {} query parameters but got {}",
                                    info.num_params, args.len()).as_slice()),
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    let ident = Ident::new(token::intern("execute"));
    let args = cx.expr_vec(sp, args);
    MacExpr::new(cx.expr_method_call(sp, conn, ident, vec![query_expr, args]))
}

fn parse_error(cx: &mut ExtCtxt, sp: Span, err: ParseError) {
    cx.span_err(sp, format!("Invalid syntax at position {}: {}",
                            err.index,
                            err.message).as_slice());
}

fn parse_str_lit(cx: &mut ExtCtxt, e: &Expr) -> Option<InternedString> {
    match e.node {
        ExprLit(ref lit) => {
            match lit.node {
                LitStr(ref s, _) => Some(s.clone()),
                _ => {
                    cx.span_err(e.span, "expected string literal");
                    None
                }
            }
        }
        _ => {
            cx.span_err(e.span, "expected string literal");
            None
        }
    }
}

fn parse_args(cx: &mut ExtCtxt, parser: &mut Parser) -> Option<Vec<P<Expr>>> {
    let mut args = Vec::new();

    while parser.token != Eof {
        args.push(parser.parse_expr());

        if !parser.eat(&Comma) && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    Some(args)
}

fn parse(query: &str) -> Result<ParseInfo, ParseError> {
    unsafe {
        let mut result = mem::uninitialized();
        let query = CString::from_slice(query.as_bytes());
        ffi::parse_query(query.as_ptr(), &mut result);
        if result.success != 0 {
            Ok(ParseInfo {
                num_params: result.num_params as usize,
            })
        } else {
            let bytes = std::ffi::c_str_to_bytes(&result.error_message);
            Err(ParseError {
                message: str::from_utf8(bytes).unwrap().to_string(),
                index: result.index as usize,
            })
        }
    }
}
<|endoftext|>