<commit_before>//! Client for connecting and communicating with a server listener which speaks SrvProtocol.
//!
//! Currently all functions will block and wait for a response from the remote. This is likely to
//! change to a futures based implementation as our needs increase.
//!
//! # RPC Call Example
//!
//! ```ignore
//! let conn = SrvClient::connect(&listen_addr, secret_key).wait()?;
//! let msg = protocols::ctl::ServiceGetDefaultCfg::new();
//! conn.call(msg).for_each(|reply| {
//!     match reply.message_id() {
//!         "ServiceCfg" => {
//!             let m = reply.parse::<protocols::types::ServiceCfg>().unwrap();
//!             println!("{}", m.get_default());
//!         }
//!         "NetErr" => {
//!             let m = reply.parse::<protocols::net::NetErr>().unwrap();
//!             println!("{}", m);
//!         }
//!         _ => (),
//!     }
//!     Ok(())
//! })
//! ```

#[macro_use]
extern crate futures;
use habitat_sup_protocol as protocol;
#[macro_use]
extern crate log;
use habitat_common as common;

use std::{error,
          fmt,
          io,
          path::PathBuf};

use crate::protocol::{codec::*,
                      net::NetErr};
use futures::{prelude::*,
              sink};
use tokio::net::TcpStream;
use tokio_codec::Framed;

use crate::common::types::ListenCtlAddr;

pub type SrvSend = sink::Send<SrvStream>;

/// Error types returned by a [`SrvClient`].
#[derive(Debug)]
pub enum SrvClientError {
    /// The remote server unexpectedly closed the connection.
    ConnectionClosed,
    /// Unable to locate a secret key on disk.
    CtlSecretNotFound(PathBuf),
    /// Decoding a message from the remote failed.
    Decode(prost::DecodeError),
    /// An Os level IO error occurred.
    Io(io::Error),
    /// An RPC call to the remote was received but failed.
    NetErr(NetErr),
    /// A parse error from an Invalid Color string
    ParseColor(termcolor::ParseColorError),
}

impl error::Error for SrvClientError {
    fn description(&self) -> &str {
        match *self {
            SrvClientError::ConnectionClosed => "Connection closed",
            SrvClientError::CtlSecretNotFound(_) => "Ctl secret key not found",
            SrvClientError::Decode(ref err) => err.description(),
            SrvClientError::Io(ref err) => err.description(),
            SrvClientError::NetErr(ref err) => err.description(),
            SrvClientError::ParseColor(ref err) => err.description(),
        }
    }
}

impl fmt::Display for SrvClientError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let content = match *self {
            SrvClientError::ConnectionClosed => {
                "The connection was unexpectedly closed.\n\nThis may be because the given \
                 Supervisor is in the middle of an orderly shutdown,\nand is no longer processing \
                 command requests."
                                   .to_string()
            }
            SrvClientError::CtlSecretNotFound(ref path) => {
                format!("No Supervisor CtlGateway secret set in `cli.toml` or found at {}. Run \
                         `hab setup` or run the Supervisor for the first time before attempting \
                         to command the Supervisor.",
                        path.display())
            }
            SrvClientError::Decode(ref err) => format!("{}", err),
            SrvClientError::Io(ref err) => {
                format!("Unable to contact the Supervisor.\n\nIf the Supervisor you are \
                         contacting is local, this probably means it is not running. You can run \
                         a Supervisor in the foreground with:\n\nhab sup run\n\nOr try restarting \
                         the Supervisor through your operating system's init process or Windows \
                         service.\n\nOriginal error is:\n\n{}",
                        err)
            }
            SrvClientError::NetErr(ref err) => format!("{}", err),
            SrvClientError::ParseColor(ref err) => format!("{}", err),
        };
        write!(f, "{}", content)
    }
}

impl From<NetErr> for SrvClientError {
    fn from(err: NetErr) -> Self { SrvClientError::NetErr(err) }
}

impl From<io::Error> for SrvClientError {
    fn from(err: io::Error) -> Self { SrvClientError::Io(err) }
}

impl From<prost::DecodeError> for SrvClientError {
    fn from(err: prost::DecodeError) -> Self { SrvClientError::Decode(err) }
}

impl From<termcolor::ParseColorError> for SrvClientError {
    fn from(err: termcolor::ParseColorError) -> Self { SrvClientError::ParseColor(err) }
}

/// Client for connecting and communicating with a server listener which speaks SrvProtocol.
///
/// See module doc for usage.
pub struct SrvClient {
    /// Sending and receiving framed socket pair for connecting and communicating to a remote
    /// server.
    socket: SrvStream,
    /// Transaction ID counter.
    ///
    /// Useful for determining the next transaction ID in sequence embed in
    /// the next transactional message sent.
    current_txn: SrvTxn,
}

impl SrvClient {
    /// Connect to the given remote server and authenticate with the given secret_key.
    pub fn connect(addr: &ListenCtlAddr,
                   secret_key: &str)
                   -> Box<dyn Future<Item = SrvClient, Error = SrvClientError> + 'static> {
        let secret_key = secret_key.to_string();
        let conn = TcpStream::connect(addr.as_ref()).map_err(SrvClientError::from)
                                                    .and_then(move |socket| {
                                                        let client = Self::new(socket, None);
                                                        let mut request =
                                                            protocol::ctl::Handshake::default();
                                                        request.secret_key = Some(secret_key);
                                                        client.call(request)
                                                              .into_future()
                                                              .map_err(|(err, _)| err)
                                                              .and_then(move |(m, io)| {
                                                                  m.map_or_else(
                            || Err(SrvClientError::ConnectionClosed),
                            move |m| {
                                m.try_ok()
                                    .map_err(SrvClientError::from)
                                    .and_then(|()| Ok(io.into_inner()))
                            },
                        )
                                                              })
                                                    });
        Box::new(conn)
    }

    pub fn read_secret_key() -> Result<String, SrvClientError> {
        let mut buf = String::new();
        protocol::read_secret_key(protocol::sup_root(None), &mut buf)
            .map_err(SrvClientError::from)?;
        Ok(buf)
    }

    fn new(socket: TcpStream, current_txn: Option<SrvTxn>) -> Self {
        SrvClient { socket:      Framed::new(socket, SrvCodec::new()),
                    current_txn: current_txn.unwrap_or_default(), }
    }

    /// Send a transactional request to the connected server. The returned `SrvReply` is a Stream
    /// containing one or more `SrvMessage` responses for the given request.
    pub fn call<T>(mut self, request: T) -> SrvReply
        where T: Into<SrvMessage> + fmt::Debug
    {
        self.current_txn.increment();
        let mut msg: SrvMessage = request.into();
        msg.set_transaction(self.current_txn);
        trace!("Sending SrvMessage -> {:?}", msg);
        SrvReply::new(self.socket.send(msg), self.current_txn)
    }

    /// Send a non-transactional request to the connected server.
    pub fn cast<T>(self, request: T) -> SrvSend
        where T: Into<SrvMessage> + fmt::Debug
    {
        let message: SrvMessage = request.into();
        self.socket.send(message)
    }
}

/// A `Future` that will resolve into a stream of one or more `SrvMessage` replies.
#[must_use = "futures do nothing unless polled"]
pub struct SrvReply {
    io:     sink::Send<SrvStream>,
    state:  SrvReplyState,
    txn_id: SrvTxn,
}

impl SrvReply {
    fn new(io: sink::Send<SrvStream>, txn_id: SrvTxn) -> Self {
        SrvReply { io,
                   state: SrvReplyState::Sending,
                   txn_id }
    }

    /// Consume the `SrvReply` and return the contained `SrvClient`.
    pub fn into_inner(self) -> SrvClient {
        match self.state {
            SrvReplyState::Receiving(io, true) => {
                SrvClient::new(io.into_inner(), Some(self.txn_id))
            }
            _ => panic!("into_inner called before complete"),
        }
    }
}

impl Stream for SrvReply {
    type Error = SrvClientError;
    type Item = SrvMessage;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            match self.state {
                SrvReplyState::Sending => {
                    let io = try_ready!(self.io.poll());
                    self.state = SrvReplyState::Receiving(io, false);
                    continue;
                }
                SrvReplyState::Receiving(_, true) => return Ok(Async::Ready(None)),
                SrvReplyState::Receiving(ref mut io, ref mut complete) => {
                    match try_ready!(io.poll()) {
                        Some(msg) => {
                            *complete = msg.is_complete();
                            return Ok(Async::Ready(Some(msg)));
                        }
                        None => return Err(SrvClientError::ConnectionClosed),
                    }
                }
            }
        }
    }
}

enum SrvReplyState {
    /// Request is sending.
    Sending,
    /// Request is sent and awaiting message(s). Receiving is complete when the bool at `self.1`
    /// is true.
    Receiving(SrvStream, bool),
}
<commit_msg>Be more explicit about connection refused errors.<commit_after>//! Client for connecting and communicating with a server listener which speaks SrvProtocol.
//!
//! Currently all functions will block and wait for a response from the remote. This is likely to
//! change to a futures based implementation as our needs increase.
//!
//! # RPC Call Example
//!
//! ```ignore
//! let conn = SrvClient::connect(&listen_addr, secret_key).wait()?;
//! let msg = protocols::ctl::ServiceGetDefaultCfg::new();
//! conn.call(msg).for_each(|reply| {
//!     match reply.message_id() {
//!         "ServiceCfg" => {
//!             let m = reply.parse::<protocols::types::ServiceCfg>().unwrap();
//!             println!("{}", m.get_default());
//!         }
//!         "NetErr" => {
//!             let m = reply.parse::<protocols::net::NetErr>().unwrap();
//!             println!("{}", m);
//!         }
//!         _ => (),
//!     }
//!     Ok(())
//! })
//! ```

#[macro_use]
extern crate futures;
use habitat_sup_protocol as protocol;
#[macro_use]
extern crate log;
use habitat_common as common;

use std::{error,
          fmt,
          io,
          path::PathBuf};

use crate::protocol::{codec::*,
                      net::NetErr};
use futures::{prelude::*,
              sink};
use tokio::net::TcpStream;
use tokio_codec::Framed;

use crate::common::types::ListenCtlAddr;

pub type SrvSend = sink::Send<SrvStream>;

/// Error types returned by a [`SrvClient`].
#[derive(Debug)]
pub enum SrvClientError {
    /// Connection refused
    ConnectionRefused,
    /// The remote server unexpectedly closed the connection.
    ConnectionClosed,
    /// Unable to locate a secret key on disk.
    CtlSecretNotFound(PathBuf),
    /// Decoding a message from the remote failed.
    Decode(prost::DecodeError),
    /// An Os level IO error occurred.
    Io(io::Error),
    /// An RPC call to the remote was received but failed.
    NetErr(NetErr),
    /// A parse error from an Invalid Color string
    ParseColor(termcolor::ParseColorError),
}

impl error::Error for SrvClientError {
    fn description(&self) -> &str {
        match *self {
            SrvClientError::ConnectionClosed => "Connection closed",
            SrvClientError::ConnectionRefused => "Connection refused",
            SrvClientError::CtlSecretNotFound(_) => "Ctl secret key not found",
            SrvClientError::Decode(ref err) => err.description(),
            SrvClientError::Io(ref err) => err.description(),
            SrvClientError::NetErr(ref err) => err.description(),
            SrvClientError::ParseColor(ref err) => err.description(),
        }
    }
}

impl fmt::Display for SrvClientError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let content = match *self {
            SrvClientError::ConnectionClosed => {
                "The connection was unexpectedly closed.\n\nThis may be because the given \
                 Supervisor is in the middle of an orderly shutdown,\nand is no longer processing \
                 command requests."
                                   .to_string()
            }
            SrvClientError::ConnectionRefused => {
                "Unable to contact the Supervisor.\n\nIf the Supervisor you are contacting is \
                 local, this probably means it is not running. You can run a Supervisor in the \
                 foreground with:\n\nhab sup run\n\nOr try restarting the Supervisor through your \
                 operating system's init process or Windows service."
                                                                     .to_string()
            }
            SrvClientError::CtlSecretNotFound(ref path) => {
                format!("No Supervisor CtlGateway secret set in `cli.toml` or found at {}. Run \
                         `hab setup` or run the Supervisor for the first time before attempting \
                         to command the Supervisor.",
                        path.display())
            }
            SrvClientError::Decode(ref err) => format!("{}", err),
            SrvClientError::Io(ref err) => format!("{}", err),
            SrvClientError::NetErr(ref err) => format!("{}", err),
            SrvClientError::ParseColor(ref err) => format!("{}", err),
        };
        write!(f, "{}", content)
    }
}

impl From<NetErr> for SrvClientError {
    fn from(err: NetErr) -> Self { SrvClientError::NetErr(err) }
}

impl From<io::Error> for SrvClientError {
    fn from(err: io::Error) -> Self {
        match err.kind() {
            io::ErrorKind::ConnectionRefused => SrvClientError::ConnectionRefused,
            _ => SrvClientError::Io(err),
        }
    }
}

impl From<prost::DecodeError> for SrvClientError {
    fn from(err: prost::DecodeError) -> Self { SrvClientError::Decode(err) }
}

impl From<termcolor::ParseColorError> for SrvClientError {
    fn from(err: termcolor::ParseColorError) -> Self { SrvClientError::ParseColor(err) }
}

/// Client for connecting and communicating with a server listener which speaks SrvProtocol.
///
/// See module doc for usage.
pub struct SrvClient {
    /// Sending and receiving framed socket pair for connecting and communicating to a remote
    /// server.
    socket: SrvStream,
    /// Transaction ID counter.
    ///
    /// Useful for determining the next transaction ID in sequence embed in
    /// the next transactional message sent.
    current_txn: SrvTxn,
}

impl SrvClient {
    /// Connect to the given remote server and authenticate with the given secret_key.
    pub fn connect(addr: &ListenCtlAddr,
                   secret_key: &str)
                   -> Box<dyn Future<Item = SrvClient, Error = SrvClientError> + 'static> {
        let secret_key = secret_key.to_string();
        let conn = TcpStream::connect(addr.as_ref()).map_err(SrvClientError::from)
                                                    .and_then(move |socket| {
                                                        let client = Self::new(socket, None);
                                                        let mut request =
                                                            protocol::ctl::Handshake::default();
                                                        request.secret_key = Some(secret_key);
                                                        client.call(request)
                                                              .into_future()
                                                              .map_err(|(err, _)| err)
                                                              .and_then(move |(m, io)| {
                                                                  m.map_or_else(
                            || Err(SrvClientError::ConnectionClosed),
                            move |m| {
                                m.try_ok()
                                    .map_err(SrvClientError::from)
                                    .and_then(|()| Ok(io.into_inner()))
                            },
                        )
                                                              })
                                                    });
        Box::new(conn)
    }

    pub fn read_secret_key() -> Result<String, SrvClientError> {
        let mut buf = String::new();
        protocol::read_secret_key(protocol::sup_root(None), &mut buf)
            .map_err(SrvClientError::from)?;
        Ok(buf)
    }

    fn new(socket: TcpStream, current_txn: Option<SrvTxn>) -> Self {
        SrvClient { socket:      Framed::new(socket, SrvCodec::new()),
                    current_txn: current_txn.unwrap_or_default(), }
    }

    /// Send a transactional request to the connected server. The returned `SrvReply` is a Stream
    /// containing one or more `SrvMessage` responses for the given request.
    pub fn call<T>(mut self, request: T) -> SrvReply
        where T: Into<SrvMessage> + fmt::Debug
    {
        self.current_txn.increment();
        let mut msg: SrvMessage = request.into();
        msg.set_transaction(self.current_txn);
        trace!("Sending SrvMessage -> {:?}", msg);
        SrvReply::new(self.socket.send(msg), self.current_txn)
    }

    /// Send a non-transactional request to the connected server.
    pub fn cast<T>(self, request: T) -> SrvSend
        where T: Into<SrvMessage> + fmt::Debug
    {
        let message: SrvMessage = request.into();
        self.socket.send(message)
    }
}

/// A `Future` that will resolve into a stream of one or more `SrvMessage` replies.
#[must_use = "futures do nothing unless polled"]
pub struct SrvReply {
    io:     sink::Send<SrvStream>,
    state:  SrvReplyState,
    txn_id: SrvTxn,
}

impl SrvReply {
    fn new(io: sink::Send<SrvStream>, txn_id: SrvTxn) -> Self {
        SrvReply { io,
                   state: SrvReplyState::Sending,
                   txn_id }
    }

    /// Consume the `SrvReply` and return the contained `SrvClient`.
    pub fn into_inner(self) -> SrvClient {
        match self.state {
            SrvReplyState::Receiving(io, true) => {
                SrvClient::new(io.into_inner(), Some(self.txn_id))
            }
            _ => panic!("into_inner called before complete"),
        }
    }
}

impl Stream for SrvReply {
    type Error = SrvClientError;
    type Item = SrvMessage;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            match self.state {
                SrvReplyState::Sending => {
                    let io = try_ready!(self.io.poll());
                    self.state = SrvReplyState::Receiving(io, false);
                    continue;
                }
                SrvReplyState::Receiving(_, true) => return Ok(Async::Ready(None)),
                SrvReplyState::Receiving(ref mut io, ref mut complete) => {
                    match try_ready!(io.poll()) {
                        Some(msg) => {
                            *complete = msg.is_complete();
                            return Ok(Async::Ready(Some(msg)));
                        }
                        None => return Err(SrvClientError::ConnectionClosed),
                    }
                }
            }
        }
    }
}

enum SrvReplyState {
    /// Request is sending.
    Sending,
    /// Request is sent and awaiting message(s). Receiving is complete when the bool at `self.1`
    /// is true.
    Receiving(SrvStream, bool),
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate error_chain;
extern crate murmurhash3;
extern crate regex;
extern crate rusty_machine;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate server;

use murmurhash3::murmurhash3_x86_32;
use regex::Regex;
use rusty_machine::prelude::BaseMatrix;
use rusty_machine::linalg::Vector;
use rusty_machine::linalg::Matrix;
use rusty_machine::linalg::Metric;
use std::fs::File;

static TOKEN_PATTERN: &'static str = r"\b\w\w+\b";

#[derive(Deserialize)]
pub struct JSONClassifier {
    feature_log_prob: Vec<f64>,
    class_log_prior: Vec<f64>,
    n_features: i32,
    n_classes: i32,
}

pub struct Classifier {
    n_features: i32,
    feature_log_prob: Matrix<f64>,
    class_log_prior: Matrix<f64>,
}

error_chain! {
    foreign_links {
        JSON(serde_json::Error);
        Io(::std::io::Error);
    }
}

impl Classifier {
    // Create matrices for classifier
    pub fn new(
        feature_log_prob: Vec<f64>,
        class_log_prior: Vec<f64>,
        n_features: i32,
        n_classes: i32,
    ) -> Classifier {
        let feature_log_mat =
            Matrix::new(n_classes as usize, n_features as usize, feature_log_prob);

        let class_prior_mat = Matrix::new(1, n_classes as usize, class_log_prior);

        Classifier {
            n_features: n_features,
            feature_log_prob: feature_log_mat,
            class_log_prior: class_prior_mat,
        }
    }

    pub fn predict(&self, doc: &str) -> usize {
        let feature_vec = Matrix::new(
            1,
            self.n_features as usize,
            create_feature_vec(doc, self.n_features),
        );
        let res = (feature_vec * self.feature_log_prob.transpose()) + &(self.class_log_prior);
        let mut class = 0;
        let mut cur_max = -1.0f64 / 0.0f64; // NEG_INFINITY
        for (i, &x) in res.into_vec().iter().enumerate() {
            if x > cur_max {
                class = i;
                cur_max = x;
            }
        }
        class
    }

    pub fn from_json(file: &str) -> Result<Classifier> {
        let file = File::open(file)?;
        let read: JSONClassifier = serde_json::from_reader(file)?;
        Ok(Classifier::new(
            read.feature_log_prob,
            read.class_log_prior,
            read.n_features,
            read.n_classes,
        ))
    }
}

/// Returns the index for a given feature.
///
/// Based on sklearn's HashingVectorizer, which uses
/// abs(murmurhash3(token))%n_features to determine
/// index of feature.
pub fn get_feature_idx(token: &str, n_features: i32) -> usize {
    let hash = murmurhash3_x86_32(token.as_bytes(), 0);
    return ((hash as i32).abs() % n_features) as usize;
}

pub fn tokenize_string(string: &str) -> Vec<&str> {
    let tokens: Vec<&str> = Regex::new(TOKEN_PATTERN)
        .unwrap()
        .find_iter(string)
        .map(|x| x.as_str())
        .collect();
    return tokens;
}

pub fn create_feature_vec(doc: &str, n_features: i32) -> Vec<f64> {
    let mut feature_vec = vec![0.0; (n_features as usize)];
    let lowercase_doc = &doc.to_lowercase();
    let tokens = tokenize_string(&lowercase_doc);

    for tok in tokens {
        feature_vec[get_feature_idx(tok, n_features)] += 1.0;
    }

    // L2 norm
    let mut normalized_vec = feature_vec.to_vec();
    let euc_norm = Vector::new(feature_vec).norm();
    normalized_vec = normalized_vec.iter().map(|x| x / euc_norm).collect();

    return normalized_vec;
}

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

    #[test]
    fn test_get_feature_idx() {
        let idx = get_feature_idx("Harold", 10);
        assert_eq!(idx, 4);

        let idx = get_feature_idx("Clinton", 10);
        assert_eq!(idx, 3);

        let idx = get_feature_idx("foobar", 10);
        assert_eq!(idx, 5);

        let idx = get_feature_idx("vote", 10);
        assert_eq!(idx, 6);

    }

    #[test]
    fn test_tokenize_string() {
        let test_string = "The quick brown fox jumped over the lazy dog";

        assert_eq!(
            vec![
                "The",
                "quick",
                "brown",
                "fox",
                "jumped",
                "over",
                "the",
                "lazy",
                "dog",
            ],
            tokenize_string(test_string)
        );
    }

    #[test]
    fn test_create_feature_vec() {
        let test_string = "The quick brown fox jumped over the lazy dog";
        let res = create_feature_vec(test_string, 10);

        assert_eq!(
            vec![
                0.0,
                0.22941573387056174,
                0.0,
                0.4588314677411235,
                0.0,
                0.4588314677411235,
                0.0,
                0.22941573387056174,
                0.6882472016116852,
                0.0,
            ],
            res
        )
    }

    #[test]
    fn test_prediction() {
        let test_pol_string = "Die Wähler sollten bei der Wahl abstimmen.";
        let test_non_pol_string = "This is nothing important, just watch netflix";
        let clf = Classifier::from_json("data/de/classifier.json").unwrap();
        assert_eq!(1, clf.predict(test_pol_string));
        assert_eq!(0, clf.predict(test_non_pol_string));

    }
}
<commit_msg>Added function to get likelihood percentage<commit_after>#[macro_use]
extern crate error_chain;
extern crate murmurhash3;
extern crate regex;
extern crate rusty_machine;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate server;

use murmurhash3::murmurhash3_x86_32;
use regex::Regex;
use rusty_machine::prelude::BaseMatrix;
use rusty_machine::linalg::Vector;
use rusty_machine::linalg::Matrix;
use rusty_machine::linalg::Metric;
use std::fs::File;

static TOKEN_PATTERN: &'static str = r"\b\w\w+\b";

#[derive(Deserialize)]
pub struct JSONClassifier {
    feature_log_prob: Vec<f64>,
    class_log_prior: Vec<f64>,
    n_features: i32,
    n_classes: i32,
}

pub struct Classifier {
    n_features: i32,
    feature_log_prob: Matrix<f64>,
    class_log_prior: Matrix<f64>,
}

error_chain! {
    foreign_links {
        JSON(serde_json::Error);
        Io(::std::io::Error);
    }
}

impl Classifier {
    // Create matrices for classifier
    pub fn new(
        feature_log_prob: Vec<f64>,
        class_log_prior: Vec<f64>,
        n_features: i32,
        n_classes: i32,
    ) -> Classifier {
        let feature_log_mat =
            Matrix::new(n_classes as usize, n_features as usize, feature_log_prob);

        let class_prior_mat = Matrix::new(1, n_classes as usize, class_log_prior);

        Classifier {
            n_features: n_features,
            feature_log_prob: feature_log_mat,
            class_log_prior: class_prior_mat,
        }
    }

    fn joint_log_likelihood(&self, doc: &str) -> Matrix<f64> {
        let feature_vec = Matrix::new(
            1,
            self.n_features as usize,
            create_feature_vec(doc, self.n_features),
        );
        let res = (feature_vec * self.feature_log_prob.transpose()) + &(self.class_log_prior);
        res
    }

    pub fn predict(&self, doc: &str) -> usize {
        let jll = self.joint_log_likelihood(doc);
        let mut class = 0;
        let mut cur_max = -1.0f64 / 0.0f64; // NEG_INFINITY
        for (i, &x) in jll.into_vec().iter().enumerate() {
            if x > cur_max {
                class = i;
                cur_max = x;
            }
        }
        class
    }

    pub fn predict_likelihoods(&self, doc:&str) -> Vec<f64> {
        let e = 1.0f64.exp();
        let jll = self.joint_log_likelihood(doc);
        let mut acc = 0.0;
        for &x in jll.clone().into_vec().iter() {
            acc += x.exp();
        }
        acc = acc.ln();
        //let log_prob_x = Matrix::new(1, 1, vec![acc]);
        let likelihoods = jll.into_vec().iter().map(|x| (x - acc).exp()).collect();
        likelihoods
    }

    pub fn from_json(file: &str) -> Result<Classifier> {
        let file = File::open(file)?;
        let read: JSONClassifier = serde_json::from_reader(file)?;
        Ok(Classifier::new(
            read.feature_log_prob,
            read.class_log_prior,
            read.n_features,
            read.n_classes,
        ))
    }
}

/// Returns the index for a given feature.
///
/// Based on sklearn's HashingVectorizer, which uses
/// abs(murmurhash3(token))%n_features to determine
/// index of feature.
pub fn get_feature_idx(token: &str, n_features: i32) -> usize {
    let hash = murmurhash3_x86_32(token.as_bytes(), 0);
    return ((hash as i32).abs() % n_features) as usize;
}

pub fn tokenize_string(string: &str) -> Vec<&str> {
    let tokens: Vec<&str> = Regex::new(TOKEN_PATTERN)
        .unwrap()
        .find_iter(string)
        .map(|x| x.as_str())
        .collect();
    return tokens;
}

pub fn create_feature_vec(doc: &str, n_features: i32) -> Vec<f64> {
    let mut feature_vec = vec![0.0; (n_features as usize)];
    let lowercase_doc = &doc.to_lowercase();
    let tokens = tokenize_string(&lowercase_doc);

    for tok in tokens {
        feature_vec[get_feature_idx(tok, n_features)] += 1.0;
    }

    // L2 norm
    let mut normalized_vec = feature_vec.to_vec();
    let euc_norm = Vector::new(feature_vec).norm();
    normalized_vec = normalized_vec.iter().map(|x| x / euc_norm).collect();

    return normalized_vec;
}

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

    #[test]
    fn test_get_feature_idx() {
        let idx = get_feature_idx("Harold", 10);
        assert_eq!(idx, 4);

        let idx = get_feature_idx("Clinton", 10);
        assert_eq!(idx, 3);

        let idx = get_feature_idx("foobar", 10);
        assert_eq!(idx, 5);

        let idx = get_feature_idx("vote", 10);
        assert_eq!(idx, 6);

    }

    #[test]
    fn test_tokenize_string() {
        let test_string = "The quick brown fox jumped over the lazy dog";

        assert_eq!(
            vec![
                "The",
                "quick",
                "brown",
                "fox",
                "jumped",
                "over",
                "the",
                "lazy",
                "dog",
            ],
            tokenize_string(test_string)
        );
    }

    #[test]
    fn test_create_feature_vec() {
        let test_string = "The quick brown fox jumped over the lazy dog";
        let res = create_feature_vec(test_string, 10);

        assert_eq!(
            vec![
                0.0,
                0.22941573387056174,
                0.0,
                0.4588314677411235,
                0.0,
                0.4588314677411235,
                0.0,
                0.22941573387056174,
                0.6882472016116852,
                0.0,
            ],
            res
        )
    }

    #[test]
    fn test_prediction() {
        let test_pol_string = "Die Wähler sollten bei der Wahl abstimmen.";
        let test_non_pol_string = "This is nothing important, just watch netflix";
        let clf = Classifier::from_json("data/de/classifier.json").unwrap();
        assert_eq!(1, clf.predict(test_pol_string));
        assert_eq!(0, clf.predict(test_non_pol_string));
    }

    #[test]
    fn test_predict_likelihoods() {
        let clf = Classifier::from_json("data/de/classifier.json").unwrap();
        let test_pol_string_1 = "Die Wähler sollten bei der Wahl abstimmen.";
        let test_pol_string_2 = "Die Wahl ist im September. Denken Sie daran, Ihren Kandidaten zu wählen.";
        let test_non_pol_string_1 = "This is nothing important, just watch netflix";
        let test_non_pol_string_2 = "Kaufen Sie Ihr Lieblingsessen. Das ist eine langweilige Werbung.";
        let likelihoods = clf.predict_likelihoods(test_pol_string_1);
        assert!(likelihoods[1] > likelihoods[0]);
        let likelihoods = clf.predict_likelihoods(test_pol_string_2);
        assert!(likelihoods[1] > likelihoods[0]);
        let likelihoods = clf.predict_likelihoods(test_non_pol_string_1);
        assert!(likelihoods[0] > likelihoods[1]);
        let likelihoods = clf.predict_likelihoods(test_non_pol_string_2);
        assert!(likelihoods[0] > likelihoods[1]);
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of cross-process surfaces for Linux. This uses X pixmaps.

use platform::surface::NativeSurfaceMethods;
use texturegl::Texture;

use geom::size::Size2D;
use libc::{c_int, c_uint, c_void};
use opengles::glx::{GLXFBConfig, GLXDrawable};
use opengles::glx::{GLX_BIND_TO_TEXTURE_RGBA_EXT};
use opengles::glx::{GLX_DRAWABLE_TYPE, GLX_FRONT_EXT, GLX_PIXMAP_BIT};
use opengles::glx::{GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT};
use opengles::glx::{GLX_TEXTURE_TARGET_EXT, glXCreatePixmap, glXDestroyPixmap};
use opengles::glx::{glXGetProcAddress, glXChooseFBConfig};
use opengles::glx::{glXGetVisualFromFBConfig};
use opengles::glx::{GLX_RGBA_BIT, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_DOUBLEBUFFER};
use opengles::gl2::NO_ERROR;
use opengles::gl2;
use std::cast;
use std::c_str::CString;
use std::ptr;
use xlib::xlib::{Display, Pixmap, XCreateGC, XCreateImage, XCreatePixmap, XDefaultScreen};
use xlib::xlib::{XDisplayString, XFreePixmap, XGetGeometry, XOpenDisplay, XPutImage, XRootWindow};
use xlib::xlib::{XVisualInfo, ZPixmap};

/// The display and visual info. This is needed in order to upload on the painting side. This
/// holds a weak reference to the display and will not close it when done.
///
/// FIXME(pcwalton): Mark nonsendable and noncopyable.
pub struct NativePaintingGraphicsContext {
    display: *Display,
    visual_info: *XVisualInfo,
}

impl NativePaintingGraphicsContext {
    pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext {
        // FIXME(pcwalton): It would be more robust to actually have the compositor pass the
        // visual.
        let (compositor_visual_info, _) =
            NativeCompositingGraphicsContext::compositor_visual_info(metadata.display);

        NativePaintingGraphicsContext {
            display: metadata.display,
            visual_info: compositor_visual_info,
        }
    }
}

/// The display, visual info, and framebuffer configuration. This is needed in order to bind to a
/// texture on the compositor side. This holds only a *weak* reference to the display and does not
/// close it.
///
/// FIXME(pcwalton): Unchecked weak references are bad and can violate memory safety. This is hard
/// to fix because the Display is given to us by the native windowing system, but we should fix it
/// someday.
///
/// FIXME(pcwalton): Mark nonsendable.
pub struct NativeCompositingGraphicsContext {
    display: *Display,
    visual_info: *XVisualInfo,
    framebuffer_configuration: Option<GLXFBConfig>,
}

impl NativeCompositingGraphicsContext {
    /// Chooses the compositor visual info using the same algorithm that the compositor uses.
    ///
    /// FIXME(pcwalton): It would be more robust to actually have the compositor pass the visual.
    fn compositor_visual_info(display: *Display) -> (*XVisualInfo, Option<GLXFBConfig>) {
        unsafe {
            let glx_display = cast::transmute(display);

            // CONSIDER:
            // In skia, they compute the GLX_ALPHA_SIZE minimum and request
            // that as well.

            let fbconfig_attributes = [
                GLX_DOUBLEBUFFER, 0,
                GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_WINDOW_BIT,
                GLX_BIND_TO_TEXTURE_RGBA_EXT, 1,
                GLX_RENDER_TYPE, GLX_RGBA_BIT,
                0
            ];

            let screen = XDefaultScreen(display);
            let mut number_of_configs = 0;
            let configs = glXChooseFBConfig(glx_display, screen,
                                            &fbconfig_attributes[0], &mut number_of_configs);
            // NVidia drives have RGBA configurations that use 24-bit XVisual, not capable of
            // representing an alpha-channel in Pixmap form, so we look for the configuration
            // with a full set of 32 bits.
            for i in range(0, number_of_configs as int) {
                let config = *configs.offset(i);
                let visual_info : *XVisualInfo = cast::transmute(glXGetVisualFromFBConfig(glx_display, config));
                if (*visual_info).depth == 32 {
                    return (visual_info, Some(config))
                }
            }

            fail!("Unable to locate a GLX FB configuration that supports RGBA.");
        }
    }

    /// Creates a native graphics context from the given X display connection. This uses GLX. Only
    /// the compositor is allowed to call this.
    pub fn from_display(display: *Display) -> NativeCompositingGraphicsContext {
        let (visual_info, fbconfig) = NativeCompositingGraphicsContext::compositor_visual_info(display);

        NativeCompositingGraphicsContext {
            display: display,
            visual_info: visual_info,
            framebuffer_configuration: fbconfig,
        }
    }
}

/// The X display.
#[deriving(Clone)]
pub struct NativeGraphicsMetadata {
    pub display: *Display,
}

impl NativeGraphicsMetadata {
    /// Creates graphics metadata from a metadata descriptor.
    pub fn from_descriptor(descriptor: &NativeGraphicsMetadataDescriptor)
                           -> NativeGraphicsMetadata {
        // WARNING: We currently rely on the X display connection being the
        // same in both the Painting and Compositing contexts, as otherwise
        // the X Pixmap will not be sharable across them. Using this
        // method breaks that assumption.
        unsafe {
            let display = descriptor.display.with_c_str(|c_str| {
                    XOpenDisplay(c_str)
                });

            if display.is_null() {
                fail!("XOpenDisplay() failed!");
            }

            NativeGraphicsMetadata {
                display: display,
            }
        }
    }
}

/// A sendable form of the X display string.
#[deriving(Clone, Decodable, Encodable)]
pub struct NativeGraphicsMetadataDescriptor {
    display: ~str,
}

impl NativeGraphicsMetadataDescriptor {
    /// Creates a metadata descriptor from metadata.
    pub fn from_metadata(metadata: NativeGraphicsMetadata) -> NativeGraphicsMetadataDescriptor {
        unsafe {
            let c_str = CString::new(XDisplayString(metadata.display), false);
            NativeGraphicsMetadataDescriptor {
                display: c_str.as_str().unwrap().to_str(),
            }
        }
    }
}

#[deriving(Eq)]
pub enum NativeSurfaceTransientData {
    NoTransientData,
    RenderTaskTransientData(*Display, *XVisualInfo),
}

#[deriving(Decodable, Encodable)]
pub struct NativeSurface {
    /// The pixmap.
    pixmap: Pixmap,

    /// Whether this pixmap will leak if the destructor runs. This is for debugging purposes.
    will_leak: bool,
}

impl Drop for NativeSurface {
    fn drop(&mut self) {
        if self.will_leak {
            fail!("You should have disposed of the pixmap properly with destroy()! This pixmap \
                   will leak!");
        }
    }
}

impl NativeSurface {
    pub fn from_pixmap(pixmap: Pixmap) -> NativeSurface {
        NativeSurface {
            pixmap: pixmap,
            will_leak: true,
        }
    }
}

impl NativeSurfaceMethods for NativeSurface {
    fn new(native_context: &NativePaintingGraphicsContext, size: Size2D<i32>, stride: i32)
           -> NativeSurface {
        unsafe {
            // Create the pixmap.
            let screen = XDefaultScreen(native_context.display);
            let window = XRootWindow(native_context.display, screen);
            let pixmap = XCreatePixmap(native_context.display,
                                       window,
                                       size.width as c_uint,
                                       size.height as c_uint,
                                       (*native_context.visual_info).depth as c_uint);
            NativeSurface::from_pixmap(pixmap)
        }
    }

    /// This may only be called on the compositor side.
    fn bind_to_texture(&self,
                       native_context: &NativeCompositingGraphicsContext,
                       texture: &Texture,
                       _size: Size2D<int>) {
        unsafe {
            // Create the GLX pixmap.
            //
            // FIXME(pcwalton): RAII for exception safety?
            let pixmap_attributes = [
                GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
                GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
                0
            ];

            let glx_display = cast::transmute(native_context.display);

            let glx_pixmap = glXCreatePixmap(glx_display,
                                             native_context.framebuffer_configuration.expect(
                                                 "GLX 1.3 should have a framebuffer_configuration"),
                                             self.pixmap,
                                             &pixmap_attributes[0]);

            let glXBindTexImageEXT: extern "C" fn(*Display, GLXDrawable, c_int, *c_int) =
                cast::transmute(glXGetProcAddress(cast::transmute(&"glXBindTexImageEXT\x00"[0])));
            assert!(glXBindTexImageEXT as *c_void != ptr::null());
            let _bound = texture.bind();
            glXBindTexImageEXT(native_context.display,
                               cast::transmute(glx_pixmap),
                               GLX_FRONT_EXT,
                               ptr::null());
            assert_eq!(gl2::get_error(), NO_ERROR);

            // FIXME(pcwalton): Recycle these for speed?
            glXDestroyPixmap(glx_display, glx_pixmap);
        }
    }

    /// This may only be called on the painting side.
    fn upload(&self, graphics_context: &NativePaintingGraphicsContext, data: &[u8]) {
        unsafe {
            // Ensure that we're running on the render task. Take the display.
            let pixmap = self.pixmap;

            // Figure out the width, height, and depth of the pixmap.
            let mut root_window = 0;
            let mut x = 0;
            let mut y = 0;
            let mut width = 0;
            let mut height = 0;
            let mut border_width = 0;
            let mut depth = 0;
            let _ = XGetGeometry(graphics_context.display,
                                 cast::transmute(pixmap),
                                 &mut root_window,
                                 &mut x,
                                 &mut y,
                                 &mut width,
                                 &mut height,
                                 &mut border_width,
                                 &mut depth);

            // Create the image.
            let image = XCreateImage(graphics_context.display,
                                     (*graphics_context.visual_info).visual,
                                     depth,
                                     ZPixmap,
                                     0,
                                     cast::transmute(&data[0]),
                                     width as c_uint,
                                     height as c_uint,
                                     32,
                                     0);

            // Create the X graphics context.
            let gc = XCreateGC(graphics_context.display, pixmap, 0, ptr::null());

            // Draw the image.
            let _ = XPutImage(graphics_context.display,
                              pixmap,
                              gc,
                              image,
                              0,
                              0,
                              0,
                              0,
                              width,
                              height);
        }
    }

    fn get_id(&self) -> int {
        self.pixmap as int
    }

    fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        unsafe {
            assert!(self.pixmap != 0);
            XFreePixmap(graphics_context.display, self.pixmap);
            self.mark_wont_leak()
        }
    }

    fn mark_will_leak(&mut self) {
        self.will_leak = true
    }

    fn mark_wont_leak(&mut self) {
        self.will_leak = false
    }
}

<commit_msg>Only apply nvidia hack with nvidia drivers Check the GLX vendor string for nvidia before applying nvidia driver hack.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of cross-process surfaces for Linux. This uses X pixmaps.

use platform::surface::NativeSurfaceMethods;
use texturegl::Texture;

use geom::size::Size2D;
use libc::{c_char, c_int, c_uint, c_void};
use opengles::glx::{GLXFBConfig, GLXDrawable};
use opengles::glx::{GLX_BIND_TO_TEXTURE_RGBA_EXT};
use opengles::glx::{GLX_DRAWABLE_TYPE, GLX_FRONT_EXT, GLX_PIXMAP_BIT};
use opengles::glx::{GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT};
use opengles::glx::{GLX_TEXTURE_TARGET_EXT, glXCreatePixmap, glXDestroyPixmap};
use opengles::glx::{glXGetProcAddress, glXChooseFBConfig};
use opengles::glx::{glXGetVisualFromFBConfig};
use opengles::glx::{GLX_RGBA_BIT, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_DOUBLEBUFFER};
use opengles::gl2::NO_ERROR;
use opengles::gl2;
use std::cast;
use std::c_str::CString;
use std::ptr;
use std::str::raw::from_c_str;
use xlib::xlib::{Display, Pixmap, XCreateGC, XCreateImage, XCreatePixmap, XDefaultScreen};
use xlib::xlib::{XDisplayString, XFreePixmap, XGetGeometry, XOpenDisplay, XPutImage, XRootWindow};
use xlib::xlib::{XVisualInfo, ZPixmap};

/// The display and visual info. This is needed in order to upload on the painting side. This
/// holds a weak reference to the display and will not close it when done.
///
/// FIXME(pcwalton): Mark nonsendable and noncopyable.
pub struct NativePaintingGraphicsContext {
    display: *Display,
    visual_info: *XVisualInfo,
}

impl NativePaintingGraphicsContext {
    pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext {
        // FIXME(pcwalton): It would be more robust to actually have the compositor pass the
        // visual.
        let (compositor_visual_info, _) =
            NativeCompositingGraphicsContext::compositor_visual_info(metadata.display);

        NativePaintingGraphicsContext {
            display: metadata.display,
            visual_info: compositor_visual_info,
        }
    }
}

/// The display, visual info, and framebuffer configuration. This is needed in order to bind to a
/// texture on the compositor side. This holds only a *weak* reference to the display and does not
/// close it.
///
/// FIXME(pcwalton): Unchecked weak references are bad and can violate memory safety. This is hard
/// to fix because the Display is given to us by the native windowing system, but we should fix it
/// someday.
///
/// FIXME(pcwalton): Mark nonsendable.
pub struct NativeCompositingGraphicsContext {
    display: *Display,
    visual_info: *XVisualInfo,
    framebuffer_configuration: Option<GLXFBConfig>,
}

impl NativeCompositingGraphicsContext {
    /// Chooses the compositor visual info using the same algorithm that the compositor uses.
    ///
    /// FIXME(pcwalton): It would be more robust to actually have the compositor pass the visual.
    fn compositor_visual_info(display: *Display) -> (*XVisualInfo, Option<GLXFBConfig>) {
        unsafe {
            let glx_display = cast::transmute(display);

            // CONSIDER:
            // In skia, they compute the GLX_ALPHA_SIZE minimum and request
            // that as well.

            let fbconfig_attributes = [
                GLX_DOUBLEBUFFER, 0,
                GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_WINDOW_BIT,
                GLX_BIND_TO_TEXTURE_RGBA_EXT, 1,
                GLX_RENDER_TYPE, GLX_RGBA_BIT,
                0
            ];

            let screen = XDefaultScreen(display);
            let mut number_of_configs = 0;
            let configs = glXChooseFBConfig(glx_display, screen,
                                            &fbconfig_attributes[0], &mut number_of_configs);
            let glXGetClientString: extern "C" fn(*Display, c_int) -> *c_char =
                cast::transmute(glXGetProcAddress(cast::transmute(&"glXGetClientString\x00"[0])));
            assert!(glXGetClientString as *c_void != ptr::null());
            let glx_client_vendor = glXGetClientString(display, 1);
            if from_c_str(glx_client_vendor).to_ascii().eq_ignore_case("NVIDIA".to_ascii()) {
                // NVidia drives have RGBA configurations that use 24-bit XVisual, not capable of
                // representing an alpha-channel in Pixmap form, so we look for the configuration
                // with a full set of 32 bits.
                for i in range(0, number_of_configs as int) {
                    let config = *configs.offset(i);
                    let visual_info : *XVisualInfo = cast::transmute(glXGetVisualFromFBConfig(glx_display, config));
                    if (*visual_info).depth == 32 {
                        return (visual_info, Some(config))
                    }
                }
            }else if number_of_configs != 0 {
                let fbconfig = *configs.offset(0);
                let vi = glXGetVisualFromFBConfig(glx_display, fbconfig);
                return (cast::transmute(vi), Some(fbconfig));

            }
            fail!("Unable to locate a GLX FB configuration that supports RGBA.");
        }
    }

    /// Creates a native graphics context from the given X display connection. This uses GLX. Only
    /// the compositor is allowed to call this.
    pub fn from_display(display: *Display) -> NativeCompositingGraphicsContext {
        let (visual_info, fbconfig) = NativeCompositingGraphicsContext::compositor_visual_info(display);

        NativeCompositingGraphicsContext {
            display: display,
            visual_info: visual_info,
            framebuffer_configuration: fbconfig,
        }
    }
}

/// The X display.
#[deriving(Clone)]
pub struct NativeGraphicsMetadata {
    pub display: *Display,
}

impl NativeGraphicsMetadata {
    /// Creates graphics metadata from a metadata descriptor.
    pub fn from_descriptor(descriptor: &NativeGraphicsMetadataDescriptor)
                           -> NativeGraphicsMetadata {
        // WARNING: We currently rely on the X display connection being the
        // same in both the Painting and Compositing contexts, as otherwise
        // the X Pixmap will not be sharable across them. Using this
        // method breaks that assumption.
        unsafe {
            let display = descriptor.display.with_c_str(|c_str| {
                    XOpenDisplay(c_str)
                });

            if display.is_null() {
                fail!("XOpenDisplay() failed!");
            }

            NativeGraphicsMetadata {
                display: display,
            }
        }
    }
}

/// A sendable form of the X display string.
#[deriving(Clone, Decodable, Encodable)]
pub struct NativeGraphicsMetadataDescriptor {
    display: ~str,
}

impl NativeGraphicsMetadataDescriptor {
    /// Creates a metadata descriptor from metadata.
    pub fn from_metadata(metadata: NativeGraphicsMetadata) -> NativeGraphicsMetadataDescriptor {
        unsafe {
            let c_str = CString::new(XDisplayString(metadata.display), false);
            NativeGraphicsMetadataDescriptor {
                display: c_str.as_str().unwrap().to_str(),
            }
        }
    }
}

#[deriving(Eq)]
pub enum NativeSurfaceTransientData {
    NoTransientData,
    RenderTaskTransientData(*Display, *XVisualInfo),
}

#[deriving(Decodable, Encodable)]
pub struct NativeSurface {
    /// The pixmap.
    pixmap: Pixmap,

    /// Whether this pixmap will leak if the destructor runs. This is for debugging purposes.
    will_leak: bool,
}

impl Drop for NativeSurface {
    fn drop(&mut self) {
        if self.will_leak {
            fail!("You should have disposed of the pixmap properly with destroy()! This pixmap \
                   will leak!");
        }
    }
}

impl NativeSurface {
    pub fn from_pixmap(pixmap: Pixmap) -> NativeSurface {
        NativeSurface {
            pixmap: pixmap,
            will_leak: true,
        }
    }
}

impl NativeSurfaceMethods for NativeSurface {
    fn new(native_context: &NativePaintingGraphicsContext, size: Size2D<i32>, stride: i32)
           -> NativeSurface {
        unsafe {
            // Create the pixmap.
            let screen = XDefaultScreen(native_context.display);
            let window = XRootWindow(native_context.display, screen);
            let pixmap = XCreatePixmap(native_context.display,
                                       window,
                                       size.width as c_uint,
                                       size.height as c_uint,
                                       (*native_context.visual_info).depth as c_uint);
            NativeSurface::from_pixmap(pixmap)
        }
    }

    /// This may only be called on the compositor side.
    fn bind_to_texture(&self,
                       native_context: &NativeCompositingGraphicsContext,
                       texture: &Texture,
                       _size: Size2D<int>) {
        unsafe {
            // Create the GLX pixmap.
            //
            // FIXME(pcwalton): RAII for exception safety?
            let pixmap_attributes = [
                GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
                GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
                0
            ];

            let glx_display = cast::transmute(native_context.display);

            let glx_pixmap = glXCreatePixmap(glx_display,
                                             native_context.framebuffer_configuration.expect(
                                                 "GLX 1.3 should have a framebuffer_configuration"),
                                             self.pixmap,
                                             &pixmap_attributes[0]);

            let glXBindTexImageEXT: extern "C" fn(*Display, GLXDrawable, c_int, *c_int) =
                cast::transmute(glXGetProcAddress(cast::transmute(&"glXBindTexImageEXT\x00"[0])));
            assert!(glXBindTexImageEXT as *c_void != ptr::null());
            let _bound = texture.bind();
            glXBindTexImageEXT(native_context.display,
                               cast::transmute(glx_pixmap),
                               GLX_FRONT_EXT,
                               ptr::null());
            assert_eq!(gl2::get_error(), NO_ERROR);

            // FIXME(pcwalton): Recycle these for speed?
            glXDestroyPixmap(glx_display, glx_pixmap);
        }
    }

    /// This may only be called on the painting side.
    fn upload(&self, graphics_context: &NativePaintingGraphicsContext, data: &[u8]) {
        unsafe {
            // Ensure that we're running on the render task. Take the display.
            let pixmap = self.pixmap;

            // Figure out the width, height, and depth of the pixmap.
            let mut root_window = 0;
            let mut x = 0;
            let mut y = 0;
            let mut width = 0;
            let mut height = 0;
            let mut border_width = 0;
            let mut depth = 0;
            let _ = XGetGeometry(graphics_context.display,
                                 cast::transmute(pixmap),
                                 &mut root_window,
                                 &mut x,
                                 &mut y,
                                 &mut width,
                                 &mut height,
                                 &mut border_width,
                                 &mut depth);

            // Create the image.
            let image = XCreateImage(graphics_context.display,
                                     (*graphics_context.visual_info).visual,
                                     depth,
                                     ZPixmap,
                                     0,
                                     cast::transmute(&data[0]),
                                     width as c_uint,
                                     height as c_uint,
                                     32,
                                     0);

            // Create the X graphics context.
            let gc = XCreateGC(graphics_context.display, pixmap, 0, ptr::null());

            // Draw the image.
            let _ = XPutImage(graphics_context.display,
                              pixmap,
                              gc,
                              image,
                              0,
                              0,
                              0,
                              0,
                              width,
                              height);
        }
    }

    fn get_id(&self) -> int {
        self.pixmap as int
    }

    fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        unsafe {
            assert!(self.pixmap != 0);
            XFreePixmap(graphics_context.display, self.pixmap);
            self.mark_wont_leak()
        }
    }

    fn mark_will_leak(&mut self) {
        self.will_leak = true
    }

    fn mark_wont_leak(&mut self) {
        self.will_leak = false
    }
}

<|endoftext|>


<commit_before>use bindgen::callbacks::*;

#[derive(Debug)]
pub struct RemoveFunctionPrefixParseCallback {
    pub remove_function_prefix: Option<String>,
}

impl RemoveFunctionPrefixParseCallback {
    pub fn new(prefix: &str) -> Self {
        RemoveFunctionPrefixParseCallback {
            remove_function_prefix: Some(prefix.to_string()),
        }
    }
}

impl ParseCallbacks for RemoveFunctionPrefixParseCallback {
    fn generated_name_override(&self, function_name: &str) -> Option<String> {
        if let Some(prefix) = &self.remove_function_prefix {
            if function_name.starts_with(prefix) {
                return Some(function_name[prefix.len()..].to_string());
            }
        }
        None
    }
}

#[derive(Debug)]
struct EnumVariantRename;

impl ParseCallbacks for EnumVariantRename {
    fn enum_variant_name(
        &self,
        _enum_name: Option<&str>,
        original_variant_name: &str,
        _variant_value: EnumVariantValue,
    ) -> Option<String> {
        Some(format!("RENAMED_{}", original_variant_name))
    }
}

#[derive(Debug)]
struct BlocklistedTypeImplementsTrait;

impl ParseCallbacks for BlocklistedTypeImplementsTrait {
    fn blocklisted_type_implements_trait(
        &self,
        _name: &str,
        derive_trait: DeriveTrait,
    ) -> Option<ImplementsTrait> {
        if derive_trait == DeriveTrait::Hash {
            Some(ImplementsTrait::No)
        } else {
            Some(ImplementsTrait::Yes)
        }
    }
}

pub fn lookup(cb: &str) -> Box<dyn ParseCallbacks> {
    match cb {
        "enum-variant-rename" => Box::new(EnumVariantRename),
        "blocklisted-type-implements-trait" => {
            Box::new(BlocklistedTypeImplementsTrait)
        }
        call_back => {
            if call_back.starts_with("remove-function-prefix-") {
                let prefix = call_back
                    .split("remove-function-prefix-")
                    .last()
                    .to_owned();
                let lnopc =
                    RemoveFunctionPrefixParseCallback::new(prefix.unwrap());
                Box::new(lnopc)
            } else {
                panic!("Couldn't find name ParseCallbacks: {}", cb)
            }
        }
    }
}
<commit_msg>Use str::strip_prefix<commit_after>use bindgen::callbacks::*;

#[derive(Debug)]
pub struct RemoveFunctionPrefixParseCallback {
    pub remove_function_prefix: Option<String>,
}

impl RemoveFunctionPrefixParseCallback {
    pub fn new(prefix: &str) -> Self {
        RemoveFunctionPrefixParseCallback {
            remove_function_prefix: Some(prefix.to_string()),
        }
    }
}

impl ParseCallbacks for RemoveFunctionPrefixParseCallback {
    fn generated_name_override(&self, function_name: &str) -> Option<String> {
        if let Some(prefix) = &self.remove_function_prefix {
            if let Some(name) = function_name.strip_prefix(prefix) {
                return Some(name.to_string())
            }
        }
        None
    }
}

#[derive(Debug)]
struct EnumVariantRename;

impl ParseCallbacks for EnumVariantRename {
    fn enum_variant_name(
        &self,
        _enum_name: Option<&str>,
        original_variant_name: &str,
        _variant_value: EnumVariantValue,
    ) -> Option<String> {
        Some(format!("RENAMED_{}", original_variant_name))
    }
}

#[derive(Debug)]
struct BlocklistedTypeImplementsTrait;

impl ParseCallbacks for BlocklistedTypeImplementsTrait {
    fn blocklisted_type_implements_trait(
        &self,
        _name: &str,
        derive_trait: DeriveTrait,
    ) -> Option<ImplementsTrait> {
        if derive_trait == DeriveTrait::Hash {
            Some(ImplementsTrait::No)
        } else {
            Some(ImplementsTrait::Yes)
        }
    }
}

pub fn lookup(cb: &str) -> Box<dyn ParseCallbacks> {
    match cb {
        "enum-variant-rename" => Box::new(EnumVariantRename),
        "blocklisted-type-implements-trait" => {
            Box::new(BlocklistedTypeImplementsTrait)
        }
        call_back => {
            if call_back.starts_with("remove-function-prefix-") {
                let prefix = call_back
                    .split("remove-function-prefix-")
                    .last()
                    .to_owned();
                let lnopc =
                    RemoveFunctionPrefixParseCallback::new(prefix.unwrap());
                Box::new(lnopc)
            } else {
                panic!("Couldn't find name ParseCallbacks: {}", cb)
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Utilities for interacting with tasks implemented in the rust-rosetta repository.

use std::collections::HashSet;
use std::fs;
use std::path::{Path, PathBuf};

use anyhow::{anyhow, Context, Error};
use reqwest::Url;
use toml::Value;
use walkdir::WalkDir;

use crate::remote;
use crate::TASK_URL_RE;

/// A local (in repository) implementation of a Rosetta Code task.
#[derive(Debug, Clone)]
pub struct LocalTask {
    /// The name of the package implementing this task.
    pub package_name: String,

    /// The path to the crate manifest for the task.
    pub manifest_path: PathBuf,

    /// A set of filenames containing the Rust source code of the tasks.
    pub source: HashSet<PathBuf>,

    /// The URL of the task on the Rosetta Code wiki.
    ///
    /// This is parsed from the crate metadata, so it may not point to an actual Rosetta Code URL.
    pub url: Url,

    /// The title of the task on Rosetta Code.
    ///
    /// The title is normalized, so it can be used to uniquely identify the task on the wiki.
    pub title: String,
}

/// Given a path to the root `Cargo.toml`, returns a list of tasks implemented in the rust-rosetta
/// repository.
pub fn parse_tasks<P>(manifest_path: P) -> Result<Vec<LocalTask>, Error>
where
    P: AsRef<Path>,
{
    let metadata = cargo_metadata::metadata(Some(&manifest_path.as_ref())).unwrap();
    let packages = &metadata.packages;

    let mut tasks = vec![];

    for member in &metadata.workspace_members {
        // Skip if we encounter known non-task crates.
        if member.name() == "rust-rosetta" || member.name() == "meta" {
            continue;
        }

        let package = packages.iter().find(|p| p.name == member.name()).unwrap();

        // If the package has a proc-macro or dylib target, it's probably just a dependency of
        // another task. Skip it.
        let closure = |t: &cargo_metadata::Target| {
            t.kind.contains(&String::from("dylib")) || t.kind.contains(&String::from("proc-macro"))
        };
        if package.targets.iter().any(closure) {
            continue;
        }

        let manifest_path = Path::new(&package.manifest_path);

        let rosetta_url = parse_rosetta_url(manifest_path).context(format!(
            "could not parse rosetta code URL from {}",
            manifest_path.display()
        ))?;

        let title = {
            let caps = TASK_URL_RE.captures(rosetta_url.as_str()).ok_or_else(|| {
                anyhow!(
                    "task URL does not match rosetta code regex: {}",
                    rosetta_url
                )
            })?;
            remote::decode_title(&caps[1])
        };

        tasks.push(LocalTask {
            package_name: member.name().to_owned(),
            manifest_path: manifest_path.to_owned(),
            source: find_sources(manifest_path.parent().unwrap())?,
            url: rosetta_url,
            title,
        });
    }

    Ok(tasks)
}

/// Parses the Rosetta Code URL from the package metadata in a task's crate manifest.
fn parse_rosetta_url<P>(manifest_path: P) -> Result<Url, Error>
where
    P: AsRef<Path>,
{
    let manifest: Value = fs::read_to_string(manifest_path)?.parse()?;

    let url = manifest
        .get("package")
        .and_then(|p| p.get("metadata"))
        .and_then(|m| m.get("rosettacode"))
        .and_then(|m| m.get("url"))
        .and_then(|u| u.as_str())
        .ok_or_else(|| anyhow!("unexpected metadata format"))?;

    Ok(Url::parse(url)?)
}

/// Collect the paths to the source files of a given package.
fn find_sources<P>(directory: P) -> Result<HashSet<PathBuf>, Error>
where
    P: AsRef<Path>,
{
    let mut sources = HashSet::new();

    for entry in WalkDir::new(directory) {
        let entry = entry?;

        if let Some("rs") = entry.path().extension().and_then(|s| s.to_str()) {
            sources.insert(entry.path().to_owned());
        }
    }

    Ok(sources)
}
<commit_msg>add function to check if a package has a proc-macro or dylib target<commit_after>//! Utilities for interacting with tasks implemented in the rust-rosetta repository.

use std::collections::HashSet;
use std::fs;
use std::path::{Path, PathBuf};

use anyhow::{anyhow, Context, Error};
use reqwest::Url;
use toml::Value;
use walkdir::WalkDir;

use crate::remote;
use crate::TASK_URL_RE;

/// A local (in repository) implementation of a Rosetta Code task.
#[derive(Debug, Clone)]
pub struct LocalTask {
    /// The name of the package implementing this task.
    pub package_name: String,

    /// The path to the crate manifest for the task.
    pub manifest_path: PathBuf,

    /// A set of filenames containing the Rust source code of the tasks.
    pub source: HashSet<PathBuf>,

    /// The URL of the task on the Rosetta Code wiki.
    ///
    /// This is parsed from the crate metadata, so it may not point to an actual Rosetta Code URL.
    pub url: Url,

    /// The title of the task on Rosetta Code.
    ///
    /// The title is normalized, so it can be used to uniquely identify the task on the wiki.
    pub title: String,
}

/// Check if the target of a package is of kind dylib or proc-macro.
fn is_dylib_or_proc_macro(target: &cargo_metadata::Target) -> bool {
    target.kind.contains(&String::from("dylib"))
        || target.kind.contains(&String::from("proc-macro"))
}

/// Given a path to the root `Cargo.toml`, returns a list of tasks implemented in the rust-rosetta
/// repository.
pub fn parse_tasks<P>(manifest_path: P) -> Result<Vec<LocalTask>, Error>
where
    P: AsRef<Path>,
{
    let metadata = cargo_metadata::metadata(Some(&manifest_path.as_ref())).unwrap();
    let packages = &metadata.packages;

    let mut tasks = vec![];

    for member in &metadata.workspace_members {
        // Skip if we encounter known non-task crates.
        if member.name() == "rust-rosetta" || member.name() == "meta" {
            continue;
        }

        let package = packages.iter().find(|p| p.name == member.name()).unwrap();

        // If the package has a proc-macro or dylib target, it's probably just a dependency of
        // another task. Skip it.
        if package.targets.iter().any(|t| is_dylib_or_proc_macro(t)) {
            continue;
        }

        let manifest_path = Path::new(&package.manifest_path);

        let rosetta_url = parse_rosetta_url(manifest_path).context(format!(
            "could not parse rosetta code URL from {}",
            manifest_path.display()
        ))?;

        let title = {
            let caps = TASK_URL_RE.captures(rosetta_url.as_str()).ok_or_else(|| {
                anyhow!(
                    "task URL does not match rosetta code regex: {}",
                    rosetta_url
                )
            })?;
            remote::decode_title(&caps[1])
        };

        tasks.push(LocalTask {
            package_name: member.name().to_owned(),
            manifest_path: manifest_path.to_owned(),
            source: find_sources(manifest_path.parent().unwrap())?,
            url: rosetta_url,
            title,
        });
    }

    Ok(tasks)
}

/// Parses the Rosetta Code URL from the package metadata in a task's crate manifest.
fn parse_rosetta_url<P>(manifest_path: P) -> Result<Url, Error>
where
    P: AsRef<Path>,
{
    let manifest: Value = fs::read_to_string(manifest_path)?.parse()?;

    let url = manifest
        .get("package")
        .and_then(|p| p.get("metadata"))
        .and_then(|m| m.get("rosettacode"))
        .and_then(|m| m.get("url"))
        .and_then(|u| u.as_str())
        .ok_or_else(|| anyhow!("unexpected metadata format"))?;

    Ok(Url::parse(url)?)
}

/// Collect the paths to the source files of a given package.
fn find_sources<P>(directory: P) -> Result<HashSet<PathBuf>, Error>
where
    P: AsRef<Path>,
{
    let mut sources = HashSet::new();

    for entry in WalkDir::new(directory) {
        let entry = entry?;

        if let Some("rs") = entry.path().extension().and_then(|s| s.to_str()) {
            sources.insert(entry.path().to_owned());
        }
    }

    Ok(sources)
}
<|endoftext|>


<commit_before>// vim: tw=80

use mockall::*;
use std::rc::Rc;

#[test]
fn match_eq_ok() {
    let mut e = Expectation::<(i32), ()>::default();
    e.returning(|_| ());
    e.with(predicate::eq(5));
    e.call(5);
}

#[test]
#[should_panic]
fn match_eq_fail() {
    let mut e = Expectation::<(i32), ()>::default();
    e.returning(|_| ());
    e.with(predicate::eq(4));
    e.call(5);
}

#[test]
fn match_fn_ok() {
    let mut e = Expectation::<(i32), ()>::default();
    e.returning(|_| ());
    e.with(predicate::function(|x: &i32| *x == 5));
    e.call(5);
}

#[test]
#[should_panic]
fn match_fn_fail() {
    let mut e = Expectation::<(i32), ()>::default();
    e.returning(|_| ());
    e.with(predicate::function(|x: &i32| *x == 6));
    e.call(5);
}

#[test]
fn match_pointer_args() {
    let mut e = Expectation::<(*const u32), ()>::default();
    e.returning(|_| ());
    unsafe {
        e.withf_unsafe(|x: &*const u32| **x == 6);
    }
    let x = 6u32;
    e.call(&x as *const u32);
}

#[test]
fn params_ok() {
    let mut e = Expectation::<(u32, u32), ()>::default();
    e.returning(|_| ());
    e.with(params!(predicate::eq(5), predicate::eq(6)));
    e.call((5, 6));
}

#[test]
#[should_panic(expected = "Expectation didn't match arguments")]
fn params_fail() {
    let mut e = Expectation::<(u32, u32), ()>::default();
    e.returning(|_| ());
    e.with(params!(predicate::eq(5), predicate::eq(6)));
    e.call((5, 5));
}

/// A MockObject with a method that takes &mut self like:
/// fn foo(&mut self, x: i32) -> u32
#[test]
fn mutable_self() {
    let mut e = Expectation::<(i32), i32>::default();
    let mut count = 0;
    e.returning(move |x| {
            count += x;
            count
        });
    assert_eq!(5, e.call(5));
    assert_eq!(10, e.call(5));
}

/// A mock struct has two different methods with the same name, from different
/// traits.  Neither automock nor mock! can handle this; manual mocking is
/// required.
///
/// The key is changing the ident names used to store the expectations.  Use
/// "traitname_methodname" as the identifier names, and in the expectation
/// methods' names.
mod name_conflict {
    trait Foo {
        fn meth(&self) -> u32;
    }
    trait Bar {
        fn meth(&self) -> u32;
    }

    #[derive(Default)]
    struct MockA {
        foo_meth: ::mockall::Expectation<(), u32>,
        bar_meth: ::mockall::Expectation<(), u32>,
    }
    impl MockA {
        fn expect_foo_meth(&mut self) -> &mut ::mockall::Expectation<(), u32>
        {
            self.foo_meth = ::mockall::Expectation::new();
            &mut self.foo_meth
        }
        fn expect_bar_meth(&mut self) -> &mut ::mockall::Expectation<(), u32>
        {
            self.bar_meth = ::mockall::Expectation::new();
            &mut self.bar_meth
        }
    }
    impl Foo for MockA {
        fn meth(&self) -> u32 {
            self.foo_meth.call(())
        }
    }
    impl Bar for MockA {
        fn meth(&self) -> u32 {
            self.bar_meth.call(())
        }
    }

    #[test]
    fn t() {
        let mut mock = MockA::default();
        mock.expect_foo_meth().returning(|_| 5);
        mock.expect_bar_meth().returning(|_| 6);
        assert_eq!(5, Foo::meth(&mock));
        assert_eq!(6, Bar::meth(&mock));
    }
}

#[test]
fn never_ok() {
    let mut e = Expectation::<(), ()>::default();
    e.returning(|_| ());
    e.never();
}

#[test]
#[should_panic(expected = "Expectation should not have been called")]
fn never_fail() {
    let mut e = Expectation::<(), ()>::default();
    e.returning(|_| ());
    e.never();
    e.call(());
}

/// A MockObject with a method that has no arguments or returns
/// fn foo(&self)
#[test]
fn no_args_or_returns() {
    let mut e = Expectation::<(), ()>::default();
    e.returning(|_| ());
    e.call(());
}

#[test]
fn non_send() {
    let mut e = Expectation::<Rc<u32>, Rc<u32>>::default();
    let y = Rc::new(43u32);
    e.returning_st(move |_| y.clone());
    let x = Rc::new(42u32);
    assert_eq!(43, *e.call(x).as_ref());
}

#[test]
fn non_send_nor_clone() {
    struct MyType(Rc<u32>);
    let mut e = Expectation::<MyType, MyType>::default();
    let y = MyType(Rc::new(43u32));
    e.return_once_st(move |_| y);
    let x = MyType(Rc::new(42u32));
    assert_eq!(43, *e.call(x).0.as_ref());
}

#[test]
fn return_const() {
    let mut e = Expectation::<(), u32>::default();
    e.return_const(42);
    assert_eq!(42, e.call(()));
}

/// Expectations return O::default() unless otherwise specified
#[test]
#[cfg_attr(not(feature = "nightly"), ignore)]
fn return_default() {
    let e = Expectation::<(), u32>::default();
    let r = e.call(());
    assert_eq!(u32::default(), r);
}

/// Can't return default for types that aren't Default
#[test]
#[should_panic]
fn return_default_panics_for_non_default_types() {
    struct NonDefault{}
    let e = Expectation::<(), NonDefault>::default();
    e.call(());
}

#[test]
fn return_owned() {
    struct NonCopy{}
    let mut e = Expectation::<(), NonCopy>::default();
    let r = NonCopy{};
    e.return_once(|_| r);
    e.call(());
}

#[test]
#[should_panic(expected = "expected only once")]
fn return_owned_too_many_times() {
    struct NonCopy{}
    let mut e = Expectation::<(), NonCopy>::default();
    let r = NonCopy{};
    e.return_once(|_| r);
    e.call(());
    e.call(());
}

#[test]
#[should_panic(expected = "exact call count")]
fn sequence_ambiguous() {
    let mut seq = Sequence::new();
    let mut e0 = Expectation::<(), ()>::default();
    e0.times_range(1..3);
    e0.in_sequence(&mut seq);
    e0.call(());
}

#[test]
#[should_panic(expected = "Method sequence violation")]
fn sequence_fail() {
    let mut seq = Sequence::new();
    let mut e0 = Expectation::<(), ()>::default();
    e0.times(1);
    e0.returning(|_| ());
    e0.in_sequence(&mut seq);

    let mut e1 = Expectation::<(), ()>::default();
    e1.times(1);
    e1.returning(|_| ());
    e1.in_sequence(&mut seq);

    e1.call(());
    e0.call(());
}

#[test]
fn sequence_ok() {
    let mut seq = Sequence::new();
    let mut e0 = Expectation::<(), ()>::default();
    e0.times(1);
    e0.returning(|_| ());
    e0.in_sequence(&mut seq);

    let mut e1 = Expectation::<(), ()>::default();
    e1.times(1);
    e1.returning(|_| ());
    e1.in_sequence(&mut seq);

    e0.call(());
    e1.call(());
}

/// A MockObject with a simple method like:
/// fn foo(&self, x: i32) -> u32
#[test]
fn simple_method() {
    let mut e = Expectation::<i32, u32>::default();
    e.returning(|_| 42);
    let r = e.call(5);
    assert_eq!(42, r);
}

/// Mocking static methods requires using globals
mod static_method {
    use std::sync::Mutex;
    use super::*;

    mockall::lazy_static! {
        static ref GLOBAL_EXPECTATIONS: Mutex<Expectations<(i32), u32>> =
            Mutex::new(Expectations::new());
    }

    /// The contorted syntax mimics what mockall_derive does.
    #[test]
    fn t() {
        {
            let mut eguard = {
                let guard = GLOBAL_EXPECTATIONS.lock().unwrap();
                ExpectationGuard::new(guard)
            };
            eguard.returning(|_| 42);
        }

        assert_eq!(42, GLOBAL_EXPECTATIONS.lock().unwrap().call(5));
    }
}

#[test]
fn times_any() {
    let mut e = Expectation::<(), ()>::default();
    e.returning(|_| ());
    e.times(1);
    e.times_any();
    e.call(());
    e.call(());
}

#[test]
fn times_ok() {
    let mut e = Expectation::<(), ()>::default();
    e.returning(|_| ());
    e.times(2);
    e.call(());
    e.call(());
}

#[test]
#[should_panic(expected = "Expectation called fewer than 2 times")]
fn times_too_few() {
    let mut e = Expectation::<(), ()>::default();
    e.returning(|_| ());
    e.times(2);
    e.call(());
}

#[test]
#[should_panic(expected = "Expectation called more than 2 times")]
fn times_too_many() {
    let mut e = Expectation::<(), ()>::default();
    e.returning(|_| ());
    e.times(2);
    e.call(());
    e.call(());
    e.call(());
    // Verify that we panic quickly and don't reach code below this point.
    panic!("Shouldn't get here!");
}

#[test]
fn times_range_ok() {
    let mut e0 = Expectation::<(), ()>::default();
    e0.returning(|_| ());
    e0.times_range(2..4);
    e0.call(());
    e0.call(());

    let mut e1 = Expectation::<(), ()>::default();
    e1.returning(|_| ());
    e1.times_range(2..4);
    e1.call(());
    e1.call(());
    e1.call(());
}

#[test]
#[should_panic(expected = "Expectation called fewer than 2 times")]
fn times_range_too_few() {
    let mut e = Expectation::<(), ()>::default();
    e.returning(|_| ());
    e.times_range(2..4);
    e.call(());
}

#[test]
#[should_panic(expected = "Expectation called more than 3 times")]
fn times_range_too_many() {
    let mut e = Expectation::<(), ()>::default();
    e.returning(|_| ());
    e.times_range(2..4);
    e.call(());
    e.call(());
    e.call(());
    e.call(());
    // Verify that we panic quickly and don't reach code below this point.
    panic!("Shouldn't get here!");
}
<commit_msg>Convert most of the Expectation tests to use expectation!<commit_after>// vim: tw=80

use mockall::*;
use mockall::expectation;
use std::rc::Rc;

#[test]
fn match_eq_ok() {
    expectation!{FooExpectation, __foo_priv, (), [i32], [&x], [x], [p], [i32]}
    let mut e = FooExpectation::default();
    e.returning(|_| ());
    e.with(predicate::eq(5));
    e.call(5);
}

#[test]
#[should_panic]
fn match_eq_fail() {
    expectation!{FooExpectation, __foo_priv, (), [i32], [&x], [x], [p], [i32]}
    let mut e = FooExpectation::default();
    e.returning(|_| ());
    e.with(predicate::eq(4));
    e.call(5);
}

#[test]
fn match_fn_ok() {
    expectation!{FooExpectation, __foo_priv, (), [i32], [&x], [x], [p], [i32]}
    let mut e = FooExpectation::default();
    e.returning(|_| ());
    e.withf(|x: &i32| *x == 5);
    e.call(5);
}

#[test]
#[should_panic]
fn match_fn_fail() {
    expectation!{FooExpectation, __foo_priv, (), [i32], [&x], [x], [p], [i32]}
    let mut e = FooExpectation::default();
    e.returning(|_| ());
    e.withf(|x: &i32| *x == 6);
    e.call(5);
}

//#[test]
//fn match_pointer_args() {
    //let mut e = Expectation::<(*const u32), ()>::default();
    //e.returning(|_| ());
    //unsafe {
        //e.withf_unsafe(|x: &*const u32| **x == 6);
    //}
    //let x = 6u32;
    //e.call(&x as *const u32);
//}

/// A MockObject with a method that takes &mut self like:
/// fn foo(&mut self, x: i32) -> u32
#[test]
fn mutable_self() {
    expectation!{FooExpectation, __foo_priv, i32, [i32], [&x], [x], [p], [i32]}
    let mut e = FooExpectation::default();
    let mut count = 0;
    e.returning(move |x| {
            count += x;
            count
        });
    assert_eq!(5, e.call(5));
    assert_eq!(10, e.call(5));
}

///// A mock struct has two different methods with the same name, from different
///// traits.  Neither automock nor mock! can handle this; manual mocking is
///// required.
/////
///// The key is changing the ident names used to store the expectations.  Use
///// "traitname_methodname" as the identifier names, and in the expectation
///// methods' names.
//mod name_conflict {
    //trait Foo {
        //fn meth(&self) -> u32;
    //}
    //trait Bar {
        //fn meth(&self) -> u32;
    //}

    //#[derive(Default)]
    //struct MockA {
        //foo_meth: ::mockall::Expectation<(), u32>,
        //bar_meth: ::mockall::Expectation<(), u32>,
    //}
    //impl MockA {
        //fn expect_foo_meth(&mut self) -> &mut ::mockall::Expectation<(), u32>
        //{
            //self.foo_meth = ::mockall::Expectation::new();
            //&mut self.foo_meth
        //}
        //fn expect_bar_meth(&mut self) -> &mut ::mockall::Expectation<(), u32>
        //{
            //self.bar_meth = ::mockall::Expectation::new();
            //&mut self.bar_meth
        //}
    //}
    //impl Foo for MockA {
        //fn meth(&self) -> u32 {
            //self.foo_meth.call(())
        //}
    //}
    //impl Bar for MockA {
        //fn meth(&self) -> u32 {
            //self.bar_meth.call(())
        //}
    //}

    //#[test]
    //fn t() {
        //let mut mock = MockA::default();
        //mock.expect_foo_meth().returning(|_| 5);
        //mock.expect_bar_meth().returning(|_| 6);
        //assert_eq!(5, Foo::meth(&mock));
        //assert_eq!(6, Bar::meth(&mock));
    //}
//}

#[test]
fn never_ok() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut e = FooExpectation::default();
    e.returning(|| ());
    e.never();
}

#[test]
#[should_panic(expected = "Expectation should not have been called")]
fn never_fail() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut e = FooExpectation::default();
    e.returning(|| ());
    e.never();
    e.call();
}

/// A MockObject with a method that has no arguments or returns
/// fn foo(&self)
#[test]
fn no_args_or_returns() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut e = FooExpectation::default();
    e.returning(|| ());
    e.call();
}

#[test]
fn non_send() {
    expectation!{
        FooExpectation, __foo_priv, Rc<u32>,
        [Rc<u32>], [&x], [x], [p], [Rc<u32>]
    }
    let mut e = FooExpectation::default();
    let y = Rc::new(43u32);
    e.returning_st(move |_| y.clone());
    let x = Rc::new(42u32);
    assert_eq!(43, *e.call(x).as_ref());
}

pub struct MyType(Rc<u32>);
#[test]
fn non_send_nor_clone() {
    expectation!{
        FooExpectation, __foo_priv, MyType,
        [MyType], [&x], [x], [p], [MyType]
    }
    let mut e = FooExpectation::default();
    let y = MyType(Rc::new(43u32));
    e.return_once_st(move |_| y);
    let x = MyType(Rc::new(42u32));
    assert_eq!(43, *e.call(x).0.as_ref());
}

//#[test]
//fn return_const() {
    //expectation!{ FooExpectation, __foo_priv, u32, [], [], [], [], [] }
    //let mut e = FooExpectation::default();
    //e.return_const(42);
    //assert_eq!(42, e.call());
//}

///// Expectations return O::default() unless otherwise specified
//#[test]
//#[cfg_attr(not(feature = "nightly"), ignore)]
//fn return_default() {
    //let e = Expectation::<(), u32>::default();
    //let r = e.call(());
    //assert_eq!(u32::default(), r);
//}

///// Can't return default for types that aren't Default
//#[test]
//#[should_panic]
//fn return_default_panics_for_non_default_types() {
    //struct NonDefault{}
    //let e = Expectation::<(), NonDefault>::default();
    //e.call(());
//}

pub struct NonCopy{}

#[test]
fn return_owned() {
    expectation!{FooExpectation, __foo_priv, NonCopy, [], [], [], [], []}
    let mut e = FooExpectation::default();
    let r = NonCopy{};
    e.return_once(|| r);
    e.call();
}

#[test]
#[should_panic(expected = "expected only once")]
fn return_owned_too_many_times() {
    expectation!{FooExpectation, __foo_priv, NonCopy, [], [], [], [], []}
    let mut e = FooExpectation::default();
    let r = NonCopy{};
    e.return_once(|| r);
    e.call();
    e.call();
}

#[test]
#[should_panic(expected = "exact call count")]
fn sequence_ambiguous() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut seq = Sequence::new();
    let mut e0 = FooExpectation::default();
    e0.times_range(1..3);
    e0.in_sequence(&mut seq);
    e0.call();
}

#[test]
#[should_panic(expected = "Method sequence violation")]
fn sequence_fail() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut seq = Sequence::new();
    let mut e0 = FooExpectation::default();
    e0.times(1);
    e0.returning(|| ());
    e0.in_sequence(&mut seq);

    let mut e1 = FooExpectation::default();
    e1.times(1);
    e1.returning(|| ());
    e1.in_sequence(&mut seq);

    e1.call();
    e0.call();
}

#[test]
fn sequence_ok() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut seq = Sequence::new();
    let mut e0 = FooExpectation::default();
    e0.times(1);
    e0.returning(|| ());
    e0.in_sequence(&mut seq);

    let mut e1 = FooExpectation::default();
    e1.times(1);
    e1.returning(|| ());
    e1.in_sequence(&mut seq);

    e0.call();
    e1.call();
}

/// A MockObject with a simple method like:
/// fn foo(&self, x: i32) -> u32
#[test]
fn simple_method() {
    expectation!{FooExpectation, __foo_priv, u32, [i32], [&x], [x], [p], [i32]}
    let mut e = FooExpectation::default();
    e.returning(|_| 42);
    let r = e.call(5);
    assert_eq!(42, r);
}

/////// Mocking static methods requires using globals
////mod static_method {
    ////use std::sync::Mutex;
    ////use super::*;

    ////mockall::lazy_static! {
        ////static ref GLOBAL_EXPECTATIONS: Mutex<Expectations<(i32), u32>> =
            ////Mutex::new(Expectations::new());
    ////}

    /////// The contorted syntax mimics what mockall_derive does.
    ////#[test]
    ////fn t() {
        ////{
            ////let mut eguard = {
                ////let guard = GLOBAL_EXPECTATIONS.lock().unwrap();
                ////ExpectationGuard::new(guard)
            ////};
            ////eguard.returning(|_| 42);
        ////}

        ////assert_eq!(42, GLOBAL_EXPECTATIONS.lock().unwrap().call(5));
    ////}
////}

#[test]
fn times_any() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut e = FooExpectation::default();
    e.returning(|| ());
    e.times(1);
    e.times_any();
    e.call();
    e.call();
}

#[test]
fn times_ok() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut e = FooExpectation::default();
    e.returning(|| ());
    e.times(2);
    e.call();
    e.call();
}

#[test]
#[should_panic(expected = "Expectation called fewer than 2 times")]
fn times_too_few() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut e = FooExpectation::default();
    e.returning(|| ());
    e.times(2);
    e.call();
}

#[test]
#[should_panic(expected = "Expectation called more than 2 times")]
fn times_too_many() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut e = FooExpectation::default();
    e.returning(|| ());
    e.times(2);
    e.call();
    e.call();
    e.call();
    // Verify that we panic quickly and don't reach code below this point.
    panic!("Shouldn't get here!");
}

#[test]
fn times_range_ok() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut e0 = FooExpectation::default();
    e0.returning(|| ());
    e0.times_range(2..4);
    e0.call();
    e0.call();

    let mut e1 = FooExpectation::default();
    e1.returning(|| ());
    e1.times_range(2..4);
    e1.call();
    e1.call();
    e1.call();
}

#[test]
#[should_panic(expected = "Expectation called fewer than 2 times")]
fn times_range_too_few() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut e = FooExpectation::default();
    e.returning(|| ());
    e.times_range(2..4);
    e.call();
}

#[test]
#[should_panic(expected = "Expectation called more than 3 times")]
fn times_range_too_many() {
    expectation!{FooExpectation, __foo_priv, (), [], [], [], [], []}
    let mut e = FooExpectation::default();
    e.returning(|| ());
    e.times_range(2..4);
    e.call();
    e.call();
    e.call();
    e.call();
    // Verify that we panic quickly and don't reach code below this point.
    panic!("Shouldn't get here!");
}

mod xxx {
}
<|endoftext|>