<commit_before>// shamelessly taken from https://github.com/nlopes/actix-web-prom
// we are unfortunatly not able to directly use this great crate,
// because  we want to use the anme of the endpoint for retrocompatibility
// (and as a side effect we also added the 'in flight' queries (but for this we could have used the Registry))

use std::marker::PhantomData;
use std::sync::Arc;
use std::time::SystemTime;

use actix_service::{Service, Transform};
use actix_web::{
    dev::{Body, BodySize, MessageBody, ResponseBody, ServiceRequest, ServiceResponse},
    http::{Method, StatusCode},
    web::Bytes,
    Error,
};
use futures::future::{ok, FutureResult};
use futures::{Async, Future, Poll};
use prometheus::{opts, Encoder, TextEncoder};

lazy_static::lazy_static! {
    static ref PATH_TO_NAME: std::collections::HashMap<&'static str, &'static str> = {
        let mut map = std::collections::HashMap::new();
        map.insert("/", "/");
        map.insert("/metrics", "metrics");
        map.insert("/status", "status");
        map.insert("/reverse", "reverse");
        map.insert("/autocomplete", "autocomplete");
        map
    };

    static ref FEATURES_ROUTE: &'static str = "features";
}

fn get_ressource_name(path: &str) -> String {
    // we can't use the ressource's name in the current actix version,
    // so we use an hardcoded associated table
    PATH_TO_NAME
        .get(path)
        .unwrap_or_else(|| {
            if path.starts_with("/features") {
                &FEATURES_ROUTE
            } else {
                &path
            }
        })
        .to_string()
}

lazy_static::lazy_static! {
    static ref HTTP_COUNTER: prometheus::CounterVec = prometheus::register_counter_vec!(
        "bragi_http_requests_total",
        "Total number of HTTP requests made.",
        &["handler", "method", "status"]
    )
    .unwrap();
    static ref HTTP_REQ_HISTOGRAM: prometheus::HistogramVec = prometheus::register_histogram_vec!(
        "bragi_http_request_duration_seconds",
        "The HTTP request latencies in seconds.",
        &["handler", "method"],
        prometheus::exponential_buckets(0.001, 1.5, 25).unwrap()
    )
    .unwrap();
    static ref HTTP_IN_FLIGHT: prometheus::Gauge = prometheus::register_gauge!(
        "bragi_http_requests_in_flight",
        "current number of http request being served"
    )
    .unwrap();
}

#[derive(Clone)]
#[must_use = "must be set up as middleware for actix-web"]
/// By default two metrics are tracked (this assumes the namespace `actix_web_prom`):
///
///   - `actix_web_prom_http_requests_total` (labels: endpoint, method, status): the total
///   number of HTTP requests handled by the actix HttpServer.
///
///   - `actix_web_prom_http_requests_duration_seconds` (labels: endpoint, method,
///    status): the request duration for all HTTP requests handled by the actix
///    HttpServer.
pub struct PrometheusMetrics {
    pub(crate) namespace: String,
    pub(crate) endpoint: String,
}

impl PrometheusMetrics {
    /// Create a new PrometheusMetrics. You set the namespace and the metrics endpoint
    /// through here.
    pub fn new(namespace: &str, endpoint: &str) -> Self {
        PrometheusMetrics {
            namespace: namespace.to_string(),
            endpoint: endpoint.to_string(),
        }
    }

    fn metrics(&self) -> String {
        let mut buffer = vec![];
        TextEncoder::new()
            .encode(&prometheus::gather(), &mut buffer)
            .unwrap();
        String::from_utf8(buffer).unwrap()
    }

    fn matches(&self, path: &str, method: &Method) -> bool {
        self.endpoint == path && method == Method::GET
    }

    fn update_metrics(
        &self,
        handler: &str,
        method: &Method,
        status: StatusCode,
        clock: SystemTime,
    ) {
        let method = method.to_string();
        let status = status.as_u16().to_string();

        if let Ok(elapsed) = clock.elapsed() {
            let duration =
                (elapsed.as_secs() as f64) + f64::from(elapsed.subsec_nanos()) / 1_000_000_000_f64;
            HTTP_REQ_HISTOGRAM
                .with_label_values(&[&handler, &method])
                .observe(duration);
        }

        HTTP_COUNTER
            .with_label_values(&[&handler, &method, &status])
            .inc();

        HTTP_IN_FLIGHT.dec();
    }
}

impl<S, B> Transform<S> for PrometheusMetrics
where
    B: MessageBody,
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse<StreamLog<B>>;
    type Error = Error;
    type InitError = ();
    type Transform = PrometheusMetricsMiddleware<S>;
    type Future = FutureResult<Self::Transform, Self::InitError>;

    fn new_transform(&self, service: S) -> Self::Future {
        ok(PrometheusMetricsMiddleware {
            service,
            inner: Arc::new(self.clone()),
        })
    }
}

#[doc(hidden)]
/// Middleware service for PrometheusMetrics
pub struct PrometheusMetricsMiddleware<S> {
    service: S,
    inner: Arc<PrometheusMetrics>,
}

impl<S, B> Service for PrometheusMetricsMiddleware<S>
where
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: MessageBody,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse<StreamLog<B>>;
    type Error = S::Error;
    type Future = MetricsResponse<S, B>;

    fn poll_ready(&mut self) -> Poll<(), Self::Error> {
        self.service.poll_ready()
    }

    fn call(&mut self, req: ServiceRequest) -> Self::Future {
        MetricsResponse {
            fut: self.service.call(req),
            clock: SystemTime::now(),
            inner: self.inner.clone(),
            _t: PhantomData,
        }
    }
}

#[doc(hidden)]
pub struct MetricsResponse<S, B>
where
    B: MessageBody,
    S: Service,
{
    fut: S::Future,
    clock: SystemTime,
    inner: Arc<PrometheusMetrics>,
    _t: PhantomData<(B,)>,
}

impl<S, B> Future for MetricsResponse<S, B>
where
    B: MessageBody,
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{
    type Item = ServiceResponse<StreamLog<B>>;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        HTTP_IN_FLIGHT.inc();
        let res = futures::try_ready!(self.fut.poll());

        let req = res.request();
        let inner = self.inner.clone();
        let method = req.method().clone();
        let path = req.path().to_string();
        let handler = get_ressource_name(&path);

        Ok(Async::Ready(res.map_body(move |mut head, mut body| {
            // We short circuit the response status and body to serve the endpoint
            // automagically. This way the user does not need to set the middleware *AND*
            // an endpoint to serve middleware results. The user is only required to set
            // the middleware and tell us what the endpoint should be.
            if inner.matches(&path, &method) {
                head.status = StatusCode::OK;
                body = ResponseBody::Other(Body::from_message(inner.metrics()));
            }
            ResponseBody::Body(StreamLog {
                body,
                size: 0,
                clock: self.clock,
                inner,
                status: head.status,
                handler,
                method,
            })
        })))
    }
}

#[doc(hidden)]
pub struct StreamLog<B> {
    body: ResponseBody<B>,
    size: usize,
    clock: SystemTime,
    inner: Arc<PrometheusMetrics>,
    status: StatusCode,
    handler: String,
    method: Method,
}

impl<B> Drop for StreamLog<B> {
    fn drop(&mut self) {
        // update the metrics for this request at the very end of responding
        self.inner
            .update_metrics(&self.handler, &self.method, self.status, self.clock);
    }
}

impl<B: MessageBody> MessageBody for StreamLog<B> {
    fn size(&self) -> BodySize {
        self.body.size()
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        match self.body.poll_next()? {
            Async::Ready(Some(chunk)) => {
                self.size += chunk.len();
                Ok(Async::Ready(Some(chunk)))
            }
            val => Ok(val),
        }
    }
}
<commit_msg>Update libs/bragi/src/prometheus_middleware.rs<commit_after>// shamelessly taken from https://github.com/nlopes/actix-web-prom
// we are unfortunatly not able to directly use this great crate,
// because  we want to use the name of the endpoint for retrocompatibility
// (and as a side effect we also added the 'in flight' queries (but for this we could have used the Registry))

use std::marker::PhantomData;
use std::sync::Arc;
use std::time::SystemTime;

use actix_service::{Service, Transform};
use actix_web::{
    dev::{Body, BodySize, MessageBody, ResponseBody, ServiceRequest, ServiceResponse},
    http::{Method, StatusCode},
    web::Bytes,
    Error,
};
use futures::future::{ok, FutureResult};
use futures::{Async, Future, Poll};
use prometheus::{opts, Encoder, TextEncoder};

lazy_static::lazy_static! {
    static ref PATH_TO_NAME: std::collections::HashMap<&'static str, &'static str> = {
        let mut map = std::collections::HashMap::new();
        map.insert("/", "/");
        map.insert("/metrics", "metrics");
        map.insert("/status", "status");
        map.insert("/reverse", "reverse");
        map.insert("/autocomplete", "autocomplete");
        map
    };

    static ref FEATURES_ROUTE: &'static str = "features";
}

fn get_ressource_name(path: &str) -> String {
    // we can't use the ressource's name in the current actix version,
    // so we use an hardcoded associated table
    PATH_TO_NAME
        .get(path)
        .unwrap_or_else(|| {
            if path.starts_with("/features") {
                &FEATURES_ROUTE
            } else {
                &path
            }
        })
        .to_string()
}

lazy_static::lazy_static! {
    static ref HTTP_COUNTER: prometheus::CounterVec = prometheus::register_counter_vec!(
        "bragi_http_requests_total",
        "Total number of HTTP requests made.",
        &["handler", "method", "status"]
    )
    .unwrap();
    static ref HTTP_REQ_HISTOGRAM: prometheus::HistogramVec = prometheus::register_histogram_vec!(
        "bragi_http_request_duration_seconds",
        "The HTTP request latencies in seconds.",
        &["handler", "method"],
        prometheus::exponential_buckets(0.001, 1.5, 25).unwrap()
    )
    .unwrap();
    static ref HTTP_IN_FLIGHT: prometheus::Gauge = prometheus::register_gauge!(
        "bragi_http_requests_in_flight",
        "current number of http request being served"
    )
    .unwrap();
}

#[derive(Clone)]
#[must_use = "must be set up as middleware for actix-web"]
/// By default two metrics are tracked (this assumes the namespace `actix_web_prom`):
///
///   - `actix_web_prom_http_requests_total` (labels: endpoint, method, status): the total
///   number of HTTP requests handled by the actix HttpServer.
///
///   - `actix_web_prom_http_requests_duration_seconds` (labels: endpoint, method,
///    status): the request duration for all HTTP requests handled by the actix
///    HttpServer.
pub struct PrometheusMetrics {
    pub(crate) namespace: String,
    pub(crate) endpoint: String,
}

impl PrometheusMetrics {
    /// Create a new PrometheusMetrics. You set the namespace and the metrics endpoint
    /// through here.
    pub fn new(namespace: &str, endpoint: &str) -> Self {
        PrometheusMetrics {
            namespace: namespace.to_string(),
            endpoint: endpoint.to_string(),
        }
    }

    fn metrics(&self) -> String {
        let mut buffer = vec![];
        TextEncoder::new()
            .encode(&prometheus::gather(), &mut buffer)
            .unwrap();
        String::from_utf8(buffer).unwrap()
    }

    fn matches(&self, path: &str, method: &Method) -> bool {
        self.endpoint == path && method == Method::GET
    }

    fn update_metrics(
        &self,
        handler: &str,
        method: &Method,
        status: StatusCode,
        clock: SystemTime,
    ) {
        let method = method.to_string();
        let status = status.as_u16().to_string();

        if let Ok(elapsed) = clock.elapsed() {
            let duration =
                (elapsed.as_secs() as f64) + f64::from(elapsed.subsec_nanos()) / 1_000_000_000_f64;
            HTTP_REQ_HISTOGRAM
                .with_label_values(&[&handler, &method])
                .observe(duration);
        }

        HTTP_COUNTER
            .with_label_values(&[&handler, &method, &status])
            .inc();

        HTTP_IN_FLIGHT.dec();
    }
}

impl<S, B> Transform<S> for PrometheusMetrics
where
    B: MessageBody,
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse<StreamLog<B>>;
    type Error = Error;
    type InitError = ();
    type Transform = PrometheusMetricsMiddleware<S>;
    type Future = FutureResult<Self::Transform, Self::InitError>;

    fn new_transform(&self, service: S) -> Self::Future {
        ok(PrometheusMetricsMiddleware {
            service,
            inner: Arc::new(self.clone()),
        })
    }
}

#[doc(hidden)]
/// Middleware service for PrometheusMetrics
pub struct PrometheusMetricsMiddleware<S> {
    service: S,
    inner: Arc<PrometheusMetrics>,
}

impl<S, B> Service for PrometheusMetricsMiddleware<S>
where
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: MessageBody,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse<StreamLog<B>>;
    type Error = S::Error;
    type Future = MetricsResponse<S, B>;

    fn poll_ready(&mut self) -> Poll<(), Self::Error> {
        self.service.poll_ready()
    }

    fn call(&mut self, req: ServiceRequest) -> Self::Future {
        MetricsResponse {
            fut: self.service.call(req),
            clock: SystemTime::now(),
            inner: self.inner.clone(),
            _t: PhantomData,
        }
    }
}

#[doc(hidden)]
pub struct MetricsResponse<S, B>
where
    B: MessageBody,
    S: Service,
{
    fut: S::Future,
    clock: SystemTime,
    inner: Arc<PrometheusMetrics>,
    _t: PhantomData<(B,)>,
}

impl<S, B> Future for MetricsResponse<S, B>
where
    B: MessageBody,
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{
    type Item = ServiceResponse<StreamLog<B>>;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        HTTP_IN_FLIGHT.inc();
        let res = futures::try_ready!(self.fut.poll());

        let req = res.request();
        let inner = self.inner.clone();
        let method = req.method().clone();
        let path = req.path().to_string();
        let handler = get_ressource_name(&path);

        Ok(Async::Ready(res.map_body(move |mut head, mut body| {
            // We short circuit the response status and body to serve the endpoint
            // automagically. This way the user does not need to set the middleware *AND*
            // an endpoint to serve middleware results. The user is only required to set
            // the middleware and tell us what the endpoint should be.
            if inner.matches(&path, &method) {
                head.status = StatusCode::OK;
                body = ResponseBody::Other(Body::from_message(inner.metrics()));
            }
            ResponseBody::Body(StreamLog {
                body,
                size: 0,
                clock: self.clock,
                inner,
                status: head.status,
                handler,
                method,
            })
        })))
    }
}

#[doc(hidden)]
pub struct StreamLog<B> {
    body: ResponseBody<B>,
    size: usize,
    clock: SystemTime,
    inner: Arc<PrometheusMetrics>,
    status: StatusCode,
    handler: String,
    method: Method,
}

impl<B> Drop for StreamLog<B> {
    fn drop(&mut self) {
        // update the metrics for this request at the very end of responding
        self.inner
            .update_metrics(&self.handler, &self.method, self.status, self.clock);
    }
}

impl<B: MessageBody> MessageBody for StreamLog<B> {
    fn size(&self) -> BodySize {
        self.body.size()
    }

    fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
        match self.body.poll_next()? {
            Async::Ready(Some(chunk)) => {
                self.size += chunk.len();
                Ok(Async::Ready(Some(chunk)))
            }
            val => Ok(val),
        }
    }
}
<|endoftext|>


<commit_before>// Venkata-Gautam Kanumuru (vrk7bp)
//
// zhttpto.rs
//
// Final code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Originally coded by Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};

static IP: &'static str = "127.0.0.1";
static PORT:        int = 4414;
static mut visitCount: int = 0;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {

        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {println(format!("Received connection from: [{:s}]", pn.to_str()));},
                                None => ()
                             }
                           },
                None => ()
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            //Gets the contents of the 2nd /, so as to check if it is an empty path or not.
            let splitArray: ~[&str] = request_str.split(' ').collect();
            let path = splitArray[1].slice_from(1).to_owned();
            let testVal = ~"";
            unsafe {
                visitCount = visitCount + 1;
            }

            //Obtain, potentially, the last four characters in the string to check if they are html
            let borrowedPath = path.clone();
            let size = path.len();
            let HTMLTestVal = ~"html";
            let mut isHTML = ~"N/A";
            if(size > 4) {
               isHTML = borrowedPath.slice_from(size-4).to_owned();
            };

            println(format!("Received request :\n{:s}", request_str));

            //First check if there is no directories being accessed. If so then show the original "home screen".
            if (std::str::eq(&path, &testVal)) {
                let response: ~str =
                format!("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Total Server Requests: {:d}

                 \r\n", unsafe{visitCount});
                stream.write(response.as_bytes());
            }

            //Second, check to see if the last four characters in the path are .html. If so, then there are two possible scenarios...
            else if(std::str::eq(&isHTML, &HTMLTestVal)) {
                let tempPath = path.clone();
                let filePath = Path::new(path);

                //The path/document is valid and the particular file will be shown through the browser.
                if(filePath.exists()) {
                    let mut msg_file = File::open(&filePath);
                    let msg_bytes: ~[u8] = msg_file.read_to_end();
                    stream.write(msg_bytes);
                }

                //Otherwise the path/document is not valid and the 403 page will be brought up with the relevant path.
                else {
                    let response: ~str =
                    format!("HTTP/1.1 403 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                    <doctype !html><title>403 Forbidden</title>

 Forbidden

 You don't have permission to access /{:s}

Total Server Requests: {}

                    \r\n", tempPath, unsafe{visitCount});
                    stream.write(response.as_bytes());
                };
            }

            //If none of the above two situations were "met", then show the 403 page with the relevant path.
            else {
                let response: ~str =
                format!("HTTP/1.1 403 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>403 Forbidden</title>

 Forbidden

 You don't have permission to access /{:s}

Total Server Requests: {}

                 \r\n", path, unsafe{visitCount});
                stream.write(response.as_bytes());
            };

            //In the command prompt, print out "Connection terminates." as well as the new page visited number.
            println!("Connection terminates.");
            unsafe {
                println!("This page has been called {} time(s).", visitCount);
            }
        }
    }
}<commit_msg>Changes to the way that HTML files were read in so that the actual results of the code show up in the browser<commit_after>// Venkata-Gautam Kanumuru (vrk7bp)
//
// zhttpto.rs
//
// Final code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Originally coded by Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::io::buffered::BufferedReader;
use std::{str};

static IP: &'static str = "127.0.0.1";
static PORT:        int = 4414;
static mut visitCount: int = 0;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {

        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {println(format!("Received connection from: [{:s}]", pn.to_str()));},
                                None => ()
                             }
                           },
                None => ()
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            //Gets the contents of the 2nd /, so as to check if it is an empty path or not.
            let splitArray: ~[&str] = request_str.split(' ').collect();
            let path = splitArray[1].slice_from(1).to_owned();
            let testVal = ~"";
            unsafe {
                visitCount = visitCount + 1;
            }

            //Obtain, potentially, the last four characters in the string to check if they are html
            let borrowedPath = path.clone();
            let size = path.len();
            let HTMLTestVal = ~"html";
            let mut isHTML = ~"N/A";
            if(size > 4) {
               isHTML = borrowedPath.slice_from(size-4).to_owned();
            };

            println(format!("Received request :\n{:s}", request_str));

            //First check if there is no directories being accessed. If so then show the original "home screen".
            if (std::str::eq(&path, &testVal)) {
                let response: ~str =
                format!("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Total Server Requests: {:d}

                 \r\n", unsafe{visitCount});
                stream.write(response.as_bytes());
            }

            //Second, check to see if the last four characters in the path are .html. If so, then there are two possible scenarios...
            else if(std::str::eq(&isHTML, &HTMLTestVal)) {
                let tempPath = path.clone();
                let filePath = Path::new(path);

                //The path/document is valid and the particular file will be shown through the browser.
                if(filePath.exists()) {
                    let msg_file = File::open(&filePath);
                    let mut fileReader = BufferedReader::new(msg_file);
                    let mut addedPart: ~str = ~"HTTP/1.1 403 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n";

                    for line in fileReader.lines() {
                        addedPart.push_str(line);
                    }

                    stream.write(addedPart.as_bytes());
                }

                //Otherwise the path/document is not valid and the 403 page will be brought up with the relevant path.
                else {
                    let response: ~str =
                    format!("HTTP/1.1 403 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                    <doctype !html><title>403 Forbidden</title>

 Forbidden

 You don't have permission to access /{:s}

Total Server Requests: {}

                    \r\n", tempPath, unsafe{visitCount});
                    stream.write(response.as_bytes());
                };
            }

            //If none of the above two situations were "met", then show the 403 page with the relevant path.
            else {
                let response: ~str =
                format!("HTTP/1.1 403 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>403 Forbidden</title>

 Forbidden

 You don't have permission to access /{:s}

Total Server Requests: {}

                 \r\n", path, unsafe{visitCount});
                stream.write(response.as_bytes());
            };

            //In the command prompt, print out "Connection terminates." as well as the new page visited number.
            println!("Connection terminates.");
            unsafe {
                println!("This page has been called {} time(s).", visitCount);
            }
        }
    }
}<|endoftext|>


<commit_before>// This file is @generated by no_atomic.sh.
// It is not intended for manual editing.

const NO_ATOMIC_CAS: &[&str] = &[
    "avr-unknown-gnu-atmega328",
    "bpfeb-unknown-none",
    "bpfel-unknown-none",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
];
#[allow(dead_code)]
const NO_ATOMIC_64: &[&str] = &[
    "arm-linux-androideabi",
    "armebv7r-none-eabi",
    "armebv7r-none-eabihf",
    "armv4t-unknown-linux-gnueabi",
    "armv5te-unknown-linux-gnueabi",
    "armv5te-unknown-linux-musleabi",
    "armv5te-unknown-linux-uclibceabi",
    "armv7r-none-eabi",
    "armv7r-none-eabihf",
    "hexagon-unknown-linux-musl",
    "mips-unknown-linux-gnu",
    "mips-unknown-linux-musl",
    "mips-unknown-linux-uclibc",
    "mipsel-unknown-linux-gnu",
    "mipsel-unknown-linux-musl",
    "mipsel-unknown-linux-uclibc",
    "mipsel-unknown-none",
    "mipsisa32r6-unknown-linux-gnu",
    "mipsisa32r6el-unknown-linux-gnu",
    "powerpc-unknown-linux-gnu",
    "powerpc-unknown-linux-gnuspe",
    "powerpc-unknown-linux-musl",
    "powerpc-unknown-netbsd",
    "powerpc-unknown-openbsd",
    "powerpc-wrs-vxworks",
    "powerpc-wrs-vxworks-spe",
    "riscv32gc-unknown-linux-gnu",
    "riscv32gc-unknown-linux-musl",
    "riscv32imac-unknown-none-elf",
    "thumbv7em-none-eabi",
    "thumbv7em-none-eabihf",
    "thumbv7m-none-eabi",
    "thumbv8m.base-none-eabi",
    "thumbv8m.main-none-eabi",
    "thumbv8m.main-none-eabihf",
    "mipsel-sony-psp",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
];
#[allow(dead_code)]
const NO_ATOMIC: &[&str] = &[
    "avr-unknown-gnu-atmega328",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
];
<commit_msg>Update list of targets that do not support Atomic*64<commit_after>// This file is @generated by no_atomic.sh.
// It is not intended for manual editing.

const NO_ATOMIC_CAS: &[&str] = &[
    "avr-unknown-gnu-atmega328",
    "bpfeb-unknown-none",
    "bpfel-unknown-none",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
];
#[allow(dead_code)]
const NO_ATOMIC_64: &[&str] = &[
    "arm-linux-androideabi",
    "armebv7r-none-eabi",
    "armebv7r-none-eabihf",
    "armv4t-unknown-linux-gnueabi",
    "armv5te-unknown-linux-gnueabi",
    "armv5te-unknown-linux-musleabi",
    "armv5te-unknown-linux-uclibceabi",
    "armv7r-none-eabi",
    "armv7r-none-eabihf",
    "hexagon-unknown-linux-musl",
    "mips-unknown-linux-gnu",
    "mips-unknown-linux-musl",
    "mips-unknown-linux-uclibc",
    "mipsel-unknown-linux-gnu",
    "mipsel-unknown-linux-musl",
    "mipsel-unknown-linux-uclibc",
    "mipsel-unknown-none",
    "mipsisa32r6-unknown-linux-gnu",
    "mipsisa32r6el-unknown-linux-gnu",
    "powerpc-unknown-freebsd",
    "powerpc-unknown-linux-gnu",
    "powerpc-unknown-linux-gnuspe",
    "powerpc-unknown-linux-musl",
    "powerpc-unknown-netbsd",
    "powerpc-unknown-openbsd",
    "powerpc-wrs-vxworks",
    "powerpc-wrs-vxworks-spe",
    "riscv32gc-unknown-linux-gnu",
    "riscv32gc-unknown-linux-musl",
    "riscv32imac-unknown-none-elf",
    "thumbv7em-none-eabi",
    "thumbv7em-none-eabihf",
    "thumbv7m-none-eabi",
    "thumbv8m.base-none-eabi",
    "thumbv8m.main-none-eabi",
    "thumbv8m.main-none-eabihf",
    "mipsel-sony-psp",
    "thumbv4t-none-eabi",
    "thumbv6m-none-eabi",
];
#[allow(dead_code)]
const NO_ATOMIC: &[&str] = &[
    "avr-unknown-gnu-atmega328",
    "msp430-none-elf",
    "riscv32i-unknown-none-elf",
    "riscv32imc-unknown-none-elf",
];
<|endoftext|>


<commit_before>extern crate gauc;

use gauc::client::*;
use gauc::couchbase::types::error_type::ErrorType;

const DEFAULT_CONNECTION_STRING: &'static str = "couchbase://localhost/default";

#[test]
fn it_connects() {
    let client = Client::new(DEFAULT_CONNECTION_STRING);
    assert!(client.opts.version() == 3);
}

#[test]
fn it_gets_fails_when_getting_nonexisting_document() {
    let mut client = Client::new(DEFAULT_CONNECTION_STRING);

    // Get data
    client.get("non-existing-key", |res| {
        if let Err(response) = res {
            assert!(res.to_string() == "The key does not exist on the server");
        }
    });
}

#[test]
fn it_stores_document() {
    let mut client = Client::new(DEFAULT_CONNECTION_STRING);

    // Store some data
    client.store("foo", "{\"msg\": \"This is test!\"}", |res| {
        if let Ok(response) = res {
            assert!(response.rc == ErrorType::Success);
            println!("Created new document, CAS: {}", response.cas)
        }
    });
}
<commit_msg>Fix tests<commit_after>extern crate gauc;

use gauc::client::*;
use gauc::couchbase::types::error_type::ErrorType;

const DEFAULT_CONNECTION_STRING: &'static str = "couchbase://localhost/default";

#[test]
fn it_connects() {
    let client = Client::new(DEFAULT_CONNECTION_STRING);
    assert!(client.opts.version() == 3);
}

#[test]
fn it_gets_fails_when_getting_nonexisting_document() {
    let mut client = Client::new(DEFAULT_CONNECTION_STRING);

    // Get data
    client.get("non-existing-key", |res| {
        if let Err(response) = res {
            assert!(response.to_string() == "The key does not exist on the server");
        }
    });
}

#[test]
fn it_stores_document() {
    let mut client = Client::new(DEFAULT_CONNECTION_STRING);

    // Store some data
    client.store("foo", "{\"msg\": \"This is test!\"}", |res| {
        if let Ok(response) = res {
            assert!(response.rc == ErrorType::Success);
            println!("Created new document, CAS: {}", response.cas)
        }
    });
}
<|endoftext|>


<commit_before>//! The integration suite helpers.

use regex::Regex;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::collections::HashMap;
use std::str::FromStr;
use std::thread::sleep;
use std::time::Duration;

/// List windows will give details about the active sessions in testing.
/// target: A string represented by the {named_session}:{named_window}
/// tmux list-windows -t TARGET -F '#{window_index}: #{window_name}#{?window_active,*, } (#{window_panes} panes) (Dir: #{pane_current_path}) (Session: #{session_name})'
pub fn list_windows(target: &String) -> String {
    let output = Command::new("tmux")
                     .arg("list-windows")
                     .arg("-t")
                     .arg(target)
                     .arg("-F")
                     .arg("'#{window_index}: #{window_name}#{?window_active,*, } (#{window_panes} panes) (Dir: #{pane_current_path}) (Session: #{session_name})'")
                     .output()
                     .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    String::from_utf8_lossy(&output.stdout).into_owned()
}

pub fn open_muxed(project: &String, project_root: &Path) -> () {
    println!("root: {}", project_root.display());
    let output = Command::new("./target/debug/muxed")
        .arg("-d")
        .arg("-p")
        .arg(format!("{}", project_root.display()))
        .arg(project)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
}

pub fn kill_session(target: &str) -> () {
    Command::new("tmux")
        .arg("kill-session")
        .arg("-t")
        .arg(target)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

pub fn send_keys(target: &String, exec: &String) -> () {
    Command::new("tmux")
        .arg("send-keys")
        .arg("-t")
        .arg(target)
        .arg(exec)
        .arg("KPEnter")
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

pub fn wait_on(file: &PathBuf) -> () {
    while !file.exists() {
        // Wait increased from 10 to 750 due to the pre_window tests.
        sleep(Duration::from_millis(750));
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum SessionValue {
    Usize(usize),
    String(String),
    Empty,
}

impl SessionValue {
    pub fn as_str(&self) -> Option<&str> {
        match self {
            &SessionValue::String(ref s) => Some(s),
            _ => None
        }
    }

    pub fn as_usize(&self) -> Option<usize> {
        match self {
            &SessionValue::Usize(s) => Some(s),
            _ => None
        }
    }
}

#[derive(Debug)]
pub struct TmuxSession {
    pub num_of_windows: usize,
    pub windows: HashMap<String, WindowValues>,
    pub window_active: SessionValue,
    pub name: SessionValue,
}

#[derive(Debug, Clone)]
pub struct WindowValues {
    pub panes: SessionValue,
    pub pane_current_path: SessionValue,
}

static NAME_REGEX:              &'static str = r"\(Session: (.*)\)";
static WINDOW_NAME_REGEX:       &'static str = r":\s(\w*)[$\*-]?\s+\(";
static WINDOW_ACTIVE_REGEX:     &'static str = r"\s(.*)\*";
static PANE_CURRENT_PATH_REGEX: &'static str = r"\(Dir: (.*)\) ";
static PANES_COUNT_REGEX:       &'static str = r"\((\d*) panes\)";

impl TmuxSession {
    pub fn from_string(results: &str) -> TmuxSession {
        let window_name = Regex::new(WINDOW_NAME_REGEX).unwrap();

        let lines: Vec<&str> = results.split('\n').collect();
        let (_, window_lines) = lines.split_last().unwrap();

        let mut windows: HashMap<String, WindowValues> = HashMap::new();

        for line in window_lines {
            let cap = window_name.captures(line).unwrap();
            let name = cap.get(1).unwrap().as_str();

            let win_val = WindowValues{
                panes: TmuxSession::count_panes(line),
                pane_current_path: TmuxSession::retrieve_capture(line, PANE_CURRENT_PATH_REGEX).unwrap_or(SessionValue::Empty)
            };

            windows.insert(name.to_string(), win_val.clone());
        }

        TmuxSession {
          num_of_windows: window_lines.len(),
          windows: windows,
          window_active: TmuxSession::retrieve_capture(window_lines[0], WINDOW_ACTIVE_REGEX).unwrap_or(SessionValue::Empty),
          name: TmuxSession::retrieve_capture(window_lines[0], NAME_REGEX).unwrap_or(SessionValue::Empty)
        }
    }

    pub fn retrieve_capture(line: &str, pattern: &str) -> Result<SessionValue, String> {
        let reg = Regex::new(pattern).unwrap();

        if let Some(caps) = reg.captures(line) {
            return match caps.get(1) {
               Some(x) => Ok(SessionValue::String(x.as_str().to_string())),
               None    => Err("No capture".to_string())
            };
        };

        Err("No capture".to_string())
    }

    pub fn count_panes(line: &str) -> SessionValue {
        let panes = Regex::new(PANES_COUNT_REGEX).unwrap();
        let mut num: &str = "";

        for cap in panes.captures_iter(line) {
            num = match cap.get(1) {
                Some(x) => x.as_str(),
                None    => "0"
            }
        }

        SessionValue::Usize(usize::from_str(num).unwrap())
    }
}

#[test]
fn count_panes_returns_two() {
    let num = TmuxSession::count_panes("1: ssh  (2 panes) (Dir: /Projects/muxed) (session: muxed)");
    assert_eq!(num.as_usize().unwrap(), 2)
}

#[test]
fn count_panes_returns_one() {
    let num = TmuxSession::count_panes("1: ssh  (1 panes) (Dir: /Projects/muxed) (session: muxed)");
    assert_eq!(num.as_usize().unwrap(), 1)
}

#[test]
fn parses_with_trailing_whitespace_after_window_name() {
    let config = "1: ssh  (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_previous_flag() {
    let config = "1: ssh- (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_dollar_sign_flag() {
    let config = "1: ssh$ (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_window_flag() {
    let config = "1: ssh* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn count_three_windows() {
    let config = "1: ssh  (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  2: vim- (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  3: bash* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let num = TmuxSession::from_string(&config.to_string()).num_of_windows;
    assert_eq!(num, 3)
}

#[test]
fn count_four_total_panes() {
    let config = "1: ssh  (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  2: vim- (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  3: bash* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let num = session.windows["ssh"].panes.as_usize().unwrap();
    let num1 = session.windows["vim"].panes.as_usize().unwrap();
    let num2 = session.windows["bash"].panes.as_usize().unwrap();
    assert_eq!(num, 1);
    assert_eq!(num1, 1);
    assert_eq!(num2, 2)
}

#[test]
fn expect_ok_session_name_capture() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_session_name_capture() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session:)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_muxed_to_be_captured_as_session() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "muxed")
}

#[test]
fn expect_ok_window_name_capture() {
    let line = "2: vim1* (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_window_name_capture() {
    let line = "2: (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_vim1_window_name_capture() {
    let line = "2: vim1* (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "vim1")
}

#[test]
fn expect_ok_active_window_capture() {
    let line = "2: vim* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_active_window_capture() {
    let line = "2: vim (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_vim_active_window_capture() {
    let line = "2: vim* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "vim")
}
<commit_msg>refactor(tests): Use str where String is<commit_after>//! The integration suite helpers.

use regex::Regex;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::collections::HashMap;
use std::str::FromStr;
use std::thread::sleep;
use std::time::Duration;

/// List windows will give details about the active sessions in testing.
/// target: A string represented by the {named_session}:{named_window}
/// tmux list-windows -t TARGET -F '#{window_index}: #{window_name}#{?window_active,*, } (#{window_panes} panes) (Dir: #{pane_current_path}) (Session: #{session_name})'
pub fn list_windows(target: &String) -> String {
    let output = Command::new("tmux")
                     .arg("list-windows")
                     .arg("-t")
                     .arg(target)
                     .arg("-F")
                     .arg("'#{window_index}: #{window_name}#{?window_active,*, } (#{window_panes} panes) (Dir: #{pane_current_path}) (Session: #{session_name})'")
                     .output()
                     .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    String::from_utf8_lossy(&output.stdout).into_owned()
}

pub fn open_muxed(project: &str, project_root: &Path) -> () {
    println!("root: {}", project_root.display());
    let output = Command::new("./target/debug/muxed")
        .arg("-d")
        .arg("-p")
        .arg(format!("{}", project_root.display()))
        .arg(project)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
}

pub fn kill_session(target: &str) -> () {
    Command::new("tmux")
        .arg("kill-session")
        .arg("-t")
        .arg(target)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

pub fn send_keys(target: &str, exec: &str) -> () {
    Command::new("tmux")
        .arg("send-keys")
        .arg("-t")
        .arg(target)
        .arg(exec)
        .arg("KPEnter")
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

pub fn wait_on(file: &PathBuf) -> () {
    while !file.exists() {
        // Wait increased from 10 to 750 due to the pre_window tests.
        sleep(Duration::from_millis(750));
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum SessionValue {
    Usize(usize),
    String(String),
    Empty,
}

impl SessionValue {
    pub fn as_str(&self) -> Option<&str> {
        match self {
            &SessionValue::String(ref s) => Some(s),
            _ => None
        }
    }

    pub fn as_usize(&self) -> Option<usize> {
        match self {
            &SessionValue::Usize(s) => Some(s),
            _ => None
        }
    }
}

#[derive(Debug)]
pub struct TmuxSession {
    pub num_of_windows: usize,
    pub windows: HashMap<String, WindowValues>,
    pub window_active: SessionValue,
    pub name: SessionValue,
}

#[derive(Debug, Clone)]
pub struct WindowValues {
    pub panes: SessionValue,
    pub pane_current_path: SessionValue,
}

static NAME_REGEX:              &'static str = r"\(Session: (.*)\)";
static WINDOW_NAME_REGEX:       &'static str = r":\s(\w*)[$\*-]?\s+\(";
static WINDOW_ACTIVE_REGEX:     &'static str = r"\s(.*)\*";
static PANE_CURRENT_PATH_REGEX: &'static str = r"\(Dir: (.*)\) ";
static PANES_COUNT_REGEX:       &'static str = r"\((\d*) panes\)";

impl TmuxSession {
    pub fn from_string(results: &str) -> TmuxSession {
        let window_name = Regex::new(WINDOW_NAME_REGEX).unwrap();

        let lines: Vec<&str> = results.split('\n').collect();
        let (_, window_lines) = lines.split_last().unwrap();

        let mut windows: HashMap<String, WindowValues> = HashMap::new();

        for line in window_lines {
            let cap = window_name.captures(line).unwrap();
            let name = cap.get(1).unwrap().as_str();

            let win_val = WindowValues{
                panes: TmuxSession::count_panes(line),
                pane_current_path: TmuxSession::retrieve_capture(line, PANE_CURRENT_PATH_REGEX).unwrap_or(SessionValue::Empty)
            };

            windows.insert(name.to_string(), win_val.clone());
        }

        TmuxSession {
          num_of_windows: window_lines.len(),
          windows: windows,
          window_active: TmuxSession::retrieve_capture(window_lines[0], WINDOW_ACTIVE_REGEX).unwrap_or(SessionValue::Empty),
          name: TmuxSession::retrieve_capture(window_lines[0], NAME_REGEX).unwrap_or(SessionValue::Empty)
        }
    }

    pub fn retrieve_capture(line: &str, pattern: &str) -> Result<SessionValue, String> {
        let reg = Regex::new(pattern).unwrap();

        if let Some(caps) = reg.captures(line) {
            return match caps.get(1) {
               Some(x) => Ok(SessionValue::String(x.as_str().to_string())),
               None    => Err("No capture".to_string())
            };
        };

        Err("No capture".to_string())
    }

    pub fn count_panes(line: &str) -> SessionValue {
        let panes = Regex::new(PANES_COUNT_REGEX).unwrap();
        let mut num: &str = "";

        for cap in panes.captures_iter(line) {
            num = match cap.get(1) {
                Some(x) => x.as_str(),
                None    => "0"
            }
        }

        SessionValue::Usize(usize::from_str(num).unwrap())
    }
}

#[test]
fn count_panes_returns_two() {
    let num = TmuxSession::count_panes("1: ssh  (2 panes) (Dir: /Projects/muxed) (session: muxed)");
    assert_eq!(num.as_usize().unwrap(), 2)
}

#[test]
fn count_panes_returns_one() {
    let num = TmuxSession::count_panes("1: ssh  (1 panes) (Dir: /Projects/muxed) (session: muxed)");
    assert_eq!(num.as_usize().unwrap(), 1)
}

#[test]
fn parses_with_trailing_whitespace_after_window_name() {
    let config = "1: ssh  (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_previous_flag() {
    let config = "1: ssh- (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_dollar_sign_flag() {
    let config = "1: ssh$ (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_window_flag() {
    let config = "1: ssh* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn count_three_windows() {
    let config = "1: ssh  (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  2: vim- (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  3: bash* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let num = TmuxSession::from_string(&config.to_string()).num_of_windows;
    assert_eq!(num, 3)
}

#[test]
fn count_four_total_panes() {
    let config = "1: ssh  (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  2: vim- (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  3: bash* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let num = session.windows["ssh"].panes.as_usize().unwrap();
    let num1 = session.windows["vim"].panes.as_usize().unwrap();
    let num2 = session.windows["bash"].panes.as_usize().unwrap();
    assert_eq!(num, 1);
    assert_eq!(num1, 1);
    assert_eq!(num2, 2)
}

#[test]
fn expect_ok_session_name_capture() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_session_name_capture() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session:)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_muxed_to_be_captured_as_session() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "muxed")
}

#[test]
fn expect_ok_window_name_capture() {
    let line = "2: vim1* (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_window_name_capture() {
    let line = "2: (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_vim1_window_name_capture() {
    let line = "2: vim1* (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "vim1")
}

#[test]
fn expect_ok_active_window_capture() {
    let line = "2: vim* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_active_window_capture() {
    let line = "2: vim (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_vim_active_window_capture() {
    let line = "2: vim* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "vim")
}
<|endoftext|>


<commit_before>
pub struct Todo {
        id: int,
        todo: ~str,
        priority: char,
        finished: bool,
        raw_todo: ~str,
        contexts: & 'static [~str],
        projects: & 'static [~str]
}

impl Todo {
        pub fn to_str(&self) -> ~str {
                return format!("{:d} {:b} ({:c}) '{:s}' \"{:s}\"",
                                self.id, self.finished, self.priority,
                                self.todo, self.raw_todo)
        }

        pub fn create(todo: ~str, id: int) -> Todo {
                let mut task = Todo{id: id, raw_todo: todo.clone(), todo: ~"",
                                        finished: false, priority: '^',
                                        contexts: &[], projects: &[]};

                if (todo[0] == "x".as_bytes()[0]) {
                        task.finished = true;
                }

                task.todo = todo.clone();

                return task;
        }
}

#[test]
fn simple_todo_create_test() {
        let t = Todo::create(~"some important task", 1);

        assert!(t.id == 1);
        assert!(t.priority == '^');
        assert!(t.finished == false);
        assert!(t.todo == ~"some important task");
        assert!(t.raw_todo == ~"some important task");
}

#[test]
fn todo_to_str_test() {
        let t = Todo::create(~"some important task", 1);

        assert!(t.to_str() == ~"1 false (^) 'some important task' \"some important task\"")
}

fn main () {

        let t = Todo::create(~"some important task", 1);
        println(t.to_str());
        let x = Todo::create(~"x some important task", 1);
        println(x.to_str());
}
<commit_msg>no main in library<commit_after>
pub struct Todo {
        id: int,
        todo: ~str,
        priority: char,
        finished: bool,
        raw_todo: ~str,
        contexts: & 'static [~str],
        projects: & 'static [~str]
}

impl Todo {
        pub fn to_str(&self) -> ~str {
                return format!("{:d} {:b} ({:c}) '{:s}' \"{:s}\"",
                                self.id, self.finished, self.priority,
                                self.todo, self.raw_todo)
        }

        pub fn create(todo: ~str, id: int) -> Todo {
                let mut task = Todo{id: id, raw_todo: todo.clone(), todo: ~"",
                                        finished: false, priority: '^',
                                        contexts: &[], projects: &[]};

                if (todo[0] == "x".as_bytes()[0]) {
                        task.finished = true;
                }

                task.todo = todo.clone();

                return task;
        }
}

#[test]
fn simple_todo_create_test() {
        let t = Todo::create(~"some important task", 1);

        assert!(t.id == 1);
        assert!(t.priority == '^');
        assert!(t.finished == false);
        assert!(t.todo == ~"some important task");
        assert!(t.raw_todo == ~"some important task");
}

#[test]
fn todo_to_str_test() {
        let t = Todo::create(~"some important task", 1);

        assert!(t.to_str() == ~"1 false (^) 'some important task' \"some important task\"")
}
<|endoftext|>


<commit_before>//! `cpuid` intrinsics

#![cfg_attr(feature = "cargo-clippy", allow(stutter))]

use mem;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Result of the `cpuid` instruction.
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let mut r = mem::uninitialized::<CpuidResult>();
    if cfg!(target_arch = "x86") {
        asm!("cpuid"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : :);
    } else {
        // x86-64 uses %rbx as the base register, so preserve it.
        asm!("cpuid\n"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : "rbx" :);
    }
    r
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline]
pub fn has_cpuid() -> bool {
    #[cfg(target_arch = "x86_64")]
    {
        true
    }
    #[cfg(target_arch = "x86")]
    {
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether the 21th bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let eax: i32;
            asm!(r#"
                push %ecx
                pushfd
                pushfd
                pop %eax
                mov %ecx, %eax
                xor %eax, 0x200000
                push %eax
                popfd
                pushfd
                pop %eax
                xor %eax, %ecx
                shrd %eax, 21
                popfd
                pop %ecx
            "#
                 : "={eax}"(eax)  // output operands
                 : // input operands
                 : "memory", "ecx" // clobbers all memory
                 : "volatile"  // has side-effects
            );
            debug_assert!(eax == 0 || eax == 1);
            eax == 1
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

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

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());
    }

    #[cfg(target_arch = "x86")]
    #[test]
    fn test_has_cpuid() {
        unsafe {
            let before = __readeflags();

            if cpuid::has_cpuid() {
                assert!(before != __readeflags());
            } else {
                assert!(before == __readeflags());
            }
        }
    }
}
<commit_msg>fix has_cpuid_test<commit_after>//! `cpuid` intrinsics

#![cfg_attr(feature = "cargo-clippy", allow(stutter))]

use mem;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Result of the `cpuid` instruction.
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub struct CpuidResult {
    /// EAX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub eax: u32,
    /// EBX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ebx: u32,
    /// ECX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub ecx: u32,
    /// EDX register.
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub edx: u32,
}

/// Returns the result of the `cpuid` instruction for a given `leaf` (`EAX`)
/// and
/// `sub_leaf` (`ECX`).
///
/// The highest-supported leaf value is returned by the first tuple argument of
/// [`__get_cpuid_max(0)`](fn.__get_cpuid_max.html). For leaves containung
/// sub-leaves, the second tuple argument returns the highest-supported
/// sub-leaf
/// value.
///
/// The [CPUID Wikipedia page][wiki_cpuid] contains how to query which
/// information using the `EAX` and `ECX` registers, and the interpretation of
/// the results returned in `EAX`, `EBX`, `ECX`, and `EDX`.
///
/// The references are:
/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2:
///   Instruction Set Reference, A-Z][intel64_ref].
/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and
///   System Instructions][amd64_ref].
///
/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
    let mut r = mem::uninitialized::<CpuidResult>();
    if cfg!(target_arch = "x86") {
        asm!("cpuid"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : :);
    } else {
        // x86-64 uses %rbx as the base register, so preserve it.
        asm!("cpuid\n"
             : "={eax}"(r.eax), "={ebx}"(r.ebx), "={ecx}"(r.ecx), "={edx}"(r.edx)
             : "{eax}"(leaf), "{ecx}"(sub_leaf)
             : "rbx" :);
    }
    r
}

/// See [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[cfg_attr(test, assert_instr(cpuid))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __cpuid(leaf: u32) -> CpuidResult {
    __cpuid_count(leaf, 0)
}

/// Does the host support the `cpuid` instruction?
#[inline]
pub fn has_cpuid() -> bool {
    #[cfg(target_arch = "x86_64")]
    {
        true
    }
    #[cfg(target_arch = "x86")]
    {
        unsafe {
            // On `x86` the `cpuid` instruction is not always available.
            // This follows the approach indicated in:
            // http://wiki.osdev.org/CPUID#Checking_CPUID_availability
            // https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
            // which detects whether `cpuid` is available by checking whether the 21th bit of the EFLAGS register is modifiable or not.
            // If it is, then `cpuid` is available.
            let eax: i32;
            asm!(r#"
                push %ecx
                pushfd
                pushfd
                pop %eax
                mov %ecx, %eax
                xor %eax, 0x200000
                push %eax
                popfd
                pushfd
                pop %eax
                xor %eax, %ecx
                shrd %eax, 21
                popfd
                pop %ecx
            "#
                 : "={eax}"(eax)  // output operands
                 : // input operands
                 : "memory", "ecx" // clobbers all memory
                 : "volatile"  // has side-effects
            );
            debug_assert!(eax == 0 || eax == 1);
            eax == 1
        }
    }
}

/// Returns the highest-supported `leaf` (`EAX`) and sub-leaf (`ECX`) `cpuid`
/// values.
///
/// If `cpuid` is supported, and `leaf` is zero, then the first tuple argument
/// contains the highest `leaf` value that `cpuid` supports. For `leaf`s
/// containing sub-leafs, the second tuple argument contains the
/// highest-supported sub-leaf value.
///
/// See also [`__cpuid`](fn.__cpuid.html) and
/// [`__cpuid_count`](fn.__cpuid_count.html).
#[inline]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn __get_cpuid_max(leaf: u32) -> (u32, u32) {
    let CpuidResult { eax, ebx, .. } = __cpuid(leaf);
    (eax, ebx)
}

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

    #[test]
    fn test_always_has_cpuid() {
        // all currently-tested targets have the instruction
        // FIXME: add targets without `cpuid` to CI
        assert!(cpuid::has_cpuid());
    }

    #[test]
    fn test_has_cpuid_idempotent() {
        assert_eq!(cpuid::has_cpuid(), cpuid::has_cpuid());

        let before = __readeflags();
        let _ = cpuid::has_cpuid();
        let after = __readeflags();
        assert_eq!(before, after);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate wlroots;
extern crate libc;

use std::env;
use std::time::Instant;

use wlroots::{CompositorBuilder, CompositorHandle, InputManagerHandler, KeyboardHandle,
              KeyboardHandler, OutputBuilder, OutputBuilderResult, OutputHandle, OutputHandler,
              OutputManagerHandler};
use wlroots::key_events::KeyEvent;
use wlroots::render::{Texture, TextureFormat};
use wlroots::utils::log::{init_logging, WLR_DEBUG};
use wlroots::wlroots_sys::wl_output_transform;
use wlroots::xkbcommon::xkb::keysyms;

const CAT_TEXTURE_WIDTH: u32 = 128;
const CAT_TEXTURE_HEIGHT: u32 = 128;
const CAT_TEXTURE_DATA: &'static [u8] = include_bytes!("cat.data");
const VELOCITY_STEP_DIFF: f32 = 16.0;

struct Vector2 {
    x: f32,
    y: f32,
}
impl Vector2 {
    pub fn increment(&mut self, x: f32, y: f32) {
        self.x += x;
        self.y += y;
    }
}

struct CompositorState {
    cat_texture: Option<Texture<'static>>,
    rotation_transform: wl_output_transform,
    last_frame: Instant,
    offset: Vector2,
    velocity: Vector2,
}
impl CompositorState {
    fn new(rotation_transform: wl_output_transform) -> Self {
        CompositorState { cat_texture: None,
                          rotation_transform,
                          last_frame: Instant::now(),
                          offset: Vector2 {
                              x: 0.0,
                              y: 0.0
                          },
                          velocity: Vector2 {
                              x: 128.0,
                              y: 128.0
                          }}
    }

    /// Registers `now` as the last frame and returns the calculated delta time since the previous last frame in seconds.
    pub fn register_frame(&mut self) -> f32 {
        let now = Instant::now();
        let delta = now.duration_since(self.last_frame);
        self.last_frame = now;
        let seconds_delta = delta.as_secs() as f32;
        let nano_delta = delta.subsec_nanos() as u64;
        let ms = (seconds_delta * 1000.0) + nano_delta as f32 / 1000000.0;
        ms / 1000.0
    }
}

compositor_data!(CompositorState);

struct OutputManager;
impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor_handle: CompositorHandle,
                             output_builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let ex_output = ExOutput;
        let mut result = output_builder.build_best_mode(ex_output);
        with_handles!([(compositor: {compositor_handle}), (output: {&mut result.output})] => {
            let compositor_state: &mut CompositorState = compositor.into();
            output.transform(compositor_state.rotation_transform);
        }).unwrap();
        Some(result)
    }
}

struct ExOutput;
impl OutputHandler for ExOutput {
    fn on_frame(&mut self, mut compositor_handle: CompositorHandle, mut output_handle: OutputHandle) {
        with_handles!([(compositor: {&mut compositor_handle}), (output: {&mut output_handle})] => {
            let (output_width, output_height) = output.effective_resolution();
            let renderer = compositor.renderer
                                    .as_mut()
                                    .expect("Compositor was not loaded with gles2 renderer");
            let compositor_state: &mut CompositorState = (&mut compositor.data).downcast_mut()
                .unwrap();
            let delta_time_in_seconds = compositor_state.register_frame();
            let transform_matrix = output.transform_matrix();
            let mut renderer = renderer.render(output, None);
            let cat_texture = compositor_state.cat_texture.as_ref().unwrap();
            let (max_width, max_height) = (CAT_TEXTURE_WIDTH as i32, CAT_TEXTURE_HEIGHT as i32);
            for y in (-max_height + compositor_state.offset.y as i32..output_height).step_by(max_height as usize) {
                for x in (-max_width + compositor_state.offset.x as i32..output_width).step_by(max_width as usize) {
                    renderer.render_texture(&cat_texture, transform_matrix, x, y, 1.0);
                }
            }
            compositor_state.offset.increment(
                compositor_state.velocity.x * delta_time_in_seconds,
                compositor_state.velocity.y * delta_time_in_seconds
            );
            if compositor_state.offset.x > max_width as f32 {
                compositor_state.offset.x = 0.0
            }
            if compositor_state.offset.y > max_height as f32 {
                compositor_state.offset.y = 0.0
            }
        }).unwrap();
    }
}

struct InputManager;
impl InputManagerHandler for InputManager {
    fn keyboard_added(&mut self,
                      _compositor_handle: CompositorHandle,
                      _keyboard_handle: KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(KeyboardManager))
    }
}

struct KeyboardManager;
impl KeyboardHandler for KeyboardManager {
    fn on_key(&mut self, compositor_handle: CompositorHandle, _keyboard_handle: KeyboardHandle, key_event: &KeyEvent) {
        with_handles!([(compositor: {compositor_handle})] => {
            let compositor_state: &mut CompositorState = (&mut compositor.data).downcast_mut().unwrap();
            for key in key_event.pressed_keys() {
                match key {
                    keysyms::KEY_Escape => wlroots::terminate(),
                    keysyms::KEY_Left => compositor_state.velocity.increment(-VELOCITY_STEP_DIFF, 0.0),
                    keysyms::KEY_Right => compositor_state.velocity.increment(VELOCITY_STEP_DIFF, 0.0),
                    keysyms::KEY_Up => compositor_state.velocity.increment(0.0, -VELOCITY_STEP_DIFF),
                    keysyms::KEY_Down => compositor_state.velocity.increment(0.0, VELOCITY_STEP_DIFF),
                    _ => {}
                }
            }
        }).unwrap();
    }
}

fn rotation_transform_from_str(rotation_str: &str) -> wl_output_transform {
    use wl_output_transform::*;
    match rotation_str {
        "90" => WL_OUTPUT_TRANSFORM_90,
        "180" => WL_OUTPUT_TRANSFORM_180,
        "270" => WL_OUTPUT_TRANSFORM_270,
        "flipped" => WL_OUTPUT_TRANSFORM_FLIPPED,
        "flipped_90" => WL_OUTPUT_TRANSFORM_FLIPPED_90,
        "flipped_180" => WL_OUTPUT_TRANSFORM_FLIPPED_180,
        "flipped_270" => WL_OUTPUT_TRANSFORM_FLIPPED_270,
        _ => WL_OUTPUT_TRANSFORM_NORMAL
    }
}

fn main() {
    init_logging(WLR_DEBUG, None);
    let mut args = env::args();
    let rotation_argument_string = args.nth(1).unwrap_or_else(|| "".to_string());
    let rotation_transform = rotation_transform_from_str(&rotation_argument_string);
    let compositor_state = CompositorState::new(rotation_transform);
    let mut compositor = CompositorBuilder::new().gles2(true)
                                                 .input_manager(Box::new(InputManager))
                                                 .output_manager(Box::new(OutputManager))
                                                 .build_auto(compositor_state);
    {
        let gles2 = &mut compositor.renderer.as_mut().unwrap();
        let compositor_state: &mut CompositorState = (&mut compositor.data).downcast_mut().unwrap();
        compositor_state.cat_texture =
            gles2.create_texture_from_pixels(TextureFormat::ABGR8888.into(),
                                             CAT_TEXTURE_WIDTH * 4,
                                             CAT_TEXTURE_WIDTH,
                                             CAT_TEXTURE_HEIGHT,
                                             CAT_TEXTURE_DATA);
    }
    compositor.run();
}
<commit_msg>Fixed rotation example<commit_after>#[macro_use]
extern crate wlroots;
extern crate libc;

use std::env;
use std::time::Instant;

use wlroots::{CompositorBuilder, CompositorHandle, InputManagerHandler, KeyboardHandle,
              KeyboardHandler, OutputBuilder, OutputBuilderResult, OutputHandle, OutputHandler,
              OutputManagerHandler, Texture, TextureFormat};
use wlroots::key_events::KeyEvent;
use wlroots::utils::log::{init_logging, WLR_DEBUG};
use wlroots::wlroots_sys::wl_output_transform;
use wlroots::xkbcommon::xkb::keysyms;

const CAT_TEXTURE_WIDTH: u32 = 128;
const CAT_TEXTURE_HEIGHT: u32 = 128;
const CAT_TEXTURE_DATA: &'static [u8] = include_bytes!("cat.data");
const VELOCITY_STEP_DIFF: f32 = 16.0;

struct Vector2 {
    x: f32,
    y: f32,
}
impl Vector2 {
    pub fn increment(&mut self, x: f32, y: f32) {
        self.x += x;
        self.y += y;
    }
}

struct CompositorState {
    cat_texture: Option<Texture<'static>>,
    rotation_transform: wl_output_transform,
    last_frame: Instant,
    offset: Vector2,
    velocity: Vector2,
}
impl CompositorState {
    fn new(rotation_transform: wl_output_transform) -> Self {
        CompositorState { cat_texture: None,
                          rotation_transform,
                          last_frame: Instant::now(),
                          offset: Vector2 {
                              x: 0.0,
                              y: 0.0
                          },
                          velocity: Vector2 {
                              x: 128.0,
                              y: 128.0
                          }}
    }

    /// Registers `now` as the last frame and returns the calculated delta time since the previous last frame in seconds.
    pub fn register_frame(&mut self) -> f32 {
        let now = Instant::now();
        let delta = now.duration_since(self.last_frame);
        self.last_frame = now;
        let seconds_delta = delta.as_secs() as f32;
        let nano_delta = delta.subsec_nanos() as u64;
        let ms = (seconds_delta * 1000.0) + nano_delta as f32 / 1000000.0;
        ms / 1000.0
    }
}

compositor_data!(CompositorState);

struct OutputManager;
impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor_handle: CompositorHandle,
                             output_builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let ex_output = ExOutput;
        let mut result = output_builder.build_best_mode(ex_output);
        with_handles!([(compositor: {compositor_handle}), (output: {&mut result.output})] => {
            let compositor_state: &mut CompositorState = compositor.into();
            output.transform(compositor_state.rotation_transform);
        }).unwrap();
        Some(result)
    }
}

struct ExOutput;
impl OutputHandler for ExOutput {
    fn on_frame(&mut self, mut compositor_handle: CompositorHandle, mut output_handle: OutputHandle) {
        with_handles!([(compositor: {&mut compositor_handle}), (output: {&mut output_handle})] => {
            let (output_width, output_height) = output.effective_resolution();
            let renderer = compositor.renderer
                                    .as_mut()
                                    .expect("Compositor was not loaded with gles2 renderer");
            let compositor_state: &mut CompositorState = (&mut compositor.data).downcast_mut()
                .unwrap();
            let delta_time_in_seconds = compositor_state.register_frame();
            let transform_matrix = output.transform_matrix();
            let mut renderer = renderer.render(output, None);
            let cat_texture = compositor_state.cat_texture.as_ref().unwrap();
            let (max_width, max_height) = (CAT_TEXTURE_WIDTH as i32, CAT_TEXTURE_HEIGHT as i32);
            for y in (-max_height + compositor_state.offset.y as i32..output_height).step_by(max_height as usize) {
                for x in (-max_width + compositor_state.offset.x as i32..output_width).step_by(max_width as usize) {
                    renderer.render_texture(&cat_texture, transform_matrix, x, y, 1.0);
                }
            }
            compositor_state.offset.increment(
                compositor_state.velocity.x * delta_time_in_seconds,
                compositor_state.velocity.y * delta_time_in_seconds
            );
            if compositor_state.offset.x > max_width as f32 {
                compositor_state.offset.x = 0.0
            }
            if compositor_state.offset.y > max_height as f32 {
                compositor_state.offset.y = 0.0
            }
        }).unwrap();
    }
}

struct InputManager;
impl InputManagerHandler for InputManager {
    fn keyboard_added(&mut self,
                      _compositor_handle: CompositorHandle,
                      _keyboard_handle: KeyboardHandle)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(KeyboardManager))
    }
}

struct KeyboardManager;
impl KeyboardHandler for KeyboardManager {
    fn on_key(&mut self, compositor_handle: CompositorHandle, _keyboard_handle: KeyboardHandle, key_event: &KeyEvent) {
        with_handles!([(compositor: {compositor_handle})] => {
            let compositor_state: &mut CompositorState = (&mut compositor.data).downcast_mut().unwrap();
            for key in key_event.pressed_keys() {
                match key {
                    keysyms::KEY_Escape => wlroots::terminate(),
                    keysyms::KEY_Left => compositor_state.velocity.increment(-VELOCITY_STEP_DIFF, 0.0),
                    keysyms::KEY_Right => compositor_state.velocity.increment(VELOCITY_STEP_DIFF, 0.0),
                    keysyms::KEY_Up => compositor_state.velocity.increment(0.0, -VELOCITY_STEP_DIFF),
                    keysyms::KEY_Down => compositor_state.velocity.increment(0.0, VELOCITY_STEP_DIFF),
                    _ => {}
                }
            }
        }).unwrap();
    }
}

fn rotation_transform_from_str(rotation_str: &str) -> wl_output_transform {
    use wl_output_transform::*;
    match rotation_str {
        "90" => WL_OUTPUT_TRANSFORM_90,
        "180" => WL_OUTPUT_TRANSFORM_180,
        "270" => WL_OUTPUT_TRANSFORM_270,
        "flipped" => WL_OUTPUT_TRANSFORM_FLIPPED,
        "flipped_90" => WL_OUTPUT_TRANSFORM_FLIPPED_90,
        "flipped_180" => WL_OUTPUT_TRANSFORM_FLIPPED_180,
        "flipped_270" => WL_OUTPUT_TRANSFORM_FLIPPED_270,
        _ => WL_OUTPUT_TRANSFORM_NORMAL
    }
}

fn main() {
    init_logging(WLR_DEBUG, None);
    let mut args = env::args();
    let rotation_argument_string = args.nth(1).unwrap_or_else(|| "".to_string());
    let rotation_transform = rotation_transform_from_str(&rotation_argument_string);
    let compositor_state = CompositorState::new(rotation_transform);
    let mut compositor = CompositorBuilder::new().gles2(true)
                                                 .input_manager(Box::new(InputManager))
                                                 .output_manager(Box::new(OutputManager))
                                                 .build_auto(compositor_state);
    {
        let gles2 = &mut compositor.renderer.as_mut().unwrap();
        let compositor_state: &mut CompositorState = (&mut compositor.data).downcast_mut().unwrap();
        compositor_state.cat_texture =
            gles2.create_texture_from_pixels(TextureFormat::ABGR8888.into(),
                                             CAT_TEXTURE_WIDTH * 4,
                                             CAT_TEXTURE_WIDTH,
                                             CAT_TEXTURE_HEIGHT,
                                             CAT_TEXTURE_DATA);
    }
    compositor.run();
}
<|endoftext|>


<commit_before>use std::io::{self, Write};
use std::thread::sleep;
use std::time::Duration;

use log::{debug, info, trace};

#[cfg(debug_assertions)]
use mio::net::UdpSocket;
use mio::net::{TcpListener, TcpStream};
use mio::{Events, Interests, Poll, Registry, Token};

mod util;

use util::localhost;

const SERVER: Token = Token(0);
const CLIENT: Token = Token(1);

struct TestHandler {
    server: TcpListener,
    client: TcpStream,
    state: usize,
}

impl TestHandler {
    fn new(srv: TcpListener, cli: TcpStream) -> TestHandler {
        TestHandler {
            server: srv,
            client: cli,
            state: 0,
        }
    }

    fn handle_read(&mut self, registry: &Registry, token: Token) {
        match token {
            SERVER => {
                trace!("handle_read; token=SERVER");
                let mut sock = self.server.accept().unwrap().0;
                if let Err(err) = sock.write(b"foobar") {
                    if err.kind() != io::ErrorKind::WouldBlock {
                        panic!("unexpected error writing to connection: {}", err);
                    }
                }
            }
            CLIENT => {
                trace!("handle_read; token=CLIENT");
                assert!(self.state == 0, "unexpected state {}", self.state);
                self.state = 1;
                registry
                    .reregister(&self.client, CLIENT, Interests::WRITABLE)
                    .unwrap();
            }
            _ => panic!("unexpected token"),
        }
    }

    fn handle_write(&mut self, registry: &Registry, token: Token) {
        debug!("handle_write; token={:?}; state={:?}", token, self.state);

        assert!(token == CLIENT, "unexpected token {:?}", token);
        assert!(self.state == 1, "unexpected state {}", self.state);

        self.state = 2;
        registry.deregister(&self.client).unwrap();
        registry.deregister(&self.server).unwrap();
    }
}

#[test]
pub fn test_register_deregister() {
    drop(env_logger::try_init());

    debug!("Starting TEST_REGISTER_DEREGISTER");
    let mut poll = Poll::new().unwrap();
    let mut events = Events::with_capacity(1024);

    let addr = localhost();

    let server = TcpListener::bind(addr).unwrap();

    info!("register server socket");
    poll.registry()
        .register(&server, SERVER, Interests::READABLE)
        .unwrap();

    let client = TcpStream::connect(addr).unwrap();

    // Register client socket only as writable
    poll.registry()
        .register(&client, CLIENT, Interests::READABLE)
        .unwrap();

    let mut handler = TestHandler::new(server, client);

    loop {
        poll.poll(&mut events, None).unwrap();

        if let Some(event) = events.iter().next() {
            if event.is_readable() {
                handler.handle_read(poll.registry(), event.token());
            }

            if event.is_writable() {
                handler.handle_write(poll.registry(), event.token());
                break;
            }
        }
    }

    poll.poll(&mut events, Some(Duration::from_millis(100)))
        .unwrap();
    assert!(events.iter().next().is_none());
}

#[test]
pub fn test_reregister_different_without_poll() {
    let mut events = Events::with_capacity(1024);
    let mut poll = Poll::new().unwrap();

    // Create the listener
    let l = TcpListener::bind("127.0.0.1:0".parse().unwrap()).unwrap();

    // Register the listener with `Poll`
    poll.registry()
        .register(&l, Token(0), Interests::READABLE)
        .unwrap();

    let s1 = TcpStream::connect(l.local_addr().unwrap()).unwrap();
    poll.registry()
        .register(&s1, Token(2), Interests::READABLE)
        .unwrap();

    const TIMEOUT: Duration = Duration::from_millis(1000);
    sleep(TIMEOUT);

    poll.registry()
        .reregister(&l, Token(0), Interests::WRITABLE)
        .unwrap();

    poll.poll(&mut events, Some(TIMEOUT)).unwrap();
    assert!(events.iter().next().is_none());
}

#[test]
#[cfg(debug_assertions)] // Check is only present when debug assertions are enabled.
fn test_tcp_register_multiple_event_loops() {
    let addr = localhost();
    let listener = TcpListener::bind(addr).unwrap();

    let poll1 = Poll::new().unwrap();
    poll1
        .registry()
        .register(
            &listener,
            Token(0),
            Interests::READABLE | Interests::WRITABLE,
        )
        .unwrap();

    let poll2 = Poll::new().unwrap();

    // Try registering the same socket with the initial one
    let res = poll2.registry().register(
        &listener,
        Token(0),
        Interests::READABLE | Interests::WRITABLE,
    );
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);

    // Try cloning the socket and registering it again
    let listener2 = listener.try_clone().unwrap();
    let res = poll2.registry().register(
        &listener2,
        Token(0),
        Interests::READABLE | Interests::WRITABLE,
    );
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);

    // Try the stream
    let stream = TcpStream::connect(addr).unwrap();

    poll1
        .registry()
        .register(&stream, Token(1), Interests::READABLE | Interests::WRITABLE)
        .unwrap();

    let res =
        poll2
            .registry()
            .register(&stream, Token(1), Interests::READABLE | Interests::WRITABLE);
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);

    // Try cloning the socket and registering it again
    let stream2 = stream.try_clone().unwrap();
    let res = poll2.registry().register(
        &stream2,
        Token(1),
        Interests::READABLE | Interests::WRITABLE,
    );
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);
}

#[test]
#[cfg(debug_assertions)] // Check is only present when debug assertions are enabled.
fn test_udp_register_multiple_event_loops() {
    let addr = localhost();
    let socket = UdpSocket::bind(addr).unwrap();

    let poll1 = Poll::new().unwrap();
    poll1
        .registry()
        .register(&socket, Token(0), Interests::READABLE | Interests::WRITABLE)
        .unwrap();

    let poll2 = Poll::new().unwrap();

    // Try registering the same socket with the initial one
    let res =
        poll2
            .registry()
            .register(&socket, Token(0), Interests::READABLE | Interests::WRITABLE);
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);

    // Try cloning the socket and registering it again
    let socket2 = socket.try_clone().unwrap();
    let res = poll2.registry().register(
        &socket2,
        Token(0),
        Interests::READABLE | Interests::WRITABLE,
    );
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);
}
<commit_msg>Add test for registering after de-registering (#1043)<commit_after>use std::io::{self, Write};
use std::thread::sleep;
use std::time::Duration;

use log::{debug, info, trace};

#[cfg(debug_assertions)]
use mio::net::UdpSocket;
use mio::net::{TcpListener, TcpStream};
use mio::{Events, Interests, Poll, Registry, Token};

mod util;

use util::localhost;

const SERVER: Token = Token(0);
const CLIENT: Token = Token(1);

struct TestHandler {
    server: TcpListener,
    client: TcpStream,
    state: usize,
}

impl TestHandler {
    fn new(srv: TcpListener, cli: TcpStream) -> TestHandler {
        TestHandler {
            server: srv,
            client: cli,
            state: 0,
        }
    }

    fn handle_read(&mut self, registry: &Registry, token: Token) {
        match token {
            SERVER => {
                trace!("handle_read; token=SERVER");
                let mut sock = self.server.accept().unwrap().0;
                if let Err(err) = sock.write(b"foobar") {
                    if err.kind() != io::ErrorKind::WouldBlock {
                        panic!("unexpected error writing to connection: {}", err);
                    }
                }
            }
            CLIENT => {
                trace!("handle_read; token=CLIENT");
                assert!(self.state == 0, "unexpected state {}", self.state);
                self.state = 1;
                registry
                    .reregister(&self.client, CLIENT, Interests::WRITABLE)
                    .unwrap();
            }
            _ => panic!("unexpected token"),
        }
    }

    fn handle_write(&mut self, registry: &Registry, token: Token) {
        debug!("handle_write; token={:?}; state={:?}", token, self.state);

        assert!(token == CLIENT, "unexpected token {:?}", token);
        assert!(self.state == 1, "unexpected state {}", self.state);

        self.state = 2;
        registry.deregister(&self.client).unwrap();
        registry.deregister(&self.server).unwrap();
    }
}

#[test]
pub fn test_register_deregister() {
    drop(env_logger::try_init());

    debug!("Starting TEST_REGISTER_DEREGISTER");
    let mut poll = Poll::new().unwrap();
    let mut events = Events::with_capacity(1024);

    let addr = localhost();

    let server = TcpListener::bind(addr).unwrap();

    info!("register server socket");
    poll.registry()
        .register(&server, SERVER, Interests::READABLE)
        .unwrap();

    let client = TcpStream::connect(addr).unwrap();

    // Register client socket only as writable
    poll.registry()
        .register(&client, CLIENT, Interests::READABLE)
        .unwrap();

    let mut handler = TestHandler::new(server, client);

    loop {
        poll.poll(&mut events, None).unwrap();

        if let Some(event) = events.iter().next() {
            if event.is_readable() {
                handler.handle_read(poll.registry(), event.token());
            }

            if event.is_writable() {
                handler.handle_write(poll.registry(), event.token());
                break;
            }
        }
    }

    poll.poll(&mut events, Some(Duration::from_millis(100)))
        .unwrap();
    assert!(events.iter().next().is_none());
}

#[test]
pub fn test_reregister_different_without_poll() {
    let mut events = Events::with_capacity(1024);
    let mut poll = Poll::new().unwrap();

    // Create the listener
    let l = TcpListener::bind("127.0.0.1:0".parse().unwrap()).unwrap();

    // Register the listener with `Poll`
    poll.registry()
        .register(&l, Token(0), Interests::READABLE)
        .unwrap();

    let s1 = TcpStream::connect(l.local_addr().unwrap()).unwrap();
    poll.registry()
        .register(&s1, Token(2), Interests::READABLE)
        .unwrap();

    const TIMEOUT: Duration = Duration::from_millis(1000);
    sleep(TIMEOUT);

    poll.registry()
        .reregister(&l, Token(0), Interests::WRITABLE)
        .unwrap();

    poll.poll(&mut events, Some(TIMEOUT)).unwrap();
    assert!(events.iter().next().is_none());
}

#[test]
#[cfg(debug_assertions)] // Check is only present when debug assertions are enabled.
fn test_tcp_register_multiple_event_loops() {
    let addr = localhost();
    let listener = TcpListener::bind(addr).unwrap();

    let poll1 = Poll::new().unwrap();
    poll1
        .registry()
        .register(
            &listener,
            Token(0),
            Interests::READABLE | Interests::WRITABLE,
        )
        .unwrap();

    let poll2 = Poll::new().unwrap();

    // Try registering the same socket with the initial one
    let res = poll2.registry().register(
        &listener,
        Token(0),
        Interests::READABLE | Interests::WRITABLE,
    );
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);

    // Try cloning the socket and registering it again
    let listener2 = listener.try_clone().unwrap();
    let res = poll2.registry().register(
        &listener2,
        Token(0),
        Interests::READABLE | Interests::WRITABLE,
    );
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);

    // Try the stream
    let stream = TcpStream::connect(addr).unwrap();

    poll1
        .registry()
        .register(&stream, Token(1), Interests::READABLE | Interests::WRITABLE)
        .unwrap();

    let res =
        poll2
            .registry()
            .register(&stream, Token(1), Interests::READABLE | Interests::WRITABLE);
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);

    // Try cloning the socket and registering it again
    let stream2 = stream.try_clone().unwrap();
    let res = poll2.registry().register(
        &stream2,
        Token(1),
        Interests::READABLE | Interests::WRITABLE,
    );
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);
}

#[test]
#[cfg(debug_assertions)] // Check is only present when debug assertions are enabled.
fn test_udp_register_multiple_event_loops() {
    let addr = localhost();
    let socket = UdpSocket::bind(addr).unwrap();

    let poll1 = Poll::new().unwrap();
    poll1
        .registry()
        .register(&socket, Token(0), Interests::READABLE | Interests::WRITABLE)
        .unwrap();

    let poll2 = Poll::new().unwrap();

    // Try registering the same socket with the initial one
    let res =
        poll2
            .registry()
            .register(&socket, Token(0), Interests::READABLE | Interests::WRITABLE);
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);

    // Try cloning the socket and registering it again
    let socket2 = socket.try_clone().unwrap();
    let res = poll2.registry().register(
        &socket2,
        Token(0),
        Interests::READABLE | Interests::WRITABLE,
    );
    assert!(res.is_err());
    assert_eq!(res.unwrap_err().kind(), io::ErrorKind::Other);
}

#[test]
fn test_registering_after_deregistering() {
    drop(env_logger::try_init());

    let mut poll = Poll::new().unwrap();
    let mut events = Events::with_capacity(8);

    let addr = localhost();
    let server = TcpListener::bind(addr).unwrap();

    let registry = poll.registry();

    registry
        .register(&server, SERVER, Interests::READABLE)
        .unwrap();

    registry.deregister(&server).unwrap();

    registry
        .register(&server, SERVER, Interests::READABLE)
        .unwrap();

    poll.poll(&mut events, Some(Duration::from_millis(100)))
        .unwrap();
    assert!(events.is_empty());
}
<|endoftext|>