<commit_before>extern crate redis;

use std::env;
use std::fmt;
use std::error::Error;
use std::default::Default;
use std::time::{SystemTime, UNIX_EPOCH};

use Value;
use rand::{Rng, thread_rng};
use serde::{Serialize, Serializer};
use serde::ser::SerializeStruct;
use serde_json;
use r2d2_redis::RedisConnectionManager;
use r2d2::{Config, Pool, PooledConnection, GetTimeout, InitializationError};

const REDIS_URL_DEFAULT: &'static str = "redis://127.0.0.1/";
pub type RedisPooledConnection = PooledConnection<RedisConnectionManager>;
pub type RedisPool = Pool<RedisConnectionManager>;

#[derive(Debug)]
pub struct ClientError {
    kind: ErrorKind,
}

#[derive(Debug)]
enum ErrorKind {
    Redis(redis::RedisError),
    PoolTimeout(GetTimeout),
    PoolInit(InitializationError),
}

pub fn create_redis_pool() -> Result<RedisPool, ClientError> {
    let config = Config::builder().build();
    let redis_url = &env::var("REDIS_URL").unwrap_or_else(|_| REDIS_URL_DEFAULT.to_owned());
    let url = redis::parse_redis_url(redis_url).unwrap();
    let manager = RedisConnectionManager::new(url).unwrap();
    Pool::new(config, manager).map_err(|err| ClientError { kind: ErrorKind::PoolInit(err) })
}

pub struct Job {
    pub class: String,
    pub args: Vec<Value>,
    pub retry: i64,
    pub queue: String,
    pub jid: String,
    pub created_at: u64,
    pub enqueued_at: u64,
}

impl fmt::Display for ClientError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            ErrorKind::Redis(ref err) => err.fmt(f),
            ErrorKind::PoolTimeout(ref err) => err.fmt(f),
            ErrorKind::PoolInit(ref err) => err.fmt(f),
        }
    }
}

impl Error for ClientError {
    fn description(&self) -> &str {
        match self.kind {
            ErrorKind::Redis(ref err) => err.description(),
            ErrorKind::PoolTimeout(ref err) => err.description(),
            ErrorKind::PoolInit(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self.kind {
            ErrorKind::Redis(ref err) => Some(err),
            ErrorKind::PoolTimeout(ref err) => Some(err),
            ErrorKind::PoolInit(ref err) => Some(err),
        }
    }
}

impl From<redis::RedisError> for ClientError {
    fn from(error: redis::RedisError) -> ClientError {
        ClientError { kind: ErrorKind::Redis(error) }
    }
}

impl From<GetTimeout> for ClientError {
    fn from(error: GetTimeout) -> ClientError {
        ClientError { kind: ErrorKind::PoolTimeout(error) }
    }
}

impl From<InitializationError> for ClientError {
    fn from(error: InitializationError) -> ClientError {
        ClientError { kind: ErrorKind::PoolInit(error) }
    }
}

impl Default for JobOpts {
    fn default() -> JobOpts {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs() as u64;
        let jid = thread_rng().gen_ascii_chars().take(24).collect::<String>();
        JobOpts {
            retry: 25,
            queue: "default".to_string(),
            jid: jid,
            created_at: now,
            enqueued_at: now,
        }
    }
}

pub struct JobOpts {
    pub retry: i64,
    pub queue: String,
    pub jid: String,
    pub created_at: u64,
    pub enqueued_at: u64,
}

/// # Examples
///
/// ```
/// use std::default::Default;
/// use sidekiq::Value;
/// use sidekiq::{Job, JobOpts};
///
/// // Create a job
/// let class = "MyClass".to_string();
/// let job_opts = JobOpts {
///     queue: "test".to_string(),
///     ..Default::default()
/// };
/// let job = Job::new(class, vec![sidekiq::Value::Null], job_opts);
/// ```
impl Job {
    pub fn new(class: String, args: Vec<Value>, opts: JobOpts) -> Job {
        Job {
            class: class,
            args: args,
            retry: opts.retry,
            queue: opts.queue,
            jid: opts.jid,
            created_at: opts.created_at,
            enqueued_at: opts.enqueued_at,
        }
    }
}

impl Serialize for Job {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        let mut s = try!(serializer.serialize_struct("Job", 7));
        try!(s.serialize_field("class", &self.class));
        try!(s.serialize_field("args", &self.args));
        try!(s.serialize_field("retry", &self.retry));
        try!(s.serialize_field("queue", &self.queue));
        try!(s.serialize_field("jid", &self.jid));
        try!(s.serialize_field("created_at", &self.created_at));
        try!(s.serialize_field("enqueued_at", &self.enqueued_at));
        s.end()
    }
}

pub struct ClientOpts {
    pub namespace: Option<String>,
}

impl Default for ClientOpts {
    fn default() -> ClientOpts {
        ClientOpts { namespace: None }
    }
}

pub struct Client {
    pub redis_pool: RedisPool,
    pub namespace: Option<String>,
}

/// # Examples
///
/// ```
///
/// use sidekiq::{Job, Value};
/// use sidekiq::{Client, ClientOpts, create_redis_pool};
///
/// let ns = "test";
/// let client_opts = ClientOpts {
///     namespace: Some(ns.to_string()),
///     ..Default::default()
/// };
/// let pool = create_redis_pool().unwrap();
/// let client = Client::new(pool, client_opts);
/// let class = "MyClass".to_string();
/// let job = Job::new(class, vec![sidekiq::Value::Null], Default::default());
/// match client.push(job) {
///     Ok(_) => {},
///     Err(err) => {
///         println!("Sidekiq push failed: {}", err);
///     },
/// }
/// ```
impl Client {
    pub fn new(redis_pool: RedisPool, opts: ClientOpts) -> Client {
        Client {
            redis_pool: redis_pool,
            namespace: opts.namespace,
        }
    }

    fn connect(&self) -> Result<RedisPooledConnection, ClientError> {
        match self.redis_pool.get() {
            Ok(conn) => Ok(conn),
            Err(err) => Err(ClientError { kind: ErrorKind::PoolTimeout(err) }),
        }
    }

    pub fn push(&self, job: Job) -> Result<(), ClientError> {
        self.raw_push(vec![job])
    }

    pub fn push_bulk(&self, jobs: Vec<Job>) -> Result<(), ClientError> {
        self.raw_push(jobs)
    }

    fn raw_push(&self, payloads: Vec<Job>) -> Result<(), ClientError> {
        let payload = &payloads[0];
        let to_push =
            payloads.iter().map(|entry| serde_json::to_string(&entry).unwrap()).collect::<Vec<_>>();
        match self.connect() {
            Ok(conn) => {
                redis::pipe()
                    .atomic()
                    .cmd("SADD")
                    .arg("queues")
                    .arg(payload.queue.to_string())
                    .ignore()
                    .cmd("LPUSH")
                    .arg(self.queue_name(&payload.queue))
                    .arg(to_push)
                    .query(&*conn)
                    .map_err(|err| ClientError { kind: ErrorKind::Redis(err) })
            }
            Err(err) => Err(err),
        }
    }

    fn queue_name(&self, queue: &str) -> String {
        if let Some(ref ns) = self.namespace {
            format!("{}:queue:{}", ns, queue)
        } else {
            format!("queue:{}", queue)
        }
    }
}
<commit_msg>Add REDIS_URL_ENV const<commit_after>extern crate redis;

use std::env;
use std::fmt;
use std::error::Error;
use std::default::Default;
use std::time::{SystemTime, UNIX_EPOCH};

use Value;
use rand::{Rng, thread_rng};
use serde::{Serialize, Serializer};
use serde::ser::SerializeStruct;
use serde_json;
use r2d2_redis::RedisConnectionManager;
use r2d2::{Config, Pool, PooledConnection, GetTimeout, InitializationError};

const REDIS_URL_ENV: &'static str = "REDIS_URL";
const REDIS_URL_DEFAULT: &'static str = "redis://127.0.0.1/";
pub type RedisPooledConnection = PooledConnection<RedisConnectionManager>;
pub type RedisPool = Pool<RedisConnectionManager>;

#[derive(Debug)]
pub struct ClientError {
    kind: ErrorKind,
}

#[derive(Debug)]
enum ErrorKind {
    Redis(redis::RedisError),
    PoolTimeout(GetTimeout),
    PoolInit(InitializationError),
}

pub fn create_redis_pool() -> Result<RedisPool, ClientError> {
    let config = Config::builder().build();
    let redis_url = &env::var(&REDIS_URL_ENV.to_owned()).unwrap_or_else(|_| REDIS_URL_DEFAULT.to_owned());
    let url = redis::parse_redis_url(redis_url).unwrap();
    let manager = RedisConnectionManager::new(url).unwrap();
    Pool::new(config, manager).map_err(|err| ClientError { kind: ErrorKind::PoolInit(err) })
}

pub struct Job {
    pub class: String,
    pub args: Vec<Value>,
    pub retry: i64,
    pub queue: String,
    pub jid: String,
    pub created_at: u64,
    pub enqueued_at: u64,
}

impl fmt::Display for ClientError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            ErrorKind::Redis(ref err) => err.fmt(f),
            ErrorKind::PoolTimeout(ref err) => err.fmt(f),
            ErrorKind::PoolInit(ref err) => err.fmt(f),
        }
    }
}

impl Error for ClientError {
    fn description(&self) -> &str {
        match self.kind {
            ErrorKind::Redis(ref err) => err.description(),
            ErrorKind::PoolTimeout(ref err) => err.description(),
            ErrorKind::PoolInit(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self.kind {
            ErrorKind::Redis(ref err) => Some(err),
            ErrorKind::PoolTimeout(ref err) => Some(err),
            ErrorKind::PoolInit(ref err) => Some(err),
        }
    }
}

impl From<redis::RedisError> for ClientError {
    fn from(error: redis::RedisError) -> ClientError {
        ClientError { kind: ErrorKind::Redis(error) }
    }
}

impl From<GetTimeout> for ClientError {
    fn from(error: GetTimeout) -> ClientError {
        ClientError { kind: ErrorKind::PoolTimeout(error) }
    }
}

impl From<InitializationError> for ClientError {
    fn from(error: InitializationError) -> ClientError {
        ClientError { kind: ErrorKind::PoolInit(error) }
    }
}

impl Default for JobOpts {
    fn default() -> JobOpts {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs() as u64;
        let jid = thread_rng().gen_ascii_chars().take(24).collect::<String>();
        JobOpts {
            retry: 25,
            queue: "default".to_string(),
            jid: jid,
            created_at: now,
            enqueued_at: now,
        }
    }
}

pub struct JobOpts {
    pub retry: i64,
    pub queue: String,
    pub jid: String,
    pub created_at: u64,
    pub enqueued_at: u64,
}

/// # Examples
///
/// ```
/// use std::default::Default;
/// use sidekiq::Value;
/// use sidekiq::{Job, JobOpts};
///
/// // Create a job
/// let class = "MyClass".to_string();
/// let job_opts = JobOpts {
///     queue: "test".to_string(),
///     ..Default::default()
/// };
/// let job = Job::new(class, vec![sidekiq::Value::Null], job_opts);
/// ```
impl Job {
    pub fn new(class: String, args: Vec<Value>, opts: JobOpts) -> Job {
        Job {
            class: class,
            args: args,
            retry: opts.retry,
            queue: opts.queue,
            jid: opts.jid,
            created_at: opts.created_at,
            enqueued_at: opts.enqueued_at,
        }
    }
}

impl Serialize for Job {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        let mut s = try!(serializer.serialize_struct("Job", 7));
        try!(s.serialize_field("class", &self.class));
        try!(s.serialize_field("args", &self.args));
        try!(s.serialize_field("retry", &self.retry));
        try!(s.serialize_field("queue", &self.queue));
        try!(s.serialize_field("jid", &self.jid));
        try!(s.serialize_field("created_at", &self.created_at));
        try!(s.serialize_field("enqueued_at", &self.enqueued_at));
        s.end()
    }
}

pub struct ClientOpts {
    pub namespace: Option<String>,
}

impl Default for ClientOpts {
    fn default() -> ClientOpts {
        ClientOpts { namespace: None }
    }
}

pub struct Client {
    pub redis_pool: RedisPool,
    pub namespace: Option<String>,
}

/// # Examples
///
/// ```
///
/// use sidekiq::{Job, Value};
/// use sidekiq::{Client, ClientOpts, create_redis_pool};
///
/// let ns = "test";
/// let client_opts = ClientOpts {
///     namespace: Some(ns.to_string()),
///     ..Default::default()
/// };
/// let pool = create_redis_pool().unwrap();
/// let client = Client::new(pool, client_opts);
/// let class = "MyClass".to_string();
/// let job = Job::new(class, vec![sidekiq::Value::Null], Default::default());
/// match client.push(job) {
///     Ok(_) => {},
///     Err(err) => {
///         println!("Sidekiq push failed: {}", err);
///     },
/// }
/// ```
impl Client {
    pub fn new(redis_pool: RedisPool, opts: ClientOpts) -> Client {
        Client {
            redis_pool: redis_pool,
            namespace: opts.namespace,
        }
    }

    fn connect(&self) -> Result<RedisPooledConnection, ClientError> {
        match self.redis_pool.get() {
            Ok(conn) => Ok(conn),
            Err(err) => Err(ClientError { kind: ErrorKind::PoolTimeout(err) }),
        }
    }

    pub fn push(&self, job: Job) -> Result<(), ClientError> {
        self.raw_push(vec![job])
    }

    pub fn push_bulk(&self, jobs: Vec<Job>) -> Result<(), ClientError> {
        self.raw_push(jobs)
    }

    fn raw_push(&self, payloads: Vec<Job>) -> Result<(), ClientError> {
        let payload = &payloads[0];
        let to_push =
            payloads.iter().map(|entry| serde_json::to_string(&entry).unwrap()).collect::<Vec<_>>();
        match self.connect() {
            Ok(conn) => {
                redis::pipe()
                    .atomic()
                    .cmd("SADD")
                    .arg("queues")
                    .arg(payload.queue.to_string())
                    .ignore()
                    .cmd("LPUSH")
                    .arg(self.queue_name(&payload.queue))
                    .arg(to_push)
                    .query(&*conn)
                    .map_err(|err| ClientError { kind: ErrorKind::Redis(err) })
            }
            Err(err) => Err(err),
        }
    }

    fn queue_name(&self, queue: &str) -> String {
        if let Some(ref ns) = self.namespace {
            format!("{}:queue:{}", ns, queue)
        } else {
            format!("queue:{}", queue)
        }
    }
}
<|endoftext|>


<commit_before>fn main() {
    let v: Vec<u8> = vec![1, 2];
    let x = unsafe { *v.as_ptr().wrapping_offset(5) }; //~ ERROR constant evaluation error
    //~^ NOTE memory access at offset 6, outside bounds of allocation
    panic!("this should never print: {}", x);
}
<commit_msg>fix test for rustup<commit_after>fn main() {
    let v: Vec<u8> = vec![1, 2];
    let x = unsafe { *v.as_ptr().wrapping_offset(5) }; //~ ERROR constant evaluation error
    //~^ NOTE outside bounds of allocation
    panic!("this should never print: {}", x);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! TLS protocol related components for DNS over TLS

extern crate futures;
extern crate native_tls;
#[cfg(target_os = "linux")]
extern crate openssl;
extern crate tokio_core;
extern crate tokio_tls;
extern crate trust_dns;

pub mod tls_client_connection;
pub mod tls_client_stream;
pub mod tls_stream;

pub use self::tls_client_connection::{TlsClientConnection, TlsClientConnectionBuilder};
pub use self::tls_client_stream::{TlsClientStream, TlsClientStreamBuilder};
pub use self::tls_stream::{TlsStream, TlsStreamBuilder};

#[cfg(test)]
mod tests;<commit_msg>remove extern openssl on linux in native-tls<commit_after>/*
 * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! TLS protocol related components for DNS over TLS

extern crate futures;
extern crate native_tls;
extern crate tokio_core;
extern crate tokio_tls;
extern crate trust_dns;

pub mod tls_client_connection;
pub mod tls_client_stream;
pub mod tls_stream;

pub use self::tls_client_connection::{TlsClientConnection, TlsClientConnectionBuilder};
pub use self::tls_client_stream::{TlsClientStream, TlsClientStreamBuilder};
pub use self::tls_stream::{TlsStream, TlsStreamBuilder};

#[cfg(test)]
mod tests;<|endoftext|>


<commit_before><commit_msg>Add a version of applies_to that corresponds to the TreeExtent::ThisNode extent<commit_after><|endoftext|>


<commit_before><commit_msg>When a node is replaced, we need to search using the updated tree rather than the original tree. Use a 'fake' root to simulate this (doesn't work if address of the change specifies a sibling other than the first)<commit_after><|endoftext|>


<commit_before>use crate::Mesh;
use std::fs::File;
use std::io::{BufRead, BufReader};

struct ReadMeshData {
    ndim: usize,
    npoint: usize,
    ncell: usize,
    current_npoint: usize,
    current_ncell: usize,
    point_id: usize,
    point_group: usize,
    point_x: f64,
    point_y: f64,
    point_z: f64,
}

impl ReadMeshData {
    fn new() -> Self {
        ReadMeshData {
            ndim: 0,
            npoint: 0,
            ncell: 0,
            current_npoint: 0,
            current_ncell: 0,
            point_id: 0,
            point_group: 0,
            point_x: 0.0,
            point_y: 0.0,
            point_z: 0.0,
        }
    }

    fn parse_sizes(&mut self, line: &String) -> Result<bool, &'static str> {
        let maybe_data = line.trim_start().trim_end_matches("\n");
        if maybe_data.starts_with("#") || maybe_data == "" {
            return Ok(false); // ignore comments or empty lines; returns false == not parsed
        }

        let mut data = maybe_data.split_whitespace();

        self.ndim = data
            .next()
            .unwrap() // must panic because no error expected here
            .parse()
            .map_err(|_| "cannot parse ndim")?;

        match data.next() {
            Some(v) => self.npoint = v.parse().map_err(|_| "cannot parse npoint")?,
            None => return Err("cannot read npoint"),
        };

        match data.next() {
            Some(v) => self.ncell = v.parse().map_err(|_| "cannot parse ncell")?,
            None => return Err("cannot read ncell"),
        };

        Ok(true) // returns true == parsed
    }

    fn parse_point(&mut self, line: &String) -> Result<bool, &'static str> {
        let maybe_data = line.trim_start().trim_end_matches("\n");
        if maybe_data.starts_with("#") || maybe_data == "" {
            return Ok(false); // ignore comments or empty lines
        }

        let mut data = maybe_data.split_whitespace();

        self.point_id = data
            .next()
            .unwrap() // must panic because no error expected here
            .parse()
            .map_err(|_| "cannot parse point id")?;

        if self.point_id != self.current_npoint {
            return Err("the id and index of points must equal each other");
        }

        match data.next() {
            Some(v) => self.point_group = v.parse().map_err(|_| "cannot parse point group")?,
            None => return Err("cannot read point group"),
        };

        match data.next() {
            Some(v) => self.point_x = v.parse().map_err(|_| "cannot parse point x coordinate")?,
            None => return Err("cannot read point x coordinate"),
        };

        match data.next() {
            Some(v) => self.point_y = v.parse().map_err(|_| "cannot parse point y coordinate")?,
            None => return Err("cannot read point y coordinate"),
        };

        if self.ndim == 3 {
            match data.next() {
                Some(v) => self.point_z = v.parse().map_err(|_| "cannot parse point z coordinate")?,
                None => return Err("cannot read point z coordinate"),
            };
        }

        self.current_npoint += 1; // next point

        Ok(true) // returns true == parsed
    }
}

pub fn read_mesh(filepath: &String) -> Result<Mesh, &'static str> {
    let input = File::open(filepath).map_err(|_| "cannot open file")?;
    let buffered = BufReader::new(input);
    let mut lines_iter = buffered.lines();

    // auxiliary data structure
    let mut data = ReadMeshData::new();

    // read and parse sizes
    loop {
        match lines_iter.next() {
            Some(v) => {
                let line = v.unwrap(); // must panic because no error expected here
                if data.parse_sizes(&line)? {
                    break;
                }
            }
            None => return Err("file is empty or header is missing"),
        }
    }

    // allocate mesh
    let mut mesh = Mesh::new_zeroed(data.ndim, data.npoint, data.ncell)?;

    // read and parse points
    loop {
        match lines_iter.next() {
            Some(v) => {
                let line = v.unwrap(); // must panic because no error expected here
                if data.parse_point(&line)? {
                    let index = data.point_id;
                    mesh.points[index].id = data.point_id;
                    mesh.points[index].group = data.point_group;
                    mesh.points[index].coords[0] = data.point_x;
                    mesh.points[index].coords[1] = data.point_y;
                    if data.ndim == 3 {
                        mesh.points[data.point_id].coords[2] = data.point_z;
                    }
                    if data.current_npoint == data.npoint {
                        break;
                    }
                }
            }
            None => break,
        }
    }

    // check data
    if data.current_npoint != data.npoint {
        return Err("not all points have been found");
    }

    // read and parse cells

    // done
    Ok(mesh)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{read_mesh, ReadMeshData};

    #[test]
    fn parse_sizes_captures_errors() -> Result<(), &'static str> {
        let mut data = ReadMeshData::new();

        assert_eq!(
            data.parse_sizes(&String::from(" wrong \n")).err(),
            Some("cannot parse ndim")
        );

        assert_eq!(
            data.parse_sizes(&String::from(" 2 \n")).err(),
            Some("cannot read npoint")
        );
        assert_eq!(
            data.parse_sizes(&String::from(" 1 wrong")).err(),
            Some("cannot parse npoint")
        );

        assert_eq!(
            data.parse_sizes(&String::from(" 2 4   \n")).err(),
            Some("cannot read ncell")
        );
        assert_eq!(
            data.parse_sizes(&String::from(" 2 4  wrong")).err(),
            Some("cannot parse ncell")
        );
        Ok(())
    }

    #[test]
    fn parse_point_captures_errors() -> Result<(), &'static str> {
        let mut data = ReadMeshData::new();
        data.ndim = 3;
        data.npoint = 2;
        data.ncell = 1;

        assert_eq!(
            data.parse_point(&String::from(" wrong \n")).err(),
            Some("cannot parse point id")
        );

        assert_eq!(
            data.parse_point(&String::from(" 2 1 0.0 0.0 0.0 \n")).err(),
            Some("the id and index of points must equal each other")
        );

        assert_eq!(
            data.parse_point(&String::from(" 0 \n")).err(),
            Some("cannot read point group")
        );
        assert_eq!(
            data.parse_point(&String::from(" 0 wrong")).err(),
            Some("cannot parse point group")
        );

        assert_eq!(
            data.parse_point(&String::from(" 0 1   \n")).err(),
            Some("cannot read point x coordinate")
        );
        assert_eq!(
            data.parse_point(&String::from(" 0 1  wrong")).err(),
            Some("cannot parse point x coordinate")
        );

        assert_eq!(
            data.parse_point(&String::from(" 0 1 0.0  \n")).err(),
            Some("cannot read point y coordinate")
        );
        assert_eq!(
            data.parse_point(&String::from(" 0 1 0.0 wrong")).err(),
            Some("cannot parse point y coordinate")
        );

        assert_eq!(
            data.parse_point(&String::from(" 0 1 0.0 0.0 \n")).err(),
            Some("cannot read point z coordinate")
        );
        assert_eq!(
            data.parse_point(&String::from(" 0 1 0.0 0.0 wrong")).err(),
            Some("cannot parse point z coordinate")
        );
        Ok(())
    }

    #[test]
    fn read_mesh_handle_wrong_files() -> Result<(), &'static str> {
        assert_eq!(read_mesh(&String::from("__wrong__")).err(), Some("cannot open file"));
        assert_eq!(
            read_mesh(&String::from("./data/meshes/bad_empty.msh")).err(),
            Some("file is empty or header is missing")
        );
        assert_eq!(
            read_mesh(&String::from("./data/meshes/bad_missing_header.msh")).err(),
            Some("file is empty or header is missing")
        );
        assert_eq!(
            read_mesh(&String::from("./data/meshes/bad_missing_points.msh")).err(),
            Some("not all points have been found")
        );
        /*
        assert_eq!(
            read_mesh(&String::from("./data/meshes/bad_many_points.msh")).err(),
            Some("there are more points than specified")
        );
        */
        Ok(())
    }

    #[test]
    fn read_mesh_works() -> Result<(), &'static str> {
        let filepath = "./data/meshes/ok1.msh".to_string();
        let mesh = read_mesh(&filepath)?;
        println!("{}", mesh);
        assert_eq!(
            format!("{}", mesh),
            "ndim = 2\n\
             npoint = 4\n\
             ncell = 1\n\
             n_boundary_point = 0\n\
             n_boundary_edge = 0\n\
             n_boundary_face = 0\n\
             \n\
             points\n\
             i:0 g:1 x:[0.0, 0.0] c:[]\n\
             i:1 g:1 x:[1.0, 0.0] c:[]\n\
             i:2 g:1 x:[1.0, 1.0] c:[]\n\
             i:3 g:1 x:[0.0, 1.0] c:[]\n\
             \n\
             cells\n\
             i:0 g:0 p:[] e:[] f:[]\n\
             \n\
             boundary_points\n\
             \n\
             boundary_edges\n\
             \n\
             boundary_faces\n"
        );

        let filepath = "./data/meshes/ok2.msh".to_string();
        let mesh = read_mesh(&filepath)?;
        println!("{}", mesh);
        assert_eq!(
            format!("{}", mesh),
            "ndim = 3\n\
             npoint = 8\n\
             ncell = 1\n\
             n_boundary_point = 0\n\
             n_boundary_edge = 0\n\
             n_boundary_face = 0\n\
             \n\
             points\n\
             i:0 g:1 x:[0.0, 0.0, 0.0] c:[]\n\
             i:1 g:1 x:[1.0, 0.0, 0.0] c:[]\n\
             i:2 g:1 x:[1.0, 1.0, 0.0] c:[]\n\
             i:3 g:1 x:[0.0, 1.0, 0.0] c:[]\n\
             i:4 g:1 x:[0.0, 0.0, 1.0] c:[]\n\
             i:5 g:1 x:[1.0, 0.0, 1.0] c:[]\n\
             i:6 g:1 x:[1.0, 1.0, 1.0] c:[]\n\
             i:7 g:1 x:[0.0, 1.0, 1.0] c:[]\n\
             \n\
             cells\n\
             i:0 g:0 p:[] e:[] f:[]\n\
             \n\
             boundary_points\n\
             \n\
             boundary_edges\n\
             \n\
             boundary_faces\n"
        );
        Ok(())
    }
}
<commit_msg>Improve read mesh<commit_after>use crate::Mesh;
use std::fs::File;
use std::io::{BufRead, BufReader};

struct ReadMeshData {
    ndim: usize,
    npoint: usize,
    ncell: usize,
    current_npoint: usize,
    current_ncell: usize,
}

impl ReadMeshData {
    fn new() -> Self {
        ReadMeshData {
            ndim: 0,
            npoint: 0,
            ncell: 0,
            current_npoint: 0,
            current_ncell: 0,
        }
    }

    fn parse_sizes(&mut self, line: &String) -> Result<bool, &'static str> {
        let maybe_data = line.trim_start().trim_end_matches("\n");
        if maybe_data.starts_with("#") || maybe_data == "" {
            return Ok(false); // ignore comments or empty lines; returns false == not parsed
        }

        let mut data = maybe_data.split_whitespace();

        self.ndim = data
            .next()
            .unwrap() // must panic because no error expected here
            .parse()
            .map_err(|_| "cannot parse ndim")?;

        match data.next() {
            Some(v) => self.npoint = v.parse().map_err(|_| "cannot parse npoint")?,
            None => return Err("cannot read npoint"),
        };

        match data.next() {
            Some(v) => self.ncell = v.parse().map_err(|_| "cannot parse ncell")?,
            None => return Err("cannot read ncell"),
        };

        Ok(true) // returns true == parsed
    }

    fn parse_point(&mut self, mesh: &mut Mesh, line: &String) -> Result<bool, &'static str> {
        let maybe_data = line.trim_start().trim_end_matches("\n");
        if maybe_data.starts_with("#") || maybe_data == "" {
            return Ok(false); // ignore comments or empty lines
        }

        let mut data = maybe_data.split_whitespace();

        let i: usize = data
            .next()
            .unwrap() // must panic because no error expected here
            .parse()
            .map_err(|_| "cannot parse point id")?;

        if i != self.current_npoint {
            return Err("the id and index of points must equal each other");
        }

        mesh.points[i].id = i;

        match data.next() {
            Some(v) => mesh.points[i].group = v.parse().map_err(|_| "cannot parse point group")?,
            None => return Err("cannot read point group"),
        };

        match data.next() {
            Some(v) => mesh.points[i].coords[0] = v.parse().map_err(|_| "cannot parse point x coordinate")?,
            None => return Err("cannot read point x coordinate"),
        };

        match data.next() {
            Some(v) => mesh.points[i].coords[1] = v.parse().map_err(|_| "cannot parse point y coordinate")?,
            None => return Err("cannot read point y coordinate"),
        };

        if self.ndim == 3 {
            match data.next() {
                Some(v) => mesh.points[i].coords[2] = v.parse().map_err(|_| "cannot parse point z coordinate")?,
                None => return Err("cannot read point z coordinate"),
            };
        }

        self.current_npoint += 1; // next point

        Ok(true) // returns true == parsed
    }
}

pub fn read_mesh(filepath: &String) -> Result<Mesh, &'static str> {
    let input = File::open(filepath).map_err(|_| "cannot open file")?;
    let buffered = BufReader::new(input);
    let mut lines_iter = buffered.lines();

    // auxiliary data structure
    let mut data = ReadMeshData::new();

    // read and parse sizes
    loop {
        match lines_iter.next() {
            Some(v) => {
                let line = v.unwrap(); // must panic because no error expected here
                if data.parse_sizes(&line)? {
                    break;
                }
            }
            None => return Err("file is empty or header is missing"),
        }
    }

    // allocate mesh
    let mut mesh = Mesh::new_zeroed(data.ndim, data.npoint, data.ncell)?;

    // read and parse points
    loop {
        match lines_iter.next() {
            Some(v) => {
                let line = v.unwrap(); // must panic because no error expected here
                if data.parse_point(&mut mesh, &line)? {
                    if data.current_npoint == data.npoint {
                        break;
                    }
                }
            }
            None => break,
        }
    }

    // check data
    if data.current_npoint != data.npoint {
        return Err("not all points have been found");
    }

    // read and parse cells

    // done
    Ok(mesh)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{read_mesh, Mesh, ReadMeshData};

    #[test]
    fn parse_sizes_captures_errors() -> Result<(), &'static str> {
        let mut data = ReadMeshData::new();

        assert_eq!(
            data.parse_sizes(&String::from(" wrong \n")).err(),
            Some("cannot parse ndim")
        );

        assert_eq!(
            data.parse_sizes(&String::from(" 2 \n")).err(),
            Some("cannot read npoint")
        );
        assert_eq!(
            data.parse_sizes(&String::from(" 1 wrong")).err(),
            Some("cannot parse npoint")
        );

        assert_eq!(
            data.parse_sizes(&String::from(" 2 4   \n")).err(),
            Some("cannot read ncell")
        );
        assert_eq!(
            data.parse_sizes(&String::from(" 2 4  wrong")).err(),
            Some("cannot parse ncell")
        );
        Ok(())
    }

    #[test]
    fn parse_point_captures_errors() -> Result<(), &'static str> {
        let mut data = ReadMeshData::new();
        data.ndim = 3;
        data.npoint = 2;
        data.ncell = 1;

        let mut mesh = Mesh::new_zeroed(data.ndim, data.npoint, data.ncell)?;

        assert_eq!(
            data.parse_point(&mut mesh, &String::from(" wrong \n")).err(),
            Some("cannot parse point id")
        );

        assert_eq!(
            data.parse_point(&mut mesh, &String::from(" 2 1 0.0 0.0 0.0 \n")).err(),
            Some("the id and index of points must equal each other")
        );

        assert_eq!(
            data.parse_point(&mut mesh, &String::from(" 0 \n")).err(),
            Some("cannot read point group")
        );
        assert_eq!(
            data.parse_point(&mut mesh, &String::from(" 0 wrong")).err(),
            Some("cannot parse point group")
        );

        assert_eq!(
            data.parse_point(&mut mesh, &String::from(" 0 1   \n")).err(),
            Some("cannot read point x coordinate")
        );
        assert_eq!(
            data.parse_point(&mut mesh, &String::from(" 0 1  wrong")).err(),
            Some("cannot parse point x coordinate")
        );

        assert_eq!(
            data.parse_point(&mut mesh, &String::from(" 0 1 0.0  \n")).err(),
            Some("cannot read point y coordinate")
        );
        assert_eq!(
            data.parse_point(&mut mesh, &String::from(" 0 1 0.0 wrong")).err(),
            Some("cannot parse point y coordinate")
        );

        assert_eq!(
            data.parse_point(&mut mesh, &String::from(" 0 1 0.0 0.0 \n")).err(),
            Some("cannot read point z coordinate")
        );
        assert_eq!(
            data.parse_point(&mut mesh, &String::from(" 0 1 0.0 0.0 wrong")).err(),
            Some("cannot parse point z coordinate")
        );
        Ok(())
    }

    #[test]
    fn read_mesh_handle_wrong_files() -> Result<(), &'static str> {
        assert_eq!(read_mesh(&String::from("__wrong__")).err(), Some("cannot open file"));
        assert_eq!(
            read_mesh(&String::from("./data/meshes/bad_empty.msh")).err(),
            Some("file is empty or header is missing")
        );
        assert_eq!(
            read_mesh(&String::from("./data/meshes/bad_missing_header.msh")).err(),
            Some("file is empty or header is missing")
        );
        assert_eq!(
            read_mesh(&String::from("./data/meshes/bad_missing_points.msh")).err(),
            Some("not all points have been found")
        );
        /*
        assert_eq!(
            read_mesh(&String::from("./data/meshes/bad_many_points.msh")).err(),
            Some("there are more points than specified")
        );
        */
        Ok(())
    }

    #[test]
    fn read_mesh_2d_works() -> Result<(), &'static str> {
        let filepath = "./data/meshes/ok1.msh".to_string();
        let mesh = read_mesh(&filepath)?;
        println!("{}", mesh);
        assert_eq!(
            format!("{}", mesh),
            "ndim = 2\n\
             npoint = 4\n\
             ncell = 1\n\
             n_boundary_point = 0\n\
             n_boundary_edge = 0\n\
             n_boundary_face = 0\n\
             \n\
             points\n\
             i:0 g:1 x:[0.0, 0.0] c:[]\n\
             i:1 g:1 x:[1.0, 0.0] c:[]\n\
             i:2 g:1 x:[1.0, 1.0] c:[]\n\
             i:3 g:1 x:[0.0, 1.0] c:[]\n\
             \n\
             cells\n\
             i:0 g:0 p:[] e:[] f:[]\n\
             \n\
             boundary_points\n\
             \n\
             boundary_edges\n\
             \n\
             boundary_faces\n"
        );
        Ok(())
    }

    #[test]
    fn read_mesh_3d_works() -> Result<(), &'static str> {
        let filepath = "./data/meshes/ok2.msh".to_string();
        let mesh = read_mesh(&filepath)?;
        println!("{}", mesh);
        assert_eq!(
            format!("{}", mesh),
            "ndim = 3\n\
             npoint = 8\n\
             ncell = 1\n\
             n_boundary_point = 0\n\
             n_boundary_edge = 0\n\
             n_boundary_face = 0\n\
             \n\
             points\n\
             i:0 g:1 x:[0.0, 0.0, 0.0] c:[]\n\
             i:1 g:1 x:[1.0, 0.0, 0.0] c:[]\n\
             i:2 g:1 x:[1.0, 1.0, 0.0] c:[]\n\
             i:3 g:1 x:[0.0, 1.0, 0.0] c:[]\n\
             i:4 g:1 x:[0.0, 0.0, 1.0] c:[]\n\
             i:5 g:1 x:[1.0, 0.0, 1.0] c:[]\n\
             i:6 g:1 x:[1.0, 1.0, 1.0] c:[]\n\
             i:7 g:1 x:[0.0, 1.0, 1.0] c:[]\n\
             \n\
             cells\n\
             i:0 g:0 p:[] e:[] f:[]\n\
             \n\
             boundary_points\n\
             \n\
             boundary_edges\n\
             \n\
             boundary_faces\n"
        );
        Ok(())
    }
}
<|endoftext|>


<commit_before>use super::Mode;
use super::KeyMap;
use super::Key;
use super::KeyMapState;
use super::Direction;
use buffer::Mark;
use command::{BuilderEvent, Operation, Instruction, Command, Action};
use textobject::{Anchor, Kind, TextObject, Offset};

// TODO: move this somewhere else - probably command module
fn movement(offset: Offset, kind: Kind) -> Command {
    Command {
        number: 0,
        action: Action::Instruction(Instruction::SetMark(Mark::Cursor(0))),
        object: TextObject {
            kind: kind,
            offset: offset
        }
    }

}

/// Standard mode is Iota's default mode.
///
/// Standard mode uses non-vi-like keybindings.
/// Unlike Normal, Command and Visual modes which are all used together, Standard
/// mode is used on its own.
///
/// Standard mode allows Iota to be used in a non-modal way, similar to mainstream
/// editors like emacs or sublime.
pub struct StandardMode {
    keymap: KeyMap<Command>,
}

impl StandardMode {

    /// Create a new instance of StandardMode
    pub fn new() -> StandardMode {
        StandardMode {
            keymap: StandardMode::key_defaults(),
        }
    }

    /// Creates a KeyMap with default StandardMode key bindings
    fn key_defaults() -> KeyMap<Command> {
        let mut keymap = KeyMap::new();

        // Editor Commands
        keymap.bind_key(Key::Ctrl('q'), Command::exit_editor());
        keymap.bind_key(Key::Ctrl('s'), Command::save_buffer());
        keymap.bind_keys(vec![Key::Ctrl('x'), Key::Ctrl('c')].as_slice(), Command::exit_editor());
        keymap.bind_keys(vec![Key::Ctrl('x'), Key::Ctrl('s')].as_slice(), Command::save_buffer());

        // Cursor movement
        keymap.bind_key(Key::Up, movement(Offset::Backward(1, Mark::Cursor(0)), Kind::Line(Anchor::Same)));
        keymap.bind_key(Key::Down, movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Line(Anchor::Same)));
        keymap.bind_key(Key::Left, movement(Offset::Backward(1, Mark::Cursor(0)), Kind::Char));
        keymap.bind_key(Key::Right, movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Char));
        keymap.bind_key(Key::Ctrl('p'), movement(Offset::Backward(1, Mark::Cursor(0)), Kind::Line(Anchor::Same)));
        keymap.bind_key(Key::Ctrl('n'), movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Line(Anchor::Same)));
        keymap.bind_key(Key::Ctrl('b'), movement(Offset::Backward(1, Mark::Cursor(0)), Kind::Char));
        keymap.bind_key(Key::Ctrl('f'), movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Char));
        keymap.bind_key(Key::Ctrl('e'), movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Line(Anchor::End)));
        keymap.bind_key(Key::Ctrl('a'), movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Line(Anchor::Start)));

        // // Editing
        keymap.bind_key(Key::Tab, Command::insert_tab());
        keymap.bind_key(Key::Enter, Command::insert_char('\n'));
        // keymap.bind_key(Key::Backspace, Command::Delete(Direction::Left, 1));
        // keymap.bind_key(Key::Ctrl('h'), Command::Delete(Direction::Left, 1));
        // keymap.bind_key(Key::Delete, Command::Delete(Direction::Right, 1));
        // keymap.bind_key(Key::Ctrl('d'), Command::Delete(Direction::Right, 1));

        // History
        keymap.bind_key(Key::Ctrl('z'), Command {
            number: 1,
            action: Action::Operation(Operation::Undo),
            object: TextObject {
                kind: Kind::Char,
                offset: Offset::Absolute(0)
            }
        });
        keymap.bind_key(Key::Ctrl('y'), Command {
            number: 1,
            action: Action::Operation(Operation::Redo),
            object: TextObject {
                kind: Kind::Char,
                offset: Offset::Absolute(0)
            }
        });

        keymap
    }

}

impl Mode for StandardMode {
    /// Given a key, pass it through the StandardMode KeyMap and return the associated Command, if any.
    /// If no match is found, treat it as an InsertChar command.
    fn handle_key_event(&mut self, key: Key) -> BuilderEvent {

        if let Key::Char(c) = key {
            BuilderEvent::Complete(Command::insert_char(c))
        } else {
            if let KeyMapState::Match(c) = self.keymap.check_key(key) {
                BuilderEvent::Complete(c)
            } else {
                BuilderEvent::Incomplete
            }
        }
    }
}
<commit_msg>Added deletion commands<commit_after>use super::Mode;
use super::KeyMap;
use super::Key;
use super::KeyMapState;
use super::Direction;
use buffer::Mark;
use command::{BuilderEvent, Operation, Instruction, Command, Action};
use textobject::{Anchor, Kind, TextObject, Offset};

// TODO: move this somewhere else - probably command module
fn movement(offset: Offset, kind: Kind) -> Command {
    Command {
        number: 0,
        action: Action::Instruction(Instruction::SetMark(Mark::Cursor(0))),
        object: TextObject {
            kind: kind,
            offset: offset
        }
    }

}

/// Standard mode is Iota's default mode.
///
/// Standard mode uses non-vi-like keybindings.
/// Unlike Normal, Command and Visual modes which are all used together, Standard
/// mode is used on its own.
///
/// Standard mode allows Iota to be used in a non-modal way, similar to mainstream
/// editors like emacs or sublime.
pub struct StandardMode {
    keymap: KeyMap<Command>,
}

impl StandardMode {

    /// Create a new instance of StandardMode
    pub fn new() -> StandardMode {
        StandardMode {
            keymap: StandardMode::key_defaults(),
        }
    }

    /// Creates a KeyMap with default StandardMode key bindings
    fn key_defaults() -> KeyMap<Command> {
        let mut keymap = KeyMap::new();

        // Editor Commands
        keymap.bind_key(Key::Ctrl('q'), Command::exit_editor());
        keymap.bind_key(Key::Ctrl('s'), Command::save_buffer());
        keymap.bind_keys(vec![Key::Ctrl('x'), Key::Ctrl('c')].as_slice(), Command::exit_editor());
        keymap.bind_keys(vec![Key::Ctrl('x'), Key::Ctrl('s')].as_slice(), Command::save_buffer());

        // Cursor movement
        keymap.bind_key(Key::Up, movement(Offset::Backward(1, Mark::Cursor(0)), Kind::Line(Anchor::Same)));
        keymap.bind_key(Key::Down, movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Line(Anchor::Same)));
        keymap.bind_key(Key::Left, movement(Offset::Backward(1, Mark::Cursor(0)), Kind::Char));
        keymap.bind_key(Key::Right, movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Char));
        keymap.bind_key(Key::Ctrl('p'), movement(Offset::Backward(1, Mark::Cursor(0)), Kind::Line(Anchor::Same)));
        keymap.bind_key(Key::Ctrl('n'), movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Line(Anchor::Same)));
        keymap.bind_key(Key::Ctrl('b'), movement(Offset::Backward(1, Mark::Cursor(0)), Kind::Char));
        keymap.bind_key(Key::Ctrl('f'), movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Char));
        keymap.bind_key(Key::Ctrl('e'), movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Line(Anchor::End)));
        keymap.bind_key(Key::Ctrl('a'), movement(Offset::Forward(1, Mark::Cursor(0)), Kind::Line(Anchor::Start)));

        // Editing
        keymap.bind_key(Key::Tab, Command::insert_tab());
        keymap.bind_key(Key::Enter, Command::insert_char('\n'));
        keymap.bind_key(Key::Backspace, Command {
            number: 1,
            action: Action::Operation(Operation::Delete),
            object: TextObject {
                kind: Kind::Char,
                offset: Offset::Backward(1, Mark::Cursor(0))
            }
        });
        keymap.bind_key(Key::Delete, Command {
            number: 1,
            action: Action::Operation(Operation::Delete),
            object: TextObject {
                kind: Kind::Char,
                offset: Offset::Forward(1, Mark::Cursor(0))
            }
        });
        keymap.bind_key(Key::Ctrl('h'), Command {
            number: 1,
            action: Action::Operation(Operation::Delete),
            object: TextObject {
                kind: Kind::Char,
                offset: Offset::Backward(1, Mark::Cursor(0))
            }
        });
        keymap.bind_key(Key::Ctrl('d'), Command {
            number: 1,
            action: Action::Operation(Operation::Delete),
            object: TextObject {
                kind: Kind::Char,
                offset: Offset::Forward(1, Mark::Cursor(0))
            }
        });

        // History
        keymap.bind_key(Key::Ctrl('z'), Command {
            number: 1,
            action: Action::Operation(Operation::Undo),
            object: TextObject {
                kind: Kind::Char,
                offset: Offset::Absolute(0)
            }
        });
        keymap.bind_key(Key::Ctrl('y'), Command {
            number: 1,
            action: Action::Operation(Operation::Redo),
            object: TextObject {
                kind: Kind::Char,
                offset: Offset::Absolute(0)
            }
        });

        keymap
    }

}

impl Mode for StandardMode {
    /// Given a key, pass it through the StandardMode KeyMap and return the associated Command, if any.
    /// If no match is found, treat it as an InsertChar command.
    fn handle_key_event(&mut self, key: Key) -> BuilderEvent {

        if let Key::Char(c) = key {
            BuilderEvent::Complete(Command::insert_char(c))
        } else {
            if let KeyMapState::Match(c) = self.keymap.check_key(key) {
                BuilderEvent::Complete(c)
            } else {
                BuilderEvent::Incomplete
            }
        }
    }
}
<|endoftext|>


<commit_before>pub use expectest::prelude::{be_ok, be_err};

pub use sql::lexer::Tokenizer;
pub use sql::parser::Parser;
pub use sql::query_executer::QueryExecuter;

describe! create_table_queries {

    describe! queries_execution {

        before_each {
            let mut executer = QueryExecuter::default();
        }

        it "creates single column table" {
            expect!(executer.execute("create table table_name (col int);".to_owned().tokenize().unwrap().parse().unwrap()))
                .to(be_ok().value("'table_name' was created".to_owned()));
        }

        it "creates a table with list of columns" {
            expect!(executer.execute("create table table_name (col1 int, col2 int, col3 int);".to_owned().tokenize().unwrap().parse().unwrap()))
                .to(be_ok().value("'table_name' was created".to_owned()));
        }

        it "inserts row in created table" {
            let r = executer.execute("create table table_name (col int);".to_owned().tokenize().unwrap().parse().unwrap());

            println!("result {:?}", r);

            expect!(executer.execute("insert into table_name values(1);".to_owned().tokenize().unwrap().parse().unwrap()))
                .to(be_ok().value("row was inserted".to_owned()));
        }
    }
}
<commit_msg>insert data into table with many columns<commit_after>pub use expectest::prelude::{be_ok, be_err};

pub use sql::lexer::Tokenizer;
pub use sql::parser::Parser;
pub use sql::query_executer::QueryExecuter;

describe! create_table_queries {

    describe! queries_execution {

        before_each {
            let mut executer = QueryExecuter::default();
        }

        it "creates single column table" {
            expect!(executer.execute("create table table_name (col int);".to_owned().tokenize().unwrap().parse().unwrap()))
                .to(be_ok().value("'table_name' was created".to_owned()));
        }

        it "creates a table with list of columns" {
            expect!(executer.execute("create table table_name (col1 int, col2 int, col3 int);".to_owned().tokenize().unwrap().parse().unwrap()))
                .to(be_ok().value("'table_name' was created".to_owned()));
        }

        it "inserts row in created table" {
            executer.execute("create table table_name (col int);".to_owned().tokenize().unwrap().parse().unwrap());

            expect!(executer.execute("insert into table_name values(1);".to_owned().tokenize().unwrap().parse().unwrap()))
                .to(be_ok().value("row was inserted".to_owned()));
        }

        it "inserts row in table with many columns" {
            executer.execute("create table table_name (col1 int, col2 int);".to_owned().tokenize().unwrap().parse().unwrap());

            expect!(executer.execute("insert into table_name values(1, 2);".to_owned().tokenize().unwrap().parse().unwrap()))
                .to(be_ok().value("row was inserted".to_owned()));
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod variable;
pub mod ops;
pub mod store;
pub mod delta_store;
pub mod arithmetics;

pub use variable::variable::*;
pub use variable::ops::Iterable;
<commit_msg>[Documentation] High-level description of the variable module.<commit_after>// Copyright 2015 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A variable is a pair `(location, value)` where the value lives inside a block of memory, called a *store*. The store is parametrized by the type of the values it will contain, it is the *domain* of the variables.
//!
//! We initialize a variable in the store by providing the associated value and the store gives back a location associated to it. Further read or write operations of the value must be done explicitly through the store with the location returned during the allocation. An important property is that only monotonic updates of a value are allowed, it means that the domains can only become smaller. For example, the variable `x: [1..10]` can be updated to `x: [2..10]` or `x: [5..5]` but not to `x: [1..11]`.
//!
//! A subset of arithmetics is provided with *views* on variables. It allows to manipulate an expression such as `x + 5` as if it was a single variable and to avoid implementing specific instances of propagation algorithms such as `x + c < y` which is just `x < y` with `x` being a view. The view acts as a proxy between requested operations and the store. It implies that operations must be called on the views instead of applying them directly to the store.

pub mod variable;
pub mod ops;
pub mod store;
pub mod delta_store;
pub mod arithmetics;

pub use variable::variable::*;
pub use variable::ops::Iterable;
<|endoftext|>


<commit_before>// Copyright 2016 Phillip Oppermann, Calvin Lee and JJ Garzella.
// See the README.md file at the top-level directory of this
// distribution.
//
// Licensed under the MIT license <LICENSE or
// http://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed
// except according to those terms.

// WARNING: IN ORDER FOR THIS FILE TO HAVE SAFETY
//          THE PAGE TABLE MUST BE MAPPED RECURSIVELY
//
// If the 510th entry of the p4 table is not mapped to
// the p4 table itself, we cannot gurentee that any of
// these addresses are valid.

use memory::paging::entry::*;
use memory::paging::ENTRY_COUNT;
use memory::paging::VirtualAddress;
use memory::FrameAllocate;

use core::marker::PhantomData;
use core::ops::{Index, IndexMut};

/// A pointer to the level 4 page table
///
/// # Safety
/// This pointer is valid if and only if recursive mapping is valid.
pub const P4: *mut Table<Level4> = 0o177777_776_776_776_776_0000 as *mut _;

/// A page table
pub struct Table<L: TableLevel> {
    entries: [Entry; ENTRY_COUNT],
    level: PhantomData<L>,
}

impl<L> Table<L>
    where L: TableLevel
{
    /// Sets each page table entry to unused
    pub fn zero(&mut self) {
        for entry in self.entries.iter_mut() {
            entry.set_unused();
        }
    }
}

/// These methods can only be used if the given table is a parent to other tables.
impl<L> Table<L>
    where L: HierarchicalLevel
{
    /// Returns a reference to the table at index `index`.
    pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &*(address as *const _) })
    }

    /// Returns a mutable reference to the table at index `index`
    pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &mut *(address as *mut _) })
    }

    /// Returns the address of the table at index `index`
    fn next_table_address(&self, index: usize) -> Option<VirtualAddress> {
        let entry_flags = self[index].flags();
        if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) {
            let table_address = self as *const _ as usize;
            // Or 0xffff << 48 to ensure a canonical address
            Some((0xffff << 48) | (table_address << 9) | (index << 12))
        } else {
            None
        }
    }

    /// If the next table does not exist, this function creates it with the physical
    /// frame allocator given and returns a mutable reference.
    pub fn next_table_create<A>(&mut self,
                                index: usize,
                                allocator: &mut A)
                                -> &mut Table<L::NextLevel>
        where A: FrameAllocate
    {
        if self.next_table(index).is_none() {
            assert!(!self.entries[index].flags().contains(HUGE_PAGE),
                    "Mapping code does not support huge pages");
            let frame = allocator.allocate_frame()
                .expect("No frames availible :(");
            self.entries[index].set(frame, PRESENT | WRITABLE);
            self.next_table_mut(index).unwrap().zero();
            assert!(self.next_table_mut(index).is_some());
        }
        self.next_table_mut(index).unwrap()
    }
}

/// Allows indexing to be used on the `Table` type.
impl<L> Index<usize> for Table<L>
    where L: TableLevel
{
    type Output = Entry;

    fn index(&self, index: usize) -> &Entry {
        &self.entries[index]
    }
}

/// Allows mutable indexing to be used on the `Table` type.
impl<L> IndexMut<usize> for Table<L>
    where L: TableLevel
{
    fn index_mut(&mut self, index: usize) -> &mut Entry {
        &mut self.entries[index]
    }
}

/// A trait that describes a table's level.
pub trait TableLevel {}

pub enum Level4 {}
pub enum Level3 {}
pub enum Level2 {}
pub enum Level1 {}

impl TableLevel for Level4 {}
impl TableLevel for Level3 {}
impl TableLevel for Level2 {}
impl TableLevel for Level1 {}

/// Each table that is not `Level1` produces another table with lower level.
pub trait HierarchicalLevel: TableLevel {
    type NextLevel: TableLevel;
}

impl HierarchicalLevel for Level4 {
    type NextLevel = Level3;
}
impl HierarchicalLevel for Level3 {
    type NextLevel = Level2;
}
impl HierarchicalLevel for Level2 {
    type NextLevel = Level1;
}
<commit_msg>Add debug printing to table.rs<commit_after>// Copyright 2016 Phillip Oppermann, Calvin Lee and JJ Garzella.
// See the README.md file at the top-level directory of this
// distribution.
//
// Licensed under the MIT license <LICENSE or
// http://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed
// except according to those terms.

// WARNING: IN ORDER FOR THIS FILE TO HAVE SAFETY
//          THE PAGE TABLE MUST BE MAPPED RECURSIVELY
//
// If the 510th entry of the p4 table is not mapped to
// the p4 table itself, we cannot gurentee that any of
// these addresses are valid.

use memory::paging::entry::*;
use memory::paging::ENTRY_COUNT;
use memory::paging::VirtualAddress;
use memory::FrameAllocate;

use core::marker::PhantomData;
use core::ops::{Index, IndexMut};

/// A pointer to the level 4 page table
///
/// # Safety
/// This pointer is valid if and only if recursive mapping is valid.
pub const P4: *mut Table<Level4> = 0o177777_776_776_776_776_0000 as *mut _;

/// A page table
pub struct Table<L: TableLevel> {
    entries: [Entry; ENTRY_COUNT],
    level: PhantomData<L>,
}

impl<L> Table<L>
    where L: TableLevel
{
    /// Sets each page table entry to unused
    pub fn zero(&mut self) {
        for entry in self.entries.iter_mut() {
            entry.set_unused();
        }
    }
}

/// These methods can only be used if the given table is a parent to other tables.
impl<L> Table<L>
    where L: HierarchicalLevel
{
    /// Returns a reference to the table at index `index`.
    pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &*(address as *const _) })
    }

    /// Returns a mutable reference to the table at index `index`
    pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &mut *(address as *mut _) })
    }

    /// Returns the address of the table at index `index`
    fn next_table_address(&self, index: usize) -> Option<VirtualAddress> {
        let entry_flags = self[index].flags();
        if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) {
            let table_address = self as *const _ as usize;
            // Or 0xffff << 48 to ensure a canonical address
            Some((0xffff << 48) | (table_address << 9) | (index << 12))
        } else {
            None
        }
    }

    /// If the next table does not exist, this function creates it with the physical
    /// frame allocator given and returns a mutable reference.
    pub fn next_table_create<A>(&mut self,
                                index: usize,
                                allocator: &mut A)
                                -> &mut Table<L::NextLevel>
        where A: FrameAllocate
    {
        if self.next_table(index).is_none() {
            println!("{:?}", self.next_table_mut(index).is_some());
            assert!(!self.entries[index].flags().contains(HUGE_PAGE),
                    "Mapping code does not support huge pages");
            let frame = allocator.allocate_frame()
                .expect("No frames availible :(");
            self.entries[index].set(frame, PRESENT | WRITABLE);
            println!("{:?}", self.next_table_mut(index).is_some());
            println!("{:?}", index);
            self.next_table_mut(index).unwrap().zero();
            println!("{:?}", self.next_table_mut(index).is_some());
            assert!(self.next_table_mut(index).is_some());
        }
        self.next_table_mut(index).unwrap()
    }
}

/// Allows indexing to be used on the `Table` type.
impl<L> Index<usize> for Table<L>
    where L: TableLevel
{
    type Output = Entry;

    fn index(&self, index: usize) -> &Entry {
        &self.entries[index]
    }
}

/// Allows mutable indexing to be used on the `Table` type.
impl<L> IndexMut<usize> for Table<L>
    where L: TableLevel
{
    fn index_mut(&mut self, index: usize) -> &mut Entry {
        &mut self.entries[index]
    }
}

/// A trait that describes a table's level.
pub trait TableLevel {}

pub enum Level4 {}
pub enum Level3 {}
pub enum Level2 {}
pub enum Level1 {}

impl TableLevel for Level4 {}
impl TableLevel for Level3 {}
impl TableLevel for Level2 {}
impl TableLevel for Level1 {}

/// Each table that is not `Level1` produces another table with lower level.
pub trait HierarchicalLevel: TableLevel {
    type NextLevel: TableLevel;
}

impl HierarchicalLevel for Level4 {
    type NextLevel = Level3;
}
impl HierarchicalLevel for Level3 {
    type NextLevel = Level2;
}
impl HierarchicalLevel for Level2 {
    type NextLevel = Level1;
}
<|endoftext|>


<commit_before>use base64::write::EncoderWriter;
use indexmap::IndexMap;
use prometheus::proto::{MetricFamily, MetricType};
use prometheus::{Encoder, Error};
use std::io::Write;

/// The `LogEncoder` struct encodes Prometheus metrics in the format [`crates-io-heroku-metrics`]
/// expects metrics to be logged. This can be used to forward instance metrics to it, allowing them
/// to be scraped by the Rust infrastructure monitoring system.
///
/// The metrics are encoded in the format [Vector expects them][vector], and the list of metrics is
/// json-encoded and then base64-encoded. The whole thing is prefixed with a predefined string to
/// let [`crates-io-heroku-metrics`] find it easily.
///
/// This is needed mostly for crates.io hosted on Heroku. Deployments of crates.io on other
/// platforms shouldn't need this.
///
/// [`crates-io-heroku-metrics`]: https://github.com/rust-lang/crates-io-heroku-metrics
/// [vector]: https://vector.dev/docs/about/under-the-hood/architecture/data-model/metric/
#[derive(Debug, Clone, Copy)]
pub struct LogEncoder(());

impl LogEncoder {
    pub fn new() -> Self {
        Self(())
    }
}

impl Encoder for LogEncoder {
    fn encode<W: Write>(
        &self,
        families: &[MetricFamily],
        mut dest: &mut W,
    ) -> prometheus::Result<()> {
        let events = families_to_json_events(families);

        dest.write_all(b"crates-io-heroku-metrics:ingest ")?;
        let base64_dest = EncoderWriter::new(&mut dest, base64::STANDARD);
        serde_json::to_writer(base64_dest, &events).map_err(|e| Error::Msg(e.to_string()))?;
        dest.write_all(b"\n")?;

        Ok(())
    }

    fn format_type(&self) -> &str {
        "crates-io-heroku-metrics log encoding"
    }
}

fn families_to_json_events(families: &[MetricFamily]) -> Vec<VectorEvent<'_>> {
    let mut events = Vec::new();
    for family in families {
        for metric in family.get_metric() {
            let data = match family.get_field_type() {
                MetricType::COUNTER => VectorMetricData::Counter {
                    value: metric.get_counter().get_value(),
                },
                MetricType::GAUGE => VectorMetricData::Gauge {
                    value: metric.get_gauge().get_value(),
                },
                other => {
                    panic!("unsupported metric type: {:?}", other)
                }
            };
            events.push(VectorEvent {
                metric: VectorMetric {
                    data,
                    kind: "absolute",
                    name: family.get_name(),
                    tags: metric
                        .get_label()
                        .iter()
                        .map(|p| (p.get_name(), p.get_value()))
                        .collect(),
                },
            });
        }
    }
    events
}

#[derive(Serialize, Debug, PartialEq)]
struct VectorEvent<'a> {
    metric: VectorMetric<'a>,
}

#[derive(Serialize, Debug, PartialEq)]
struct VectorMetric<'a> {
    #[serde(flatten)]
    data: VectorMetricData,
    kind: &'a str,
    name: &'a str,
    tags: IndexMap<&'a str, &'a str>,
}

#[derive(Serialize, Debug, PartialEq)]
#[serde(rename_all = "snake_case")]
enum VectorMetricData {
    Counter { value: f64 },
    Gauge { value: f64 },
}

#[cfg(test)]
mod tests {
    use super::*;
    use anyhow::Error;
    use prometheus::{IntCounter, IntGauge, IntGaugeVec, Opts, Registry};

    #[test]
    fn test_counter_to_json() -> Result<(), Error> {
        let counter =
            IntCounter::with_opts(Opts::new("sample_counter", "sample_counter help message"))?;
        let registry = Registry::new();
        registry.register(Box::new(counter.clone()))?;

        assert_eq!(
            vec![VectorEvent {
                metric: VectorMetric {
                    data: VectorMetricData::Counter { value: 0.0 },
                    kind: "absolute",
                    name: "sample_counter",
                    tags: IndexMap::new(),
                }
            }],
            families_to_json_events(&registry.gather())
        );

        counter.inc_by(42);
        assert_eq!(
            vec![VectorEvent {
                metric: VectorMetric {
                    data: VectorMetricData::Counter { value: 42.0 },
                    kind: "absolute",
                    name: "sample_counter",
                    tags: IndexMap::new(),
                }
            }],
            families_to_json_events(&registry.gather())
        );

        Ok(())
    }

    #[test]
    fn test_gauge_to_json() -> Result<(), Error> {
        let gauge = IntGauge::with_opts(Opts::new("sample_gauge", "sample_gauge help message"))?;
        let registry = Registry::new();
        registry.register(Box::new(gauge.clone()))?;

        assert_eq!(
            vec![VectorEvent {
                metric: VectorMetric {
                    data: VectorMetricData::Gauge { value: 0.0 },
                    kind: "absolute",
                    name: "sample_gauge",
                    tags: IndexMap::new(),
                }
            }],
            families_to_json_events(&registry.gather())
        );

        gauge.set(42);
        assert_eq!(
            vec![VectorEvent {
                metric: VectorMetric {
                    data: VectorMetricData::Gauge { value: 42.0 },
                    kind: "absolute",
                    name: "sample_gauge",
                    tags: IndexMap::new(),
                }
            }],
            families_to_json_events(&registry.gather())
        );

        Ok(())
    }

    #[test]
    fn test_metric_with_tags_to_json() -> Result<(), Error> {
        let gauge_vec = IntGaugeVec::new(
            Opts::new("sample_gauge", "sample_gauge help message"),
            &["label1", "label2"],
        )?;
        let registry = Registry::new();
        registry.register(Box::new(gauge_vec.clone()))?;

        gauge_vec.with_label_values(&["foo", "1"]).set(42);
        gauge_vec.with_label_values(&["bar", "2"]).set(98);

        assert_eq!(
            vec![
                VectorEvent {
                    metric: VectorMetric {
                        data: VectorMetricData::Gauge { value: 98.0 },
                        kind: "absolute",
                        name: "sample_gauge",
                        tags: [("label1", "bar"), ("label2", "2")]
                            .iter()
                            .copied()
                            .collect(),
                    }
                },
                VectorEvent {
                    metric: VectorMetric {
                        data: VectorMetricData::Gauge { value: 42.0 },
                        kind: "absolute",
                        name: "sample_gauge",
                        tags: [("label1", "foo"), ("label2", "1")]
                            .iter()
                            .copied()
                            .collect(),
                    }
                },
            ],
            families_to_json_events(&registry.gather())
        );

        Ok(())
    }

    #[test]
    fn test_encoding() -> Result<(), Error> {
        let gauge = IntGauge::with_opts(Opts::new("sample_gauge", "sample_gauge help message"))?;
        let registry = Registry::new();
        registry.register(Box::new(gauge.clone()))?;

        let mut output = Vec::new();
        LogEncoder::new().encode(&registry.gather(), &mut output)?;

        assert_eq!(
            b"crates-io-heroku-metrics:ingest W3sibWV0cmljIjp7ImdhdWdlIjp7InZhbHVlIjowLjB9LCJraW5kIjoiYWJzb2x1dGUiLCJuYW1lIjoic2FtcGxlX2dhdWdlIiwidGFncyI6e319fV0=\n",
            output.as_slice(),
        );

        Ok(())
    }
}
<commit_msg>add support for histograms in log_encoder<commit_after>use base64::write::EncoderWriter;
use indexmap::IndexMap;
use prometheus::proto::{MetricFamily, MetricType};
use prometheus::{Encoder, Error};
use std::io::Write;

/// The `LogEncoder` struct encodes Prometheus metrics in the format [`crates-io-heroku-metrics`]
/// expects metrics to be logged. This can be used to forward instance metrics to it, allowing them
/// to be scraped by the Rust infrastructure monitoring system.
///
/// The metrics are encoded in the format [Vector expects them][vector], and the list of metrics is
/// json-encoded and then base64-encoded. The whole thing is prefixed with a predefined string to
/// let [`crates-io-heroku-metrics`] find it easily.
///
/// This is needed mostly for crates.io hosted on Heroku. Deployments of crates.io on other
/// platforms shouldn't need this.
///
/// [`crates-io-heroku-metrics`]: https://github.com/rust-lang/crates-io-heroku-metrics
/// [vector]: https://vector.dev/docs/about/under-the-hood/architecture/data-model/metric/
#[derive(Debug, Clone, Copy)]
pub struct LogEncoder(());

impl LogEncoder {
    pub fn new() -> Self {
        Self(())
    }
}

impl Encoder for LogEncoder {
    fn encode<W: Write>(
        &self,
        families: &[MetricFamily],
        mut dest: &mut W,
    ) -> prometheus::Result<()> {
        let events = families_to_json_events(families);

        dest.write_all(b"crates-io-heroku-metrics:ingest ")?;
        let base64_dest = EncoderWriter::new(&mut dest, base64::STANDARD);
        serde_json::to_writer(base64_dest, &events).map_err(|e| Error::Msg(e.to_string()))?;
        dest.write_all(b"\n")?;

        Ok(())
    }

    fn format_type(&self) -> &str {
        "crates-io-heroku-metrics log encoding"
    }
}

fn families_to_json_events(families: &[MetricFamily]) -> Vec<VectorEvent<'_>> {
    let mut events = Vec::new();
    for family in families {
        for metric in family.get_metric() {
            let data = match family.get_field_type() {
                MetricType::COUNTER => VectorMetricData::Counter {
                    value: metric.get_counter().get_value(),
                },
                MetricType::GAUGE => VectorMetricData::Gauge {
                    value: metric.get_gauge().get_value(),
                },
                MetricType::HISTOGRAM => {
                    let histogram = metric.get_histogram();

                    // We need to convert from cumulative counts (used by the Prometheus library)
                    // to plain counts (used by Vector).
                    let mut buckets = Vec::new();
                    let mut last_cumulative_count = 0;
                    for bucket in histogram.get_bucket() {
                        buckets.push(VectorHistogramBucket {
                            upper_limit: bucket.get_upper_bound(),
                            count: bucket.get_cumulative_count() - last_cumulative_count,
                        });
                        last_cumulative_count = bucket.get_cumulative_count();
                    }

                    VectorMetricData::AggregatedHistogram {
                        count: histogram.get_sample_count(),
                        sum: histogram.get_sample_sum(),
                        buckets,
                    }
                }
                other => {
                    panic!("unsupported metric type: {:?}", other)
                }
            };
            events.push(VectorEvent {
                metric: VectorMetric {
                    data,
                    kind: "absolute",
                    name: family.get_name(),
                    tags: metric
                        .get_label()
                        .iter()
                        .map(|p| (p.get_name(), p.get_value()))
                        .collect(),
                },
            });
        }
    }
    events
}

#[derive(Serialize, Debug, PartialEq)]
struct VectorEvent<'a> {
    metric: VectorMetric<'a>,
}

#[derive(Serialize, Debug, PartialEq)]
struct VectorMetric<'a> {
    #[serde(flatten)]
    data: VectorMetricData,
    kind: &'a str,
    name: &'a str,
    tags: IndexMap<&'a str, &'a str>,
}

#[derive(Serialize, Debug, PartialEq)]
#[serde(rename_all = "snake_case")]
enum VectorMetricData {
    AggregatedHistogram {
        buckets: Vec<VectorHistogramBucket>,
        count: u64,
        sum: f64,
    },
    Counter {
        value: f64,
    },
    Gauge {
        value: f64,
    },
}

#[derive(Serialize, Debug, PartialEq)]
struct VectorHistogramBucket {
    upper_limit: f64,
    count: u64,
}

#[cfg(test)]
mod tests {
    use super::*;
    use anyhow::Error;
    use prometheus::{Histogram, HistogramOpts, IntCounter, IntGauge, IntGaugeVec, Opts, Registry};

    #[test]
    fn test_counter_to_json() -> Result<(), Error> {
        let counter =
            IntCounter::with_opts(Opts::new("sample_counter", "sample_counter help message"))?;
        let registry = Registry::new();
        registry.register(Box::new(counter.clone()))?;

        assert_eq!(
            vec![VectorEvent {
                metric: VectorMetric {
                    data: VectorMetricData::Counter { value: 0.0 },
                    kind: "absolute",
                    name: "sample_counter",
                    tags: IndexMap::new(),
                }
            }],
            families_to_json_events(&registry.gather())
        );

        counter.inc_by(42);
        assert_eq!(
            vec![VectorEvent {
                metric: VectorMetric {
                    data: VectorMetricData::Counter { value: 42.0 },
                    kind: "absolute",
                    name: "sample_counter",
                    tags: IndexMap::new(),
                }
            }],
            families_to_json_events(&registry.gather())
        );

        Ok(())
    }

    #[test]
    fn test_gauge_to_json() -> Result<(), Error> {
        let gauge = IntGauge::with_opts(Opts::new("sample_gauge", "sample_gauge help message"))?;
        let registry = Registry::new();
        registry.register(Box::new(gauge.clone()))?;

        assert_eq!(
            vec![VectorEvent {
                metric: VectorMetric {
                    data: VectorMetricData::Gauge { value: 0.0 },
                    kind: "absolute",
                    name: "sample_gauge",
                    tags: IndexMap::new(),
                }
            }],
            families_to_json_events(&registry.gather())
        );

        gauge.set(42);
        assert_eq!(
            vec![VectorEvent {
                metric: VectorMetric {
                    data: VectorMetricData::Gauge { value: 42.0 },
                    kind: "absolute",
                    name: "sample_gauge",
                    tags: IndexMap::new(),
                }
            }],
            families_to_json_events(&registry.gather())
        );

        Ok(())
    }

    #[test]
    fn test_histogram_to_json() -> Result<(), Error> {
        let histogram = Histogram::with_opts(HistogramOpts::new(
            "sample_histogram",
            "sample_histogram help message",
        ))?;
        let registry = Registry::new();
        registry.register(Box::new(histogram.clone()))?;

        let mut value = 0.0;
        while value < 11.0 {
            histogram.observe(value);
            value += 0.001;
        }

        assert_eq!(
            vec![VectorEvent {
                metric: VectorMetric {
                    data: VectorMetricData::AggregatedHistogram {
                        buckets: vec![
                            VectorHistogramBucket {
                                upper_limit: 0.005,
                                count: 6,
                            },
                            VectorHistogramBucket {
                                upper_limit: 0.01,
                                count: 4,
                            },
                            VectorHistogramBucket {
                                upper_limit: 0.025,
                                count: 15,
                            },
                            VectorHistogramBucket {
                                upper_limit: 0.05,
                                count: 25,
                            },
                            VectorHistogramBucket {
                                upper_limit: 0.1,
                                count: 50,
                            },
                            VectorHistogramBucket {
                                upper_limit: 0.25,
                                count: 150,
                            },
                            VectorHistogramBucket {
                                upper_limit: 0.5,
                                count: 250,
                            },
                            VectorHistogramBucket {
                                upper_limit: 1.0,
                                count: 500,
                            },
                            VectorHistogramBucket {
                                upper_limit: 2.5,
                                count: 1501,
                            },
                            VectorHistogramBucket {
                                upper_limit: 5.0,
                                count: 2499,
                            },
                            VectorHistogramBucket {
                                upper_limit: 10.0,
                                count: 5001,
                            },
                        ],
                        count: 11001,
                        sum: 60505.50000000138,
                    },
                    kind: "absolute",
                    name: "sample_histogram",
                    tags: IndexMap::new(),
                }
            }],
            families_to_json_events(&registry.gather())
        );

        Ok(())
    }

    #[test]
    fn test_metric_with_tags_to_json() -> Result<(), Error> {
        let gauge_vec = IntGaugeVec::new(
            Opts::new("sample_gauge", "sample_gauge help message"),
            &["label1", "label2"],
        )?;
        let registry = Registry::new();
        registry.register(Box::new(gauge_vec.clone()))?;

        gauge_vec.with_label_values(&["foo", "1"]).set(42);
        gauge_vec.with_label_values(&["bar", "2"]).set(98);

        assert_eq!(
            vec![
                VectorEvent {
                    metric: VectorMetric {
                        data: VectorMetricData::Gauge { value: 98.0 },
                        kind: "absolute",
                        name: "sample_gauge",
                        tags: [("label1", "bar"), ("label2", "2")]
                            .iter()
                            .copied()
                            .collect(),
                    }
                },
                VectorEvent {
                    metric: VectorMetric {
                        data: VectorMetricData::Gauge { value: 42.0 },
                        kind: "absolute",
                        name: "sample_gauge",
                        tags: [("label1", "foo"), ("label2", "1")]
                            .iter()
                            .copied()
                            .collect(),
                    }
                },
            ],
            families_to_json_events(&registry.gather())
        );

        Ok(())
    }

    #[test]
    fn test_encoding() -> Result<(), Error> {
        let gauge = IntGauge::with_opts(Opts::new("sample_gauge", "sample_gauge help message"))?;
        let registry = Registry::new();
        registry.register(Box::new(gauge.clone()))?;

        let mut output = Vec::new();
        LogEncoder::new().encode(&registry.gather(), &mut output)?;

        assert_eq!(
            b"crates-io-heroku-metrics:ingest W3sibWV0cmljIjp7ImdhdWdlIjp7InZhbHVlIjowLjB9LCJraW5kIjoiYWJzb2x1dGUiLCJuYW1lIjoic2FtcGxlX2dhdWdlIiwidGFncyI6e319fV0=\n",
            output.as_slice(),
        );

        Ok(())
    }
}
<|endoftext|>


<commit_before>#[macro_use]
mod macros;

use std::str::FromStr;

use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Expr, ExprRange};

#[test]
fn test_expr_parse() {
    let code = "..100u32";
    let tt = TokenStream::from_str(code).unwrap();
    let expr: Expr = syn::parse2(tt.clone()).unwrap();
    let expr_range: ExprRange = syn::parse2(tt).unwrap();
    assert_eq!(expr, Expr::Range(expr_range));
}

#[test]
fn test_await() {
    // Must not parse as Expr::Field.
    let expr = syn::parse_str::<Expr>("fut.await").unwrap();

    snapshot!(expr, @r###"
    Expr::Await {
        base: Expr::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "fut",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);
}

#[test]
fn test_macro_variable_func() {
    // mimics the token stream corresponding to `$fn()`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { f })),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Call {
        func: Expr::Group {
            expr: Expr::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "f",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);
}
<commit_msg>Add test for attributes surrounding group expr<commit_after>#[macro_use]
mod macros;

use std::str::FromStr;

use proc_macro2::{Delimiter, Group, Punct, Spacing, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Expr, ExprRange};

#[test]
fn test_expr_parse() {
    let code = "..100u32";
    let tt = TokenStream::from_str(code).unwrap();
    let expr: Expr = syn::parse2(tt.clone()).unwrap();
    let expr_range: ExprRange = syn::parse2(tt).unwrap();
    assert_eq!(expr, Expr::Range(expr_range));
}

#[test]
fn test_await() {
    // Must not parse as Expr::Field.
    let expr = syn::parse_str::<Expr>("fut.await").unwrap();

    snapshot!(expr, @r###"
    Expr::Await {
        base: Expr::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "fut",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);
}

#[test]
fn test_macro_variable_func() {
    // mimics the token stream corresponding to `$fn()`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { f })),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    snapshot!(tokens as Expr, @r###"
    Expr::Call {
        func: Expr::Group {
            expr: Expr::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "f",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);

    let tokens = TokenStream::from_iter(vec![
        TokenTree::Punct(Punct::new('#', Spacing::Alone)),
        TokenTree::Group(Group::new(Delimiter::Bracket, quote! { outside })),
        TokenTree::Group(Group::new(Delimiter::None, quote! { #[inside] f })),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
    ]);

    // FIXME: the #[inside] attribute should go on the Expr::Path not Expr::Call
    snapshot!(tokens as Expr, @r###"
    Expr::Call {
        attrs: [
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "outside",
                            arguments: None,
                        },
                    ],
                },
                tokens: ``,
            },
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "inside",
                            arguments: None,
                        },
                    ],
                },
                tokens: ``,
            },
        ],
        func: Expr::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "f",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);
}
<|endoftext|>