<commit_before>use crate::schema::*;
use diesel::connection::BoxableConnection;
use diesel::*;

table! {
    auto_time {
        id -> Integer,
        n -> Integer,
        updated_at -> Timestamp,
    }
}

#[test]
#[cfg(any(feature = "postgres", feature = "sqlite"))]
fn managing_updated_at_for_table() {
    use self::auto_time::dsl::*;
    use crate::schema_dsl::*;
    use chrono::NaiveDateTime;
    use std::{thread, time::Duration};

    // transactions have frozen time, so we can't use them
    let connection = &mut connection_without_transaction();
    create_table(
        "auto_time",
        (
            integer("id").primary_key().auto_increment(),
            integer("n"),
            timestamp("updated_at"),
        ),
    )
    .execute(connection)
    .unwrap();
    let mut _drop_conn = connection_without_transaction();
    let _guard = DropTable {
        connection: &mut _drop_conn,
        table_name: "auto_time",
        can_drop: !cfg!(feature = "sqlite"),
    };

    sql_query("SELECT diesel_manage_updated_at('auto_time')")
        .execute(connection)
        .unwrap();

    insert_into(auto_time)
        .values(&vec![n.eq(2), n.eq(1), n.eq(5)])
        .execute(connection)
        .unwrap();

    let result = auto_time
        .count()
        .filter(updated_at.is_null())
        .get_result::<i64>(connection);
    assert_eq!(Ok(3), result);

    update(auto_time)
        .set(n.eq(n + 1))
        .execute(connection)
        .unwrap();

    let result = auto_time
        .count()
        .filter(updated_at.is_null())
        .get_result::<i64>(connection);
    assert_eq!(Ok(0), result);

    if cfg!(feature = "sqlite") {
        // SQLite only has second precision
        thread::sleep(Duration::from_millis(1000));
    }

    let query = auto_time.find(2).select(updated_at);
    let old_time: NaiveDateTime = query.first(connection).unwrap();
    update(auto_time.find(2))
        .set(n.eq(0))
        .execute(connection)
        .unwrap();
    let new_time: NaiveDateTime = query.first(connection).unwrap();
    assert!(old_time < new_time);
}

#[test]
#[cfg(feature = "sqlite")]
fn strips_sqlite_url_prefix() {
    let mut path = std::env::temp_dir();
    path.push("diesel_test_sqlite.db");
    assert!(SqliteConnection::establish(&format!("sqlite://{}", path.display())).is_ok());
}

#[test]
#[cfg(feature = "sqlite")]
fn file_uri_created_in_memory() {
    use std::path::Path;

    assert!(SqliteConnection::establish("file::memory:").is_ok());
    assert!(!Path::new("file::memory:").exists());
    assert!(!Path::new(":memory:").exists());
}

#[test]
#[cfg(feature = "sqlite")]
fn sqlite_uri_prefix_interpreted_as_file() {
    let mut path = std::env::temp_dir();
    path.push("diesel_test_sqlite_readonly.db");
    assert!(SqliteConnection::establish(&format!("sqlite://{}?mode=rwc", path.display())).is_ok());
    assert!(path.exists());
}

#[test]
fn boxable_connection_downcast_mut_usable() {
    use crate::schema::users::dsl::*;

    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let boxable = connection as &mut dyn BoxableConnection<TestBackend>;
    let connection = boxable.downcast_mut::<TestConnection>().unwrap();
    let sean = users.select(name).find(1).first(connection);

    assert_eq!(Ok(String::from("Sean")), sean);
}

#[test]
#[cfg(feature = "postgres")]
fn use_the_same_connection_multiple_times() {
    use crate::*;
    use diesel::result::DatabaseErrorKind;
    use diesel::result::Error::DatabaseError;

    table! {
        #[sql_name = "github_issue_3342"]
        github_issue_3342_table {
            id -> Serial,
            uid -> Integer,
        }
    }
    use github_issue_3342_table::dsl::{github_issue_3342_table as github_issue_3342, uid};

    let connection = &mut connection_without_transaction();

    // We can extend `schema_dsl` module to accommodate UNIQUE constraint.
    sql_query(
        r#"
          CREATE TABLE github_issue_3342 (
            id SERIAL PRIMARY KEY,
            uid INTEGER NOT NULL UNIQUE
          )
        "#,
    )
    .execute(connection)
    .unwrap();

    let mut _drop_conn = connection_without_transaction();
    let _guard = DropTable {
        connection: &mut _drop_conn,
        table_name: "github_issue_3342",
        can_drop: true,
    };

    // helper method to simulate database error.
    fn insert_or_fetch(conn: &mut PgConnection, input: i32) {
        let result = insert_into(github_issue_3342)
            .values(uid.eq(input))
            .get_result::<(i32, i32)>(conn);

        match result {
            Ok((_, r)) => assert_eq!(r, input),
            Err(DatabaseError(DatabaseErrorKind::UniqueViolation, _)) => {
                let result = github_issue_3342
                    .filter(uid.eq(input))
                    .first::<(i32, i32)>(conn);
                match result {
                    Ok((_, r)) => assert_eq!(r, input),
                    Err(DatabaseError(DatabaseErrorKind::UnableToSendCommand, message))
                        if message.message() == "another command is already in progress\n" =>
                    {
                        panic!("The fix didn't solve the problem!?")
                    }
                    Err(e) => panic!("Caused by: {}", e),
                }
            }
            Err(DatabaseError(DatabaseErrorKind::UnableToSendCommand, message))
                if message.message() == "another command is already in progress\n" =>
            {
                panic!("The fix didn't solve the problem!?")
            }
            Err(e) => panic!("Caused by: {}", e),
        }
    }

    // simulate multiple queries using the same connection sequentially.
    for _ in 0..5 {
        insert_or_fetch(connection, 1);
    }
}
<commit_msg>move table definition to relevant test method<commit_after>use crate::schema::*;
use diesel::connection::BoxableConnection;
use diesel::*;

#[test]
#[cfg(any(feature = "postgres", feature = "sqlite"))]
fn managing_updated_at_for_table() {
    use crate::schema_dsl::*;
    use chrono::NaiveDateTime;
    use std::{thread, time::Duration};

    table! {
        #[sql_name = "auto_time"]
            auto_time_table {
            id -> Integer,
            n -> Integer,
            updated_at -> Timestamp,
        }
    }
    use auto_time_table::dsl::{auto_time_table as auto_time, n, updated_at};

    // transactions have frozen time, so we can't use them
    let connection = &mut connection_without_transaction();
    create_table(
        "auto_time",
        (
            integer("id").primary_key().auto_increment(),
            integer("n"),
            timestamp("updated_at"),
        ),
    )
    .execute(connection)
    .unwrap();
    let mut _drop_conn = connection_without_transaction();
    let _guard = DropTable {
        connection: &mut _drop_conn,
        table_name: "auto_time",
        can_drop: !cfg!(feature = "sqlite"),
    };

    sql_query("SELECT diesel_manage_updated_at('auto_time')")
        .execute(connection)
        .unwrap();

    insert_into(auto_time)
        .values(&vec![n.eq(2), n.eq(1), n.eq(5)])
        .execute(connection)
        .unwrap();

    let result = auto_time
        .count()
        .filter(updated_at.is_null())
        .get_result::<i64>(connection);
    assert_eq!(Ok(3), result);

    update(auto_time)
        .set(n.eq(n + 1))
        .execute(connection)
        .unwrap();

    let result = auto_time
        .count()
        .filter(updated_at.is_null())
        .get_result::<i64>(connection);
    assert_eq!(Ok(0), result);

    if cfg!(feature = "sqlite") {
        // SQLite only has second precision
        thread::sleep(Duration::from_millis(1000));
    }

    let query = auto_time.find(2).select(updated_at);
    let old_time: NaiveDateTime = query.first(connection).unwrap();
    update(auto_time.find(2))
        .set(n.eq(0))
        .execute(connection)
        .unwrap();
    let new_time: NaiveDateTime = query.first(connection).unwrap();
    assert!(old_time < new_time);
}

#[test]
#[cfg(feature = "sqlite")]
fn strips_sqlite_url_prefix() {
    let mut path = std::env::temp_dir();
    path.push("diesel_test_sqlite.db");
    assert!(SqliteConnection::establish(&format!("sqlite://{}", path.display())).is_ok());
}

#[test]
#[cfg(feature = "sqlite")]
fn file_uri_created_in_memory() {
    use std::path::Path;

    assert!(SqliteConnection::establish("file::memory:").is_ok());
    assert!(!Path::new("file::memory:").exists());
    assert!(!Path::new(":memory:").exists());
}

#[test]
#[cfg(feature = "sqlite")]
fn sqlite_uri_prefix_interpreted_as_file() {
    let mut path = std::env::temp_dir();
    path.push("diesel_test_sqlite_readonly.db");
    assert!(SqliteConnection::establish(&format!("sqlite://{}?mode=rwc", path.display())).is_ok());
    assert!(path.exists());
}

#[test]
fn boxable_connection_downcast_mut_usable() {
    use crate::schema::users::dsl::*;

    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let boxable = connection as &mut dyn BoxableConnection<TestBackend>;
    let connection = boxable.downcast_mut::<TestConnection>().unwrap();
    let sean = users.select(name).find(1).first(connection);

    assert_eq!(Ok(String::from("Sean")), sean);
}

#[test]
#[cfg(feature = "postgres")]
fn use_the_same_connection_multiple_times() {
    use crate::*;
    use diesel::result::DatabaseErrorKind;
    use diesel::result::Error::DatabaseError;

    table! {
        #[sql_name = "github_issue_3342"]
        github_issue_3342_table {
            id -> Serial,
            uid -> Integer,
        }
    }
    use github_issue_3342_table::dsl::{github_issue_3342_table as github_issue_3342, uid};

    let connection = &mut connection_without_transaction();

    // We can extend `schema_dsl` module to accommodate UNIQUE constraint.
    sql_query(
        r#"
          CREATE TABLE github_issue_3342 (
            id SERIAL PRIMARY KEY,
            uid INTEGER NOT NULL UNIQUE
          )
        "#,
    )
    .execute(connection)
    .unwrap();

    let mut _drop_conn = connection_without_transaction();
    let _guard = DropTable {
        connection: &mut _drop_conn,
        table_name: "github_issue_3342",
        can_drop: true,
    };

    // helper method to simulate database error.
    fn insert_or_fetch(conn: &mut PgConnection, input: i32) {
        let result = insert_into(github_issue_3342)
            .values(uid.eq(input))
            .get_result::<(i32, i32)>(conn);

        match result {
            Ok((_, r)) => assert_eq!(r, input),
            Err(DatabaseError(DatabaseErrorKind::UniqueViolation, _)) => {
                let result = github_issue_3342
                    .filter(uid.eq(input))
                    .first::<(i32, i32)>(conn);
                match result {
                    Ok((_, r)) => assert_eq!(r, input),
                    Err(DatabaseError(DatabaseErrorKind::UnableToSendCommand, message))
                        if message.message() == "another command is already in progress\n" =>
                    {
                        panic!("The fix didn't solve the problem!?")
                    }
                    Err(e) => panic!("Caused by: {}", e),
                }
            }
            Err(DatabaseError(DatabaseErrorKind::UnableToSendCommand, message))
                if message.message() == "another command is already in progress\n" =>
            {
                panic!("The fix didn't solve the problem!?")
            }
            Err(e) => panic!("Caused by: {}", e),
        }
    }

    // simulate multiple queries using the same connection sequentially.
    for _ in 0..5 {
        insert_or_fetch(connection, 1);
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate exonum;
extern crate test;

#[cfg(all(test, feature = "long_benchmarks"))]
#[cfg(test)]
mod tests {
    use test::Bencher;

    use std::net::SocketAddr;

    use exonum::node::EventsPoolCapacity;
    use exonum::events::network::NetworkConfiguration;
    use exonum::events::tests::{connect_message, raw_message, TestEvents, TestHandler};

    struct BenchConfig {
        times: usize,
        len: usize,
        tcp_nodelay: bool,
    }

    fn test_events(cfg: &BenchConfig, listen_address: SocketAddr) -> TestEvents {
        let network_config = NetworkConfiguration {
            tcp_nodelay: cfg.tcp_nodelay,
            ..Default::default()
        };
        TestEvents {
            listen_address,
            network_config,
            events_config: EventsPoolCapacity::default(),
        }
    }

    fn bench_network(b: &mut Bencher, addrs: [SocketAddr; 2], cfg: &BenchConfig) {
        b.iter(|| {
            let times = cfg.times;
            let len = cfg.len;

            let c1 = connect_message(addrs[0]);
            let c2 = connect_message(addrs[1]);

            let t1 = test_events(cfg, addrs[0]).spawn(move |e: &mut TestHandler| {
                e.connect_with(addrs[1]);
                assert_eq!(e.wait_for_connect(), c2);
                for _ in 0..times {
                    let msg = raw_message(0, len);
                    e.send_to(addrs[1], msg);
                    e.wait_for_message();
                }
                e.disconnect_with(addrs[1]);
                assert_eq!(e.wait_for_disconnect(), addrs[1]);
            });
            let t2 = test_events(cfg, addrs[1]).spawn(move |e: &mut TestHandler| {
                assert_eq!(e.wait_for_connect(), c1);
                e.connect_with(addrs[0]);
                for _ in 0..times {
                    let msg = raw_message(1, len);
                    e.send_to(addrs[0], msg);
                    e.wait_for_message();
                }
                assert_eq!(e.wait_for_disconnect(), addrs[0]);
            });

            t1.join().unwrap();
            t2.join().unwrap();
        })
    }

    #[bench]
    fn bench_msg_short_100(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 100,
            times: 100,
        };
        let addrs = ["127.0.0.1:6990".parse().unwrap(), "127.0.0.1:6991".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_short_1000(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 1000,
            times: 1000,
        };
        let addrs = ["127.0.0.1:9792".parse().unwrap(), "127.0.0.1:9793".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_short_10_000(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 1000,
            times: 10_000,
        };
        let addrs = ["127.0.0.1:9792".parse().unwrap(), "127.0.0.1:9793".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_short_100_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100,
            times: 100,
        };
        let addrs = ["127.0.0.1:4990".parse().unwrap(), "127.0.0.1:4991".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_short_1000_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100,
            times: 1000,
        };
        let addrs = ["127.0.0.1:5990".parse().unwrap(), "127.0.0.1:5991".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_short_10_000_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100,
            times: 10_000,
        };
        let addrs = ["127.0.0.1:5990".parse().unwrap(), "127.0.0.1:5991".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_long_10(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 100_000,
            times: 10,
        };
        let addrs = ["127.0.0.1:9984".parse().unwrap(), "127.0.0.1:9985".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_long_100(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 100_000,
            times: 100,
        };
        let addrs = ["127.0.0.1:9946".parse().unwrap(), "127.0.0.1:9947".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_long_10_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100_000,
            times: 10,
        };
        let addrs = ["127.0.0.1:9198".parse().unwrap(), "127.0.0.1:9199".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_long_100_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100_000,
            times: 100,
        };
        let addrs = ["127.0.0.1:9198".parse().unwrap(), "127.0.0.1:9199".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }
}
<commit_msg>Fix network benches for tokio<commit_after>#![feature(test)]

extern crate exonum;
extern crate test;

#[cfg(all(test, feature = "long_benchmarks"))]
#[cfg(test)]
mod tests {
    use test::Bencher;

    use std::net::SocketAddr;
    use std::thread;

    use exonum::node::EventsPoolCapacity;
    use exonum::events::network::NetworkConfiguration;
    use exonum::events::tests::{connect_message, raw_message, TestEvents};

    struct BenchConfig {
        times: usize,
        len: usize,
        tcp_nodelay: bool,
    }

    fn test_events(cfg: &BenchConfig, listen_address: SocketAddr) -> TestEvents {
        let network_config = NetworkConfiguration {
            tcp_nodelay: cfg.tcp_nodelay,
            ..Default::default()
        };
        TestEvents {
            listen_address,
            network_config,
            events_config: EventsPoolCapacity::default(),
        }
    }

    fn bench_network(b: &mut Bencher, addrs: [SocketAddr; 2], cfg: &BenchConfig) {
        b.iter(|| {
            let times = cfg.times;
            let len = cfg.len;
            let first = addrs[0];
            let second = addrs[1];

            let c1 = connect_message(first);
            let c2 = connect_message(second);

            let mut t1 = test_events(cfg, first).spawn();
            let mut t2 = test_events(cfg, second).spawn();

            t1.connect_with(second);
            t2.connect_with(first);
            assert_eq!(t1.wait_for_connect(), c2);
            assert_eq!(t2.wait_for_connect(), c1);

            let t1 = thread::spawn(move || {
                for _ in 0..times {
                    let msg = raw_message(0, len);
                    t1.send_to(second, msg);
                    t1.wait_for_message();
                }
                t1
            });

            let t2 = thread::spawn(move || {
                for _ in 0..times {
                    let msg = raw_message(1, len);
                    t2.send_to(first, msg);
                    t2.wait_for_message();
                }
                t2
            });

            let mut t1 = t1.join().unwrap();
            let mut t2 = t2.join().unwrap();

            t1.disconnect_with(second);
            t2.disconnect_with(first);

            assert_eq!(t1.wait_for_disconnect(), second);
            assert_eq!(t2.wait_for_disconnect(), first);

            drop(t1);
            drop(t2);
        })
    }

    #[bench]
    fn bench_msg_short_100(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 100,
            times: 100,
        };
        let addrs = ["127.0.0.1:6990".parse().unwrap(), "127.0.0.1:6991".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_short_1000(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 1000,
            times: 1000,
        };
        let addrs = ["127.0.0.1:9792".parse().unwrap(), "127.0.0.1:9793".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_short_10_000(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 1000,
            times: 10_000,
        };
        let addrs = ["127.0.0.1:9792".parse().unwrap(), "127.0.0.1:9793".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_short_100_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100,
            times: 100,
        };
        let addrs = ["127.0.0.1:4990".parse().unwrap(), "127.0.0.1:4991".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_short_1000_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100,
            times: 1000,
        };
        let addrs = ["127.0.0.1:5990".parse().unwrap(), "127.0.0.1:5991".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_short_10_000_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100,
            times: 10_000,
        };
        let addrs = ["127.0.0.1:5990".parse().unwrap(), "127.0.0.1:5991".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_long_10(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 100_000,
            times: 10,
        };
        let addrs = ["127.0.0.1:9984".parse().unwrap(), "127.0.0.1:9985".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_long_100(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: false,
            len: 100_000,
            times: 100,
        };
        let addrs = ["127.0.0.1:9946".parse().unwrap(), "127.0.0.1:9947".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_long_10_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100_000,
            times: 10,
        };
        let addrs = ["127.0.0.1:9198".parse().unwrap(), "127.0.0.1:9199".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }

    #[bench]
    fn bench_msg_long_100_nodelay(b: &mut Bencher) {
        let cfg = BenchConfig {
            tcp_nodelay: true,
            len: 100_000,
            times: 100,
        };
        let addrs = ["127.0.0.1:9198".parse().unwrap(), "127.0.0.1:9199".parse().unwrap()];
        bench_network(b, addrs, &cfg);
    }
}
<|endoftext|>


<commit_before>extern crate time;

use std::rand::{Rng, SeedableRng, StdRng};
use std::collections::HashMap;
use time::precise_time_ns;
use std::io::{File, BufferedReader};
use std::fmt;

pub type Node = uint;

#[deriving(Show)]
pub struct NodePt {
    id: Node,
    x: f64,
    y: f64
}

impl NodePt {
    fn new(nodeId: Node, x: f64, y: f64) -> NodePt {
        NodePt {
            id: nodeId,
            x: x,
            y: y
        }
    }

    fn distance_to(self, other: NodePt) -> f64 {
        let xx = (self.x - other.x) * (self.x - other.x);
        let yy = (self.y - other.y) * (self.y - other.y);

        (xx+yy).sqrt()
    }
}

impl PartialEq for NodePt {
    fn eq(&self, other: &NodePt) -> bool {
        self.id == other.id
    }

    fn ne(&self, other: &NodePt) -> bool {
        self.id != other.id
    }
}

#[deriving(Show, Clone)]
pub struct Edge {
    from: Node,
    to: Node,
    weight: f64
}

impl Edge {
    fn new(a: NodePt, b: NodePt) -> Edge {
        Edge {
            from: a.id,
            to: b.id,
            weight: a.distance_to(b)
        }
    }
}

#[deriving(Show, Clone)]
pub struct Tour {
    nodes: Vec<Node>,
    total_weight: f64
}

impl PartialEq for Tour {
    fn eq(&self, other: &Tour) -> bool {
        self.nodes == other.nodes
    }

    fn ne(&self, other: &Tour) -> bool {
        self.nodes != other.nodes
    }
}

impl PartialOrd for Tour {
    fn lt(&self, other: &Tour) -> bool {
        self.total_weight < other.total_weight
    }
}

impl Tour {
    fn new(nodes: Vec<Node>, weight: f64) -> Tour {
        Tour {
            nodes: nodes,
            total_weight: weight
        }
    }

    fn calc_tour_weight(tour: &Vec<Node>, graph: &Graph) -> f64 {
        let mut tour_weight = 0.0;
        let mut last_node = tour.get(0u);

        for node in tour.iter() {
            tour_weight += graph.get(*last_node, *node);
            last_node = node;
        }

        tour_weight
    }

    fn random_tour<R: Rng>(rng: &mut R, graph: &Graph) -> Tour {
        let mut tour_nodes = graph.nodes();
        rng.shuffle(tour_nodes.as_mut_slice());
        let last: Node = *tour_nodes.last().unwrap();
        tour_nodes.insert(0, last);
        let tour_weight = Tour::calc_tour_weight(&tour_nodes, graph);
        Tour::new(tour_nodes, tour_weight)
    }

    fn mutate<R: Rng>(&self, rng: &mut R, graph: &Graph, mutation_rate: f64) -> Tour {
        let size = self.nodes.len() as f64;
        let mut mutated: Vec<Node> = self.nodes.clone();

        for i in range(0, self.nodes.len()) {
            let t = rng.gen::<f64>();
            if t < mutation_rate {
                let j = (rng.gen::<f64>() * size) as uint;
                mutated.as_mut_slice().swap(i, j);
            }
        }
        let weight = Tour::calc_tour_weight(&mutated, graph);
        Tour {
            nodes: mutated,
            total_weight: weight
        }
    }

    fn crossover<R: Rng>(&self, other: Tour, graph: &Graph, rng: &mut R) -> Tour {
        let size = self.nodes.len();
        let mut start = (rng.gen::<f64>() * (size as f64)) as uint;
        let mut end = (rng.gen::<f64>() * (size as f64)) as uint;
        if start == end {
            return self.clone()
        }

        if end > start {
            std::mem::swap(&mut start, &mut end);
        }

        let new_tour = Vec::from_fn(size, |i| {
            if i >= start && i <= end {
                *self.nodes.get(i)
            } else {
                *other.nodes.get(i)
            }
        });

        let tour_weight = Tour::calc_tour_weight(&new_tour, graph);
        Tour::new(new_tour, tour_weight)
    }
}

#[deriving(Show, Clone)]
pub struct Graph {
    adj_list: HashMap<Node, Vec<Edge>>
}

impl Graph {
    fn new(adj_list: HashMap<Node, Vec<Edge>>) -> Graph {
        Graph {
            adj_list: adj_list
        }
    }

    fn from_nodes(nodes: Vec<NodePt>) -> Graph {
        let mut map: HashMap<Node, Vec<Edge>> = HashMap::new();
        for i in range(0, nodes.len()) {
            let mut adj_edges: Vec<Edge> = Vec::new();

            for j in range(0, nodes.len()) {
                let a = nodes.get(i);
                let b = nodes.get(j);
                if i != j {
                    adj_edges.push(Edge::new(*a, *b));
                }
            }

            map.insert(i, adj_edges);
        }

        Graph::new(map)
    }

    fn random_graph<R: Rng>(rng: &mut R, num_nodes: uint, x_max: f64, y_max: f64) -> Graph {
        let points = rng.gen_iter::<(f64, f64)>()
            .enumerate()
            .map(|(idx, (x, y))| NodePt::new(idx, x * x_max, y * y_max))
            .take(num_nodes)
            .collect();

        Graph::from_nodes(points)
    }

    fn get(&self, n: Node, m: Node) -> f64 {
        if n == m {
            0.0
        } else {
            let edges = self.adj_list.get(&n);
            let result = edges.iter().filter(|edge| edge.to == m).nth(0);
            match result {
                Some(edge) => edge.weight,
                None => fail!("No edge found!")
            }
        }
    }

    fn size(&self) -> uint {
        self.adj_list.len()
    }

    fn nodes(&self) -> Vec<Node> {
        range(0, self.size()).collect()
    }

    #[allow(dead_code)]
    fn from_file(file_path: &str) -> Graph {
        let path = Path::new(file_path);
        let mut file = BufferedReader::new(File::open(&path));
        let mut nodes: Vec<NodePt> = Vec::new();
        let mut i = 0u;

        for line in file.lines() {
            let mut numbers: Vec<f64> = Vec::new();
            // This could be a lot nicer
            match line {
                Ok(val) => {
                    for token in val.as_slice().split(' ') {
                        if token == "\n" {
                            continue
                        }

                        let n = match from_str::<f64>(token) {
                            Some(num) => num,
                            None => continue
                        };
                        numbers.push(n);
                    }
                },
                Err(_) => fail!("Failed reading file.")
            }

            if numbers.len() == 2 {
                let point = NodePt::new(i, *numbers.get(0), *numbers.get(1));
                nodes.push(point);
            }

            i += 1;
        }

        Graph::from_nodes(nodes)
    }
}

struct Population {
    rng: StdRng,
    graph: Box<Graph>,
    population: Vec<Tour>,
    mutation_rate: f64,
    tournament_size: uint
}

impl Population {
    fn new(population_count: uint, graph: Box<Graph>, mutation_rate: f64, tournament_size: uint, mut rng: StdRng) -> Population {
        let population = Vec::from_fn(population_count, |_| Tour::random_tour(&mut rng, graph));

        Population {
            rng: rng,
            graph: graph,
            population: population,
            mutation_rate: mutation_rate,
            tournament_size: tournament_size
        }
    }

    fn fittest(&self) -> Tour {
        find_min(&self.population)
    }

    fn tournament_selection(&mut self) -> Tour {
        let size = self.population.len();
        let mut buffer: Vec<Tour> = Vec::new();
        for _ in range(0, self.tournament_size) {
            let t = (self.rng.gen::<f64>() * (size as f64)) as uint;
            buffer.push(self.population.get(t).clone());
        }
        find_min(&buffer)
    }

    fn evolve(&mut self) -> Population {
        let mut new_population: Vec<Tour> = Vec::new();

        for _ in range(0, self.population.len()) {
            let parent1 = self.tournament_selection();
            let parent2 = self.tournament_selection();
            let child: Tour = parent1.crossover(parent2, self.graph, &mut self.rng);
            new_population.push(child);
        }

        let mutated = new_population.iter().map(|tour| tour.mutate(&mut self.rng, self.graph, self.mutation_rate)).collect();

        Population {
            rng: self.rng,
            graph: self.graph.clone(),
            population: mutated,
            mutation_rate: self.mutation_rate,
            tournament_size: self.tournament_size
        }
    }
}

impl fmt::Show for Population {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Population: {}", self.population)
    }
}

fn find_min<E: PartialOrd+Clone>(xs: &Vec<E>) -> E {
    let ref min = *xs.iter().fold(xs.get(0), |min, next| if next < min {next} else {min});
    min.clone()
}

fn main() {
    // let mut rng: StdRng = match StdRng::new() {
    //     Ok(r) => r,
    //     Err(why) => fail!("failed to acquire RNG")
    // };
    let mut rng: StdRng = SeedableRng::from_seed(&[12, 13, 14, 15]);
    let graph = Graph::random_graph(&mut rng, 25, 200.0, 200.0);
    let mut pop = Population::new(5000, box graph, 0.03, 5, rng);
    println!("Fittest at start: {}", pop.fittest())

    let t0 = precise_time_ns();
    for _ in range(0, 100) {
        pop = pop.evolve();
    }
    let t1 = precise_time_ns();

    println!("Fittest at end: {}", pop.fittest())
    let dt = ((t1-t0) as f64) / 1e6;
    println!("t_avg = {} ms", dt / 100.0);
}<commit_msg>added todos<commit_after>extern crate time;

use std::rand::{Rng, SeedableRng, StdRng};
use std::collections::HashMap;
use time::precise_time_ns;
use std::io::{File, BufferedReader};
use std::fmt;

pub type Node = uint;

#[deriving(Show)]
pub struct NodePt {
    id: Node,
    x: f64,
    y: f64
}

impl NodePt {
    fn new(nodeId: Node, x: f64, y: f64) -> NodePt {
        NodePt {
            id: nodeId,
            x: x,
            y: y
        }
    }

    fn distance_to(self, other: NodePt) -> f64 {
        let xx = (self.x - other.x) * (self.x - other.x);
        let yy = (self.y - other.y) * (self.y - other.y);

        (xx+yy).sqrt()
    }
}

impl PartialEq for NodePt {
    fn eq(&self, other: &NodePt) -> bool {
        self.id == other.id
    }

    fn ne(&self, other: &NodePt) -> bool {
        self.id != other.id
    }
}

#[deriving(Show, Clone)]
pub struct Edge {
    from: Node,
    to: Node,
    weight: f64
}

impl Edge {
    fn new(a: NodePt, b: NodePt) -> Edge {
        Edge {
            from: a.id,
            to: b.id,
            weight: a.distance_to(b)
        }
    }
}

#[deriving(Show, Clone)]
pub struct Tour {
    nodes: Vec<Node>,
    total_weight: f64
}

impl PartialEq for Tour {
    fn eq(&self, other: &Tour) -> bool {
        self.nodes == other.nodes
    }

    fn ne(&self, other: &Tour) -> bool {
        self.nodes != other.nodes
    }
}

impl PartialOrd for Tour {
    fn lt(&self, other: &Tour) -> bool {
        self.total_weight < other.total_weight
    }
}

impl Tour {
    fn new(nodes: Vec<Node>, weight: f64) -> Tour {
        Tour {
            nodes: nodes,
            total_weight: weight
        }
    }

    // TODO add weight between first and last node to the tour weight
    fn calc_tour_weight(tour: &Vec<Node>, graph: &Graph) -> f64 {
        let mut tour_weight = 0.0;
        let mut last_node = tour.get(0u);

        for node in tour.iter() {
            tour_weight += graph.get(*last_node, *node);
            last_node = node;
        }

        tour_weight
    }
    // TODO for ease of crossover between tours, don't add the
    //      first node again
    fn random_tour<R: Rng>(rng: &mut R, graph: &Graph) -> Tour {
        let mut tour_nodes = graph.nodes();
        rng.shuffle(tour_nodes.as_mut_slice());
        let last: Node = *tour_nodes.last().unwrap();
        tour_nodes.insert(0, last);
        let tour_weight = Tour::calc_tour_weight(&tour_nodes, graph);
        Tour::new(tour_nodes, tour_weight)
    }

    fn mutate<R: Rng>(&self, rng: &mut R, graph: &Graph, mutation_rate: f64) -> Tour {
        let size = self.nodes.len() as f64;
        let mut mutated: Vec<Node> = self.nodes.clone();

        for i in range(0, self.nodes.len()) {
            let t = rng.gen::<f64>();
            if t < mutation_rate {
                let j = (rng.gen::<f64>() * size) as uint;
                mutated.as_mut_slice().swap(i, j);
            }
        }
        let weight = Tour::calc_tour_weight(&mutated, graph);
        Tour {
            nodes: mutated,
            total_weight: weight
        }
    }

    fn crossover<R: Rng>(&self, other: Tour, graph: &Graph, rng: &mut R) -> Tour {
        let size = self.nodes.len();
        let mut start = (rng.gen::<f64>() * (size as f64)) as uint;
        let mut end = (rng.gen::<f64>() * (size as f64)) as uint;
        if start == end {
            return self.clone()
        }

        if end > start {
            std::mem::swap(&mut start, &mut end);
        }
        // TODO fix this (produces invalid tours)
        let new_tour = Vec::from_fn(size, |i| {
            if i >= start && i <= end {
                *self.nodes.get(i)
            } else {
                *other.nodes.get(i)
            }
        });

        let tour_weight = Tour::calc_tour_weight(&new_tour, graph);
        Tour::new(new_tour, tour_weight)
    }
}

#[deriving(Show, Clone)]
pub struct Graph {
    adj_list: HashMap<Node, Vec<Edge>>
}

impl Graph {
    fn new(adj_list: HashMap<Node, Vec<Edge>>) -> Graph {
        Graph {
            adj_list: adj_list
        }
    }

    fn from_nodes(nodes: Vec<NodePt>) -> Graph {
        let mut map: HashMap<Node, Vec<Edge>> = HashMap::new();
        for i in range(0, nodes.len()) {
            let mut adj_edges: Vec<Edge> = Vec::new();

            for j in range(0, nodes.len()) {
                let a = nodes.get(i);
                let b = nodes.get(j);
                if i != j {
                    adj_edges.push(Edge::new(*a, *b));
                }
            }

            map.insert(i, adj_edges);
        }

        Graph::new(map)
    }

    fn random_graph<R: Rng>(rng: &mut R, num_nodes: uint, x_max: f64, y_max: f64) -> Graph {
        let points = rng.gen_iter::<(f64, f64)>()
            .enumerate()
            .map(|(idx, (x, y))| NodePt::new(idx, x * x_max, y * y_max))
            .take(num_nodes)
            .collect();

        Graph::from_nodes(points)
    }

    fn get(&self, n: Node, m: Node) -> f64 {
        if n == m {
            0.0
        } else {
            let edges = self.adj_list.get(&n);
            let result = edges.iter().filter(|edge| edge.to == m).nth(0);
            match result {
                Some(edge) => edge.weight,
                None => fail!("No edge found!")
            }
        }
    }

    fn size(&self) -> uint {
        self.adj_list.len()
    }

    fn nodes(&self) -> Vec<Node> {
        range(0, self.size()).collect()
    }

    #[allow(dead_code)]
    fn from_file(file_path: &str) -> Graph {
        let path = Path::new(file_path);
        let mut file = BufferedReader::new(File::open(&path));
        let mut nodes: Vec<NodePt> = Vec::new();
        let mut i = 0u;

        for line in file.lines() {
            let mut numbers: Vec<f64> = Vec::new();
            // This could be a lot nicer
            match line {
                Ok(val) => {
                    for token in val.as_slice().split(' ') {
                        if token == "\n" {
                            continue
                        }

                        let n = match from_str::<f64>(token) {
                            Some(num) => num,
                            None => continue
                        };
                        numbers.push(n);
                    }
                },
                Err(_) => fail!("Failed reading file.")
            }

            if numbers.len() == 2 {
                let point = NodePt::new(i, *numbers.get(0), *numbers.get(1));
                nodes.push(point);
            }

            i += 1;
        }

        Graph::from_nodes(nodes)
    }
}

struct Population {
    rng: StdRng,
    graph: Box<Graph>,
    population: Vec<Tour>,
    mutation_rate: f64,
    tournament_size: uint
}

impl Population {
    fn new(population_count: uint, graph: Box<Graph>, mutation_rate: f64, tournament_size: uint, mut rng: StdRng) -> Population {
        let population = Vec::from_fn(population_count, |_| Tour::random_tour(&mut rng, graph));

        Population {
            rng: rng,
            graph: graph,
            population: population,
            mutation_rate: mutation_rate,
            tournament_size: tournament_size
        }
    }

    fn fittest(&self) -> Tour {
        find_min(&self.population)
    }

    fn tournament_selection(&mut self) -> Tour {
        let size = self.population.len();
        let mut buffer: Vec<Tour> = Vec::new();
        for _ in range(0, self.tournament_size) {
            let t = (self.rng.gen::<f64>() * (size as f64)) as uint;
            buffer.push(self.population.get(t).clone());
        }
        find_min(&buffer)
    }

    fn evolve(&mut self) -> Population {
        let mut new_population: Vec<Tour> = Vec::new();

        for _ in range(0, self.population.len()) {
            let parent1 = self.tournament_selection();
            let parent2 = self.tournament_selection();
            let child: Tour = parent1.crossover(parent2, self.graph, &mut self.rng);
            new_population.push(child);
        }

        let mutated = new_population.iter().map(|tour| tour.mutate(&mut self.rng, self.graph, self.mutation_rate)).collect();

        Population {
            rng: self.rng,
            graph: self.graph.clone(),
            population: mutated,
            mutation_rate: self.mutation_rate,
            tournament_size: self.tournament_size
        }
    }
}

impl fmt::Show for Population {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Population: {}", self.population)
    }
}

fn find_min<E: PartialOrd+Clone>(xs: &Vec<E>) -> E {
    let ref min = *xs.iter().fold(xs.get(0), |min, next| if next < min {next} else {min});
    min.clone()
}

fn main() {
    // let mut rng: StdRng = match StdRng::new() {
    //     Ok(r) => r,
    //     Err(why) => fail!("failed to acquire RNG")
    // };
    let mut rng: StdRng = SeedableRng::from_seed(&[12, 13, 14, 15]);
    let graph = Graph::random_graph(&mut rng, 10, 200.0, 200.0);
    //let graph = Graph::from_file("graph.txt");

    let mut pop = Population::new(10000, box graph, 0.01, 15, rng);
    println!("Fittest at start: {}", pop.fittest())

    let t0 = precise_time_ns();
    for _ in range(0, 100) {
        pop = pop.evolve();
    }
    let t1 = precise_time_ns();

    println!("Fittest at end: {}", pop.fittest())
    let dt = ((t1-t0) as f64) / 1e6;
    println!("t_avg = {} ms", dt / 100.0);
}<|endoftext|>


<commit_before>//! lint when there is an enum with no variants

use rustc::lint::*;
use rustc::hir::*;
use utils::span_lint_and_then;

/// **What it does:** Checks for `enum`s with no variants.
///
/// **Why is this bad?** Enum's with no variants should be replaced with `!`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// enum Test {}
/// ```
declare_lint! {
    pub EMPTY_ENUM,
    Allow,
    "enum with no variants"
}

#[derive(Copy,Clone)]
pub struct EmptyEnum;

impl LintPass for EmptyEnum {
    fn get_lints(&self) -> LintArray {
        lint_array!(EMPTY_ENUM)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum {
    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        let did = cx.tcx.hir.local_def_id(item.id);
        if let ItemEnum(..) = item.node {
            let ty = cx.tcx.item_type(did);
            let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
            if adt.variants.is_empty() {
                span_lint_and_then(cx, EMPTY_ENUM, item.span, "enum with no variants", |db| {
                    db.span_help(item.span,
                                 "consider using the uninhabited type `!` or a wrapper around it");
                });
            }
        }
    }
}
<commit_msg>Suggest to use a wrapper in the wiki for the empty_enum lint<commit_after>//! lint when there is an enum with no variants

use rustc::lint::*;
use rustc::hir::*;
use utils::span_lint_and_then;

/// **What it does:** Checks for `enum`s with no variants.
///
/// **Why is this bad?** Enum's with no variants should be replaced with `!`, the uninhabited type,
/// or a wrapper around it.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// enum Test {}
/// ```
declare_lint! {
    pub EMPTY_ENUM,
    Allow,
    "enum with no variants"
}

#[derive(Copy,Clone)]
pub struct EmptyEnum;

impl LintPass for EmptyEnum {
    fn get_lints(&self) -> LintArray {
        lint_array!(EMPTY_ENUM)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum {
    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        let did = cx.tcx.hir.local_def_id(item.id);
        if let ItemEnum(..) = item.node {
            let ty = cx.tcx.item_type(did);
            let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
            if adt.variants.is_empty() {
                span_lint_and_then(cx, EMPTY_ENUM, item.span, "enum with no variants", |db| {
                    db.span_help(item.span,
                                 "consider using the uninhabited type `!` or a wrapper around it");
                });
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(proc_macro, conservative_impl_trait, generators)]
extern crate bytes;
extern crate futures_await as futures;
extern crate tokio_core;
extern crate tokio_io;

mod cmd;
mod ftp;
mod error;
mod codec;

use std::result;
use std::io;
use std::env;
use futures::prelude::*;
use tokio_core::reactor::Core;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use tokio_core::reactor::Handle;
use tokio_core::net::TcpListener;

use tokio_core::net::TcpStream;

use futures::{Sink, Stream};
use futures::stream::SplitSink;

use tokio_io::AsyncRead;
use tokio_io::codec::Framed;
use codec::FtpCodec;
use error::Result;
use ftp::{Answer, ResultCode};
use std::path::PathBuf;
use std::path::StripPrefixError;

use futures::stream::SplitStream;
use codec::BytesCodec;

use cmd::Command;
use cmd::TransferType;

use std::ffi::OsString;
use std::fs::{create_dir, remove_dir_all};

type DataReader = SplitStream<Framed<TcpStream, BytesCodec>>;
type DataWriter = SplitSink<Framed<TcpStream,BytesCodec>>;
type Writer = SplitSink<Framed<TcpStream, FtpCodec>>;

fn get_parent(path: PathBuf) -> Option<PathBuf> {
    path.parent().map(|p| p.to_path_buf())
}

fn get_filename(path: PathBuf) -> Option<OsString> {
    path.file_name().map(|p| p.to_os_string())
}

struct Client {
    data_port: Option<u16>,
    data_reader: Option<DataReader>,
    data_writer: Option<DataWriter>,
    handle: Handle,
    cwd: PathBuf,
    server_root: PathBuf,
    transfer_type: TransferType,
    writer: Writer,
}

impl Client {
    fn new(handle: Handle, writer: Writer, server_root: PathBuf) -> Client {
        Client {
            data_port: None,
            data_reader: None,
            data_writer: None,
            handle,
            cwd: PathBuf::from("/"),
            server_root,
            transfer_type: TransferType::Ascii,
            writer,
        }
    }
    #[async]
    fn send(mut self, answer: Answer) -> Result<Self> {
        self.writer = await!(self.writer.send(answer))?;
        Ok(self)
    }

    fn complete_path(self, path: PathBuf) -> (Self, result::Result<PathBuf, io::Error>) {
        let directory = self.server_root.join(if path.has_root() {
                path.iter().skip(1).collect()
            } else {
                path
        });
        let dir = directory.canonicalize();
        if let Ok(ref dir) = dir {
            if !dir.starts_with(&self.server_root) {
                return (self, Err(io::ErrorKind::PermissionDenied.into()));
            }
        }
        (self,dir)
    }
    fn strip_prefix(self, dir:PathBuf) -> (Self, result::Result<PathBuf, StripPrefixError>) {
        let res = dir.strip_prefix(&self.server_root).map(|p| p.to_path_buf());
        (self,res)
    }

    #[async]
    fn cwd(mut self, directory: PathBuf) -> Result<Self>{
        let path = self.cwd.join(&directory);
        let (new_self, res) = self.complete_path(path);
        self = new_self;
        if let Ok(dir) = res {
            let (new_self, res) = self.strip_prefix(dir);
            self = new_self;
            if let Ok(prefix) = res {
                self.cwd = prefix.to_path_buf();
                self = await!(self.send(Answer::new(ResultCode::Ok, &format!("Directory changed to \"{}\"", directory.display()))))?;
                return Ok(self)
            }
        }
        self = await!(self.send(Answer::new(ResultCode::FileNotFound, "No such file or directory")))?;
        return Ok(self);
    }
    #[async]
    fn pasv(mut self) -> Result<Self> {
        let port =
            if let Some(port) = self.data_port {
                port
             } else {
                0
             };
        if self.data_writer.is_some() {
            self = await!(self.send(Answer::new(ResultCode::DataConnectionAlreadyOpen,"Already listening...")))?;
            return Ok(self);
        }

        let addr= SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127,0,0,1)),port);
        let listener = TcpListener::bind(&addr, &self.handle)?;
        let port = listener.local_addr()?.port();

        self = await!(self.send(Answer::new(ResultCode::EnteringPassiveMode, &format!("127,0,0,1,{},{}", port>>8, port & 0xFF))))?;

        println!("Waiting clients on the port {}...", port);

        #[async]
        for(stream, _rest) in listener.incoming()  {
            let (writer, reader) = stream.framed(BytesCodec).split();
            self.data_writer = Some(writer);
            self.data_reader = Some(reader);
            break;
        }
        Ok(self)
    }

    #[async]
    fn quit(mut self) -> Result<Self> {
        if self.data_writer.is_some() {
            unimplemented!();
        } else {
            self = await!(self.send(Answer::new(ResultCode::ServiceClosingControlConnection, "Closing connection...")))?;
            self.writer.close()?;
        }
        Ok(self)
    }

    #[async]
    fn mkd(mut self, path: PathBuf) -> Result<Self> {
        let path = self.cwd.join(&path);
        let parent = get_parent(path.clone());
        if let Some(parent) = parent {
            let parent = parent.to_path_buf();
            let(new_self, res) = self.complete_path(parent);
            self = new_self;
            if let Ok(mut dir) = res {
                if dir.is_dir() {
                    let filename = get_filename(path);
                    if let Some(filename) = filename {
                        dir.push(filename);
                        if create_dir(dir).is_ok() {
                            self = await!(self.send(Answer::new(ResultCode::PATHNAMECreated,"Folder sucessfully crated!")))?;
                            return Ok(self);
                        }
                    }
                }
            }
        }
        self = await!(self.send(Answer::new(ResultCode::FileNotFound, "Could not create folder")))?;
        Ok(self)
    }

    #[async]
    fn rmd(mut self, directory: PathBuf) -> Result<Self> {
        let path = self.cwd.join(&directory);
        let (new_self, res) = self.complete_path(path);
        self = new_self;
        if let Ok(dir) = res {
            if remove_dir_all(dir).is_ok() {
                self = await!(self.send(Answer::new(ResultCode::RequestedFileActionOkay,
                                                    "Folder successfully removed")))?;
                return Ok(self);
            }
        }
        self = await!(self.send(Answer::new(ResultCode::FileNotFound,
                                            "Couldn't remove folder")))?;
        Ok(self)
    }

    #[async]
    fn handle_cmd(mut self, cmd: Command) -> Result<Self> {
        println!("Received command: {:?}", cmd);
        match cmd {
            Command::Mkd(path) => self = await!(self.mkd(path))?,
            Command::Rmd(path) => self = await!(self.rmd(path))?,
            Command::Quit => self = await!(self.quit())?,
            Command::Pasv => self = await!(self.pasv())?,
            Command::Type(typ) => {
                self.transfer_type = typ;
                self = await!(self.send(Answer::new(ResultCode::Ok, "Transfer type changed successfully")))?;
            },
            Command::Cwd(directory) => {
                self= await!(self.cwd(directory))?;
            },
            Command::User(content) => {
                if content.is_empty() {
                    self = await!(self.send(Answer::new(ResultCode::InvalidParameterOrArgument,"Invalid username")))?;
                } else {
                    self = await!(self.send(Answer::new(ResultCode::UserloggedIn,&format!("Welcome {}",content))))?;
                }
            },
            Command::Pwd => {
                let msg = format!("{}", self.cwd.to_str().unwrap_or(""));
                if !msg.is_empty() {
                    let message = format!("\"/{}\" ",msg);
                    self = await!(self.send(Answer::new(ResultCode::PATHNAMECreated, &message)))?;
                } else {
                    self = await!(self.send(Answer::new(ResultCode::FileNotFound, "No such file or directory")))?;
                }
            },
            Command::Unknown(s) => self = await!(self.send(Answer::new(ResultCode::UnknownCommand, &format!("\"{}\": Not Implemented",s))))?,
            _=>  self = await!(self.send(Answer::new(ResultCode::CommandNotImplemented, "Not implemented")))?,
        }
        return Ok(self);
    }
}

#[async]
fn client(stream: TcpStream, handle: Handle,  server_root: PathBuf) -> Result<()>{
    let (writer, reader) = stream.framed(FtpCodec).split();
    let writer = await!(writer.send(Answer::new(ResultCode::ServiceReadyForNewUser, "Welcome to this FTP Server!")))?;
    let mut client = Client::new(handle, writer, server_root);
    #[async]
    for cmd in reader {
        client = await!(client.handle_cmd(cmd))?;
    }
    println!("Client closed");
    return Ok(());;
}

#[async]
fn handle_client(stream: TcpStream, handle: Handle, server_root: PathBuf) -> result::Result<(), ()> {
    await!(client(stream, handle, server_root)).map_err(|error| println!("Error handling client: {}", error))
}

#[async]
fn server(handle: Handle, server_root: PathBuf) -> io::Result<()> {
    let port = 1234;
    let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127,0,0,1)), port);
    let listener = TcpListener::bind(&addr,&handle)?;
    println!("Waiting clients on port {}...",port);
    #[async]
    for (stream, addr) in listener.incoming() {
        let address = format!("[address : {}]",addr);
        println!("New client {}", address);
        handle.spawn(handle_client(stream, handle.clone() ,server_root.clone()));
        println!("Waiting another client...");
    }
    return Ok(());
}

fn main() {
    let mut core = Core::new().expect("Cannot create tokio Core");
    let handle = core.handle();
    match env::current_dir() {
        Ok(server_root) => {
            if let Err(error) = core.run(server(handle, server_root)) {
                println!("Error running the server: {}", error);
            }
        },
        Err(e) => println!("Could not start server: {:?}",e),

    }

}
<commit_msg>Updated main to implement list operation<commit_after>#![feature(proc_macro, conservative_impl_trait, generators)]
extern crate bytes;
extern crate futures_await as futures;
extern crate tokio_core;
extern crate tokio_io;

mod cmd;
mod ftp;
mod error;
mod codec;

use std::result;
use std::io;
use std::env;
use futures::prelude::*;
use tokio_core::reactor::Core;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use tokio_core::reactor::Handle;
use tokio_core::net::TcpListener;

use tokio_core::net::TcpStream;

use futures::{Sink, Stream};
use futures::stream::SplitSink;

use tokio_io::AsyncRead;
use tokio_io::codec::Framed;
use codec::FtpCodec;
use error::Result;
use ftp::{Answer, ResultCode};
use std::path::PathBuf;
use std::path::StripPrefixError;

use futures::stream::SplitStream;
use codec::BytesCodec;

use cmd::Command;
use cmd::TransferType;

use std::ffi::OsString;
use std::fs::{create_dir, remove_dir_all};

type DataReader = SplitStream<Framed<TcpStream, BytesCodec>>;
type DataWriter = SplitSink<Framed<TcpStream,BytesCodec>>;
type Writer = SplitSink<Framed<TcpStream, FtpCodec>>;

fn get_parent(path: PathBuf) -> Option<PathBuf> {
    path.parent().map(|p| p.to_path_buf())
}

fn get_filename(path: PathBuf) -> Option<OsString> {
    path.file_name().map(|p| p.to_os_string())
}

struct Client {
    data_port: Option<u16>,
    data_reader: Option<DataReader>,
    data_writer: Option<DataWriter>,
    handle: Handle,
    cwd: PathBuf,
    server_root: PathBuf,
    transfer_type: TransferType,
    writer: Writer,
}

impl Client {
    fn new(handle: Handle, writer: Writer, server_root: PathBuf) -> Client {
        Client {
            data_port: None,
            data_reader: None,
            data_writer: None,
            handle,
            cwd: PathBuf::from("/"),
            server_root,
            transfer_type: TransferType::Ascii,
            writer,
        }
    }
    #[async]
    fn send(mut self, answer: Answer) -> Result<Self> {
        self.writer = await!(self.writer.send(answer))?;
        Ok(self)
    }

    fn complete_path(self, path: PathBuf) -> (Self, result::Result<PathBuf, io::Error>) {
        let directory = self.server_root.join(if path.has_root() {
                path.iter().skip(1).collect()
            } else {
                path
        });
        let dir = directory.canonicalize();
        if let Ok(ref dir) = dir {
            if !dir.starts_with(&self.server_root) {
                return (self, Err(io::ErrorKind::PermissionDenied.into()));
            }
        }
        (self,dir)
    }
    fn strip_prefix(self, dir:PathBuf) -> (Self, result::Result<PathBuf, StripPrefixError>) {
        let res = dir.strip_prefix(&self.server_root).map(|p| p.to_path_buf());
        (self,res)
    }

    #[async]
    fn cwd(mut self, directory: PathBuf) -> Result<Self>{
        let path = self.cwd.join(&directory);
        let (new_self, res) = self.complete_path(path);
        self = new_self;
        if let Ok(dir) = res {
            let (new_self, res) = self.strip_prefix(dir);
            self = new_self;
            if let Ok(prefix) = res {
                self.cwd = prefix.to_path_buf();
                self = await!(self.send(Answer::new(ResultCode::Ok, &format!("Directory changed to \"{}\"", directory.display()))))?;
                return Ok(self)
            }
        }
        self = await!(self.send(Answer::new(ResultCode::FileNotFound, "No such file or directory")))?;
        return Ok(self);
    }
    #[async]
    fn pasv(mut self) -> Result<Self> {
        let port =
            if let Some(port) = self.data_port {
                port
             } else {
                0
             };
        if self.data_writer.is_some() {
            self = await!(self.send(Answer::new(ResultCode::DataConnectionAlreadyOpen,"Already listening...")))?;
            return Ok(self);
        }

        let addr= SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127,0,0,1)),port);
        let listener = TcpListener::bind(&addr, &self.handle)?;
        let port = listener.local_addr()?.port();

        self = await!(self.send(Answer::new(ResultCode::EnteringPassiveMode, &format!("127,0,0,1,{},{}", port>>8, port & 0xFF))))?;

        println!("Waiting clients on the port {}...", port);

        #[async]
        for(stream, _rest) in listener.incoming()  {
            let (writer, reader) = stream.framed(BytesCodec).split();
            self.data_writer = Some(writer);
            self.data_reader = Some(reader);
            break;
        }
        Ok(self)
    }

    #[async]
    fn quit(mut self) -> Result<Self> {
        if self.data_writer.is_some() {
            unimplemented!();
        } else {
            self = await!(self.send(Answer::new(ResultCode::ServiceClosingControlConnection, "Closing connection...")))?;
            self.writer.close()?;
        }
        Ok(self)
    }

    #[async]
    fn mkd(mut self, path: PathBuf) -> Result<Self> {
        let path = self.cwd.join(&path);
        let parent = get_parent(path.clone());
        if let Some(parent) = parent {
            let parent = parent.to_path_buf();
            let(new_self, res) = self.complete_path(parent);
            self = new_self;
            if let Ok(mut dir) = res {
                if dir.is_dir() {
                    let filename = get_filename(path);
                    if let Some(filename) = filename {
                        dir.push(filename);
                        if create_dir(dir).is_ok() {
                            self = await!(self.send(Answer::new(ResultCode::PATHNAMECreated,"Folder sucessfully crated!")))?;
                            return Ok(self);
                        }
                    }
                }
            }
        }
        self = await!(self.send(Answer::new(ResultCode::FileNotFound, "Could not create folder")))?;
        Ok(self)
    }

    #[async]
    fn rmd(mut self, directory: PathBuf) -> Result<Self> {
        let path = self.cwd.join(&directory);
        let (new_self, res) = self.complete_path(path);
        self = new_self;
        if let Ok(dir) = res {
            if remove_dir_all(dir).is_ok() {
                self = await!(self.send(Answer::new(ResultCode::RequestedFileActionOkay,
                                                    "Folder successfully removed")))?;
                return Ok(self);
            }
        }
        self = await!(self.send(Answer::new(ResultCode::FileNotFound,
                                            "Couldn't remove folder")))?;
        Ok(self)
    }

    #[async]
    fn send_data(mut self, data: Vec<u8>) -> Result<Self> {
        if let Some(writer) = self.data_writer {
            self.data_writer = Some(await!(writer.send(data))?);
        }
        Ok(self);
    }

    fn close_data_connection(&mut self) {
        self.data_reader = None;
        self.data_writer = None;
    }
    const MONTHS: [&'static str; 12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

    fn add_file_info(path: PathBuf, out: &mut Vec<u8>) {
        let extra = if path.is_dir() {"/"} else {""};
        let is_dir = if path.is_dir() {"d"}  else {"-"};
        let meta = match ::std::fs::metadata(&path) {
            Ok(meta) => path,
            _=> return,
        },
        _=>return,
    };
    let rights = if meta.permissions().readonly() {
        "r--r--r--"
    } else {
        "rw-rw-rw-"
    };

    }
    #[async]
    fn list(mut self, path: Option<PathBuf>) -> Result<Self> {
        if self.data_writer.is_some() {
            let path = self.cwd.join(path.unwrap_or_default());
            let directory = PathBuf::from(&path);
            let (new_self, res) = self.complete_path(directory);
            self = ne_self;
            if  let Ok(path) = res {
                self = await!(self.send(Answer::new(ResultCode::DataConnectionAlreadyOpen, "Starting to list directory...")));

                let mut out = vec![];
                if path.is_dir() {
                    if let Ok(dir) = read_dir(path) {
                        for entry in dir {
                            if let Ok(entry) = entry {
                                add_file_info(entry.path(),&mut out);
                            }
                        }
                    } else {
                        self =  await!(self.send(Answer::new(ResultCode::InvalidParameterOrArgument, "No such file or directory")))?;
                        return Ok(self);
                    }
                } else {
                    add_file_info(entry.path(),&mut out);
                }
                self = await!(self.send_data(out))?;
                println!("-> and done!");
            } else {
                self = await!(self.send(Answer::new(ResultCode::InvalidParameterOrArgument)))?;
            }
        } else {
            self = await!(self.send(Answer::new(ResultCode::ConnectionClosed, "No opened data connection")))?;
        }
        if self.data_writer.is_some() {
            self.close_data_connection();
            self = await!(self.send(Answer::new(ResultCode::ClosingDataConnection, "Transfer done")))?;
        }
        Ok(self);
    }

    #[async]
    fn handle_cmd(mut self, cmd: Command) -> Result<Self> {
        println!("Received command: {:?}", cmd);
        match cmd {
            Command::List(path) => self = await!(self.list(path))?,
            Command::Mkd(path) => self = await!(self.mkd(path))?,
            Command::Rmd(path) => self = await!(self.rmd(path))?,
            Command::Quit => self = await!(self.quit())?,
            Command::Pasv => self = await!(self.pasv())?,
            Command::Type(typ) => {
                self.transfer_type = typ;
                self = await!(self.send(Answer::new(ResultCode::Ok, "Transfer type changed successfully")))?;
            },
            Command::Cwd(directory) => {
                self= await!(self.cwd(directory))?;
            },
            Command::User(content) => {
                if content.is_empty() {
                    self = await!(self.send(Answer::new(ResultCode::InvalidParameterOrArgument,"Invalid username")))?;
                } else {
                    self = await!(self.send(Answer::new(ResultCode::UserloggedIn,&format!("Welcome {}",content))))?;
                }
            },
            Command::Pwd => {
                let msg = format!("{}", self.cwd.to_str().unwrap_or(""));
                if !msg.is_empty() {
                    let message = format!("\"/{}\" ",msg);
                    self = await!(self.send(Answer::new(ResultCode::PATHNAMECreated, &message)))?;
                } else {
                    self = await!(self.send(Answer::new(ResultCode::FileNotFound, "No such file or directory")))?;
                }
            },
            Command::Unknown(s) => self = await!(self.send(Answer::new(ResultCode::UnknownCommand, &format!("\"{}\": Not Implemented",s))))?,
            _=>  self = await!(self.send(Answer::new(ResultCode::CommandNotImplemented, "Not implemented")))?,
        }
        return Ok(self);
    }
}

#[async]
fn client(stream: TcpStream, handle: Handle,  server_root: PathBuf) -> Result<()>{
    let (writer, reader) = stream.framed(FtpCodec).split();
    let writer = await!(writer.send(Answer::new(ResultCode::ServiceReadyForNewUser, "Welcome to this FTP Server!")))?;
    let mut client = Client::new(handle, writer, server_root);
    #[async]
    for cmd in reader {
        client = await!(client.handle_cmd(cmd))?;
    }
    println!("Client closed");
    return Ok(());;
}

#[async]
fn handle_client(stream: TcpStream, handle: Handle, server_root: PathBuf) -> result::Result<(), ()> {
    await!(client(stream, handle, server_root)).map_err(|error| println!("Error handling client: {}", error))
}

#[async]
fn server(handle: Handle, server_root: PathBuf) -> io::Result<()> {
    let port = 1234;
    let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127,0,0,1)), port);
    let listener = TcpListener::bind(&addr,&handle)?;
    println!("Waiting clients on port {}...",port);
    #[async]
    for (stream, addr) in listener.incoming() {
        let address = format!("[address : {}]",addr);
        println!("New client {}", address);
        handle.spawn(handle_client(stream, handle.clone() ,server_root.clone()));
        println!("Waiting another client...");
    }
    return Ok(());
}

fn main() {
    let mut core = Core::new().expect("Cannot create tokio Core");
    let handle = core.handle();
    match env::current_dir() {
        Ok(server_root) => {
            if let Err(error) = core.run(server(handle, server_root)) {
                println!("Error running the server: {}", error);
            }
        },
        Err(e) => println!("Could not start server: {:?}",e),

    }

}
<|endoftext|>


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

use crate::test_utils::{
    compare_balances,
    libra_swarm_utils::{get_op_tool, load_libra_root_storage},
    setup_swarm_and_client_proxy,
};
use cli::client_proxy::ClientProxy;
use debug_interface::NodeDebugClient;
use libra_trace::trace::trace_node;
use libra_types::{
    account_address::AccountAddress, account_config::testnet_dd_account_address,
    ledger_info::LedgerInfo, waypoint::Waypoint,
};

#[test]
fn smoke_test_single_node() {
    let (_swarm, client_proxy) = setup_swarm_and_client_proxy(1, 0);
    test_smoke_script(client_proxy);
}

// Test if we commit not only user transactions but also block metadata transactions,
// assert committed version > # of user transactions
#[test]
fn smoke_test_single_node_block_metadata() {
    let (swarm, mut client_proxy) = setup_swarm_and_client_proxy(1, 0);
    // just need an address to get the latest version
    let address = AccountAddress::from_hex_literal("0xA550C18").unwrap();
    // this script does 4 transactions
    test_smoke_script(swarm.get_validator_client(0, None));
    let (_account, version) = client_proxy
        .get_latest_account(&["q", &address.to_string()])
        .unwrap();
    assert!(
        version > 4,
        "BlockMetadata txn not produced, current version: {}",
        version
    );
}

#[test]
fn test_basic_fault_tolerance() {
    // A configuration with 4 validators should tolerate single node failure.
    let (mut env, client_proxy) = setup_swarm_and_client_proxy(4, 1);
    // kill the first validator
    env.validator_swarm.kill_node(0);
    // run the script for the smoke test by submitting requests to the second validator
    test_smoke_script(client_proxy);
}

#[test]
fn test_basic_restartability() {
    let (mut env, mut client_proxy) = setup_swarm_and_client_proxy(4, 0);
    client_proxy.create_next_account(false).unwrap();
    client_proxy.create_next_account(false).unwrap();
    client_proxy
        .mint_coins(&["mb", "0", "100", "Coin1"], true)
        .unwrap();
    client_proxy
        .mint_coins(&["mb", "1", "10", "Coin1"], true)
        .unwrap();
    client_proxy
        .transfer_coins(&["tb", "0", "1", "10", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(90.0, "Coin1".to_string())],
        client_proxy.get_balances(&["b", "0"]).unwrap(),
    ));
    assert!(compare_balances(
        vec![(20.0, "Coin1".to_string())],
        client_proxy.get_balances(&["b", "1"]).unwrap(),
    ));
    let peer_to_restart = 0;
    // restart node
    env.validator_swarm.kill_node(peer_to_restart);
    assert!(env.validator_swarm.add_node(peer_to_restart).is_ok());
    assert!(compare_balances(
        vec![(90.0, "Coin1".to_string())],
        client_proxy.get_balances(&["b", "0"]).unwrap(),
    ));
    assert!(compare_balances(
        vec![(20.0, "Coin1".to_string())],
        client_proxy.get_balances(&["b", "1"]).unwrap(),
    ));
    client_proxy
        .transfer_coins(&["tb", "0", "1", "10", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(80.0, "Coin1".to_string())],
        client_proxy.get_balances(&["b", "0"]).unwrap(),
    ));
    assert!(compare_balances(
        vec![(30.0, "Coin1".to_string())],
        client_proxy.get_balances(&["b", "1"]).unwrap(),
    ));
}

#[test]
fn test_client_waypoints() {
    let (env, mut client_proxy) = setup_swarm_and_client_proxy(4, 1);
    // Make sure some txns are committed
    client_proxy.create_next_account(false).unwrap();
    client_proxy
        .mint_coins(&["mintb", "0", "10", "Coin1"], true)
        .unwrap();

    // Create the waypoint for the initial epoch
    let genesis_li = client_proxy
        .latest_epoch_change_li()
        .expect("Failed to retrieve genesis LedgerInfo");
    assert_eq!(genesis_li.ledger_info().epoch(), 0);
    let genesis_waypoint = Waypoint::new_epoch_boundary(genesis_li.ledger_info())
        .expect("Failed to generate waypoint from genesis LI");

    // Start another client with the genesis waypoint and make sure it successfully connects
    let mut client_with_waypoint = env.get_validator_client(0, Some(genesis_waypoint));
    client_with_waypoint.test_trusted_connection().unwrap();
    assert_eq!(
        client_with_waypoint.latest_epoch_change_li().unwrap(),
        genesis_li
    );

    // Start next epoch

    // This ugly blob is to remove a validator, we can do better...
    let peer_id = env
        .validator_swarm
        .get_validator(0)
        .unwrap()
        .validator_peer_id()
        .unwrap();
    let op_tool = get_op_tool(&env.validator_swarm, 1);
    let libra_root = load_libra_root_storage(&env.validator_swarm, 0);
    let context = op_tool.remove_validator(peer_id, &libra_root).unwrap();
    client_proxy
        .wait_for_transaction(context.address, context.sequence_number + 1)
        .unwrap();
    // end ugly blob
    client_proxy
        .mint_coins(&["mintb", "0", "10", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(20.0, "Coin1".to_string())],
        client_proxy.get_balances(&["b", "0"]).unwrap(),
    ));
    let epoch_1_li = client_proxy
        .latest_epoch_change_li()
        .expect("Failed to retrieve end of epoch 1 LedgerInfo");

    assert_eq!(epoch_1_li.ledger_info().epoch(), 1);
    let epoch_1_waypoint = Waypoint::new_epoch_boundary(epoch_1_li.ledger_info())
        .expect("Failed to generate waypoint from end of epoch 1");

    // Start a client with the waypoint for end of epoch 1 and make sure it successfully connects
    client_with_waypoint = env.get_validator_client(1, Some(epoch_1_waypoint));
    client_with_waypoint.test_trusted_connection().unwrap();
    assert_eq!(
        client_with_waypoint.latest_epoch_change_li().unwrap(),
        epoch_1_li
    );

    // Verify that a client with the wrong waypoint is not going to be able to connect to the chain.
    let bad_li = LedgerInfo::mock_genesis(None);
    let bad_waypoint = Waypoint::new_epoch_boundary(&bad_li).unwrap();
    let mut client_with_bad_waypoint = env.get_validator_client(1, Some(bad_waypoint));
    assert!(client_with_bad_waypoint.test_trusted_connection().is_err());
}

#[test]
fn test_concurrent_transfers_single_node() {
    let (_swarm, mut client_proxy) = setup_swarm_and_client_proxy(1, 0);
    client_proxy.create_next_account(false).unwrap();
    client_proxy
        .mint_coins(&["mintb", "0", "100", "Coin1"], true)
        .unwrap();
    client_proxy.create_next_account(false).unwrap();
    client_proxy
        .mint_coins(&["mintb", "1", "10", "Coin1"], true)
        .unwrap();
    for _ in 0..20 {
        client_proxy
            .transfer_coins(&["t", "0", "1", "1", "Coin1"], false)
            .unwrap();
    }
    client_proxy
        .transfer_coins(&["tb", "0", "1", "1", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(79.0, "Coin1".to_string())],
        client_proxy.get_balances(&["b", "0"]).unwrap(),
    ));
    assert!(compare_balances(
        vec![(31.0, "Coin1".to_string())],
        client_proxy.get_balances(&["b", "1"]).unwrap(),
    ));
}

#[test]
fn test_trace() {
    let (swarm, mut client_proxy) = setup_swarm_and_client_proxy(1, 0);
    let port = swarm.validator_swarm.get_validators_debug_ports()[0];
    let mut debug_client = NodeDebugClient::new("localhost", port);
    client_proxy.create_next_account(false).unwrap();
    client_proxy
        .mint_coins(&["mintb", "0", "100", "Coin1"], true)
        .unwrap();
    client_proxy.create_next_account(false).unwrap();
    client_proxy
        .mint_coins(&["mintb", "1", "10", "Coin1"], true)
        .unwrap();
    client_proxy
        .transfer_coins(&["t", "0", "1", "1", "Coin1"], false)
        .unwrap();
    let events = debug_client.get_events().expect("Failed to get events");
    let txn_node = format!("txn::{}::{}", testnet_dd_account_address(), 1);
    println!("Tracing {}", txn_node);
    trace_node(&events[..], &txn_node);
}

/// This helper function creates 3 new accounts, mints funds, transfers funds
/// between the accounts and verifies that these operations succeed.
fn test_smoke_script(mut client: ClientProxy) {
    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mintb", "0", "10", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(10.0, "Coin1".to_string())],
        client.get_balances(&["b", "0"]).unwrap(),
    ));

    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mintb", "1", "1", "Coin1"], true)
        .unwrap();
    client
        .transfer_coins(&["tb", "0", "1", "3", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(7.0, "Coin1".to_string())],
        client.get_balances(&["b", "0"]).unwrap(),
    ));
    assert!(compare_balances(
        vec![(4.0, "Coin1".to_string())],
        client.get_balances(&["b", "1"]).unwrap(),
    ));

    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mintb", "2", "15", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(15.0, "Coin1".to_string())],
        client.get_balances(&["b", "2"]).unwrap(),
    ));
}
<commit_msg>[Smoke Tests] Clean up client.rs file and tests<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::test_utils::{
    compare_balances,
    libra_swarm_utils::{get_op_tool, load_libra_root_storage},
    setup_swarm_and_client_proxy,
};
use cli::client_proxy::ClientProxy;
use debug_interface::NodeDebugClient;
use libra_trace::trace::trace_node;
use libra_types::{
    account_address::AccountAddress, account_config::testnet_dd_account_address,
    ledger_info::LedgerInfo, waypoint::Waypoint,
};

#[test]
fn test_create_mint_transfer() {
    let (_env, client) = setup_swarm_and_client_proxy(1, 0);
    check_create_mint_transfer(client);
}

// Test if we commit not only user transactions but also block metadata transactions,
// assert committed version > # of user transactions
#[test]
fn test_create_mint_transfer_block_metadata() {
    let (env, mut client) = setup_swarm_and_client_proxy(1, 0);
    check_create_mint_transfer(env.get_validator_client(0, None));

    let address = AccountAddress::from_hex_literal("0xA550C18").unwrap();
    let (_account, version) = client
        .get_latest_account(&["q", &address.to_string()])
        .unwrap();
    assert!(
        version > 4,
        "BlockMetadata txn not produced, current version: {}",
        version
    );
}

#[test]
fn test_basic_fault_tolerance() {
    // A configuration with 4 validators should tolerate single node failure.
    let (mut env, client) = setup_swarm_and_client_proxy(4, 1);
    env.validator_swarm.kill_node(0);
    check_create_mint_transfer(client);
}

#[test]
fn test_basic_restartability() {
    let (mut env, mut client) = setup_swarm_and_client_proxy(4, 0);

    client.create_next_account(false).unwrap();
    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mb", "0", "100", "Coin1"], true)
        .unwrap();
    client
        .mint_coins(&["mb", "1", "10", "Coin1"], true)
        .unwrap();
    client
        .transfer_coins(&["tb", "0", "1", "10", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(90.0, "Coin1".to_string())],
        client.get_balances(&["b", "0"]).unwrap(),
    ));
    assert!(compare_balances(
        vec![(20.0, "Coin1".to_string())],
        client.get_balances(&["b", "1"]).unwrap(),
    ));

    let peer_to_restart = 0;
    env.validator_swarm.kill_node(peer_to_restart);

    assert!(env.validator_swarm.add_node(peer_to_restart).is_ok());
    assert!(compare_balances(
        vec![(90.0, "Coin1".to_string())],
        client.get_balances(&["b", "0"]).unwrap(),
    ));
    assert!(compare_balances(
        vec![(20.0, "Coin1".to_string())],
        client.get_balances(&["b", "1"]).unwrap(),
    ));

    client
        .transfer_coins(&["tb", "0", "1", "10", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(80.0, "Coin1".to_string())],
        client.get_balances(&["b", "0"]).unwrap(),
    ));
    assert!(compare_balances(
        vec![(30.0, "Coin1".to_string())],
        client.get_balances(&["b", "1"]).unwrap(),
    ));
}

#[test]
fn test_client_waypoints() {
    let (env, mut client) = setup_swarm_and_client_proxy(4, 1);

    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mintb", "0", "10", "Coin1"], true)
        .unwrap();

    // Create the waypoint for the initial epoch
    let genesis_li = client
        .latest_epoch_change_li().unwrap();
    assert_eq!(genesis_li.ledger_info().epoch(), 0);
    let genesis_waypoint = Waypoint::new_epoch_boundary(genesis_li.ledger_info()).unwrap();

    // Start another client with the genesis waypoint and make sure it successfully connects
    let mut client_with_waypoint = env.get_validator_client(0, Some(genesis_waypoint));
    client_with_waypoint.test_trusted_connection().unwrap();
    assert_eq!(
        client_with_waypoint.latest_epoch_change_li().unwrap(),
        genesis_li
    );

    // Start next epoch

    // This ugly blob is to remove a validator, we can do better...
    let peer_id = env
        .validator_swarm
        .get_validator(0)
        .unwrap()
        .validator_peer_id()
        .unwrap();
    let op_tool = get_op_tool(&env.validator_swarm, 1);
    let libra_root = load_libra_root_storage(&env.validator_swarm, 0);
    let context = op_tool.remove_validator(peer_id, &libra_root).unwrap();
    client
        .wait_for_transaction(context.address, context.sequence_number + 1)
        .unwrap();
    // end ugly blob

    client
        .mint_coins(&["mintb", "0", "10", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(20.0, "Coin1".to_string())],
        client.get_balances(&["b", "0"]).unwrap(),
    ));
    let epoch_1_li = client
        .latest_epoch_change_li()
        .expect("Failed to retrieve end of epoch 1 LedgerInfo");

    assert_eq!(epoch_1_li.ledger_info().epoch(), 1);
    let epoch_1_waypoint = Waypoint::new_epoch_boundary(epoch_1_li.ledger_info())
        .expect("Failed to generate waypoint from end of epoch 1");

    // Start a client with the waypoint for end of epoch 1 and make sure it successfully connects
    client_with_waypoint = env.get_validator_client(1, Some(epoch_1_waypoint));
    client_with_waypoint.test_trusted_connection().unwrap();
    assert_eq!(
        client_with_waypoint.latest_epoch_change_li().unwrap(),
        epoch_1_li
    );

    // Verify that a client with the wrong waypoint is not going to be able to connect to the chain.
    let bad_li = LedgerInfo::mock_genesis(None);
    let bad_waypoint = Waypoint::new_epoch_boundary(&bad_li).unwrap();
    let mut client_with_bad_waypoint = env.get_validator_client(1, Some(bad_waypoint));
    assert!(client_with_bad_waypoint.test_trusted_connection().is_err());
}

#[test]
fn test_concurrent_transfers_single_node() {
    let (_env, mut client) = setup_swarm_and_client_proxy(1, 0);

    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mintb", "0", "100", "Coin1"], true)
        .unwrap();

    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mintb", "1", "10", "Coin1"], true)
        .unwrap();

    for _ in 0..20 {
        client
            .transfer_coins(&["t", "0", "1", "1", "Coin1"], false)
            .unwrap();
    }
    client
        .transfer_coins(&["tb", "0", "1", "1", "Coin1"], true)
        .unwrap();

    assert!(compare_balances(
        vec![(79.0, "Coin1".to_string())],
        client.get_balances(&["b", "0"]).unwrap(),
    ));
    assert!(compare_balances(
        vec![(31.0, "Coin1".to_string())],
        client.get_balances(&["b", "1"]).unwrap(),
    ));
}

#[test]
fn test_trace() {
    let (env, mut client) = setup_swarm_and_client_proxy(1, 0);

    let port = env.validator_swarm.get_validators_debug_ports()[0];
    let mut debug_client = NodeDebugClient::new("localhost", port);

    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mintb", "0", "100", "Coin1"], true)
        .unwrap();

    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mintb", "1", "10", "Coin1"], true)
        .unwrap();
    client
        .transfer_coins(&["t", "0", "1", "1", "Coin1"], false)
        .unwrap();

    let events = debug_client.get_events().expect("Failed to get events");
    let txn_node = format!("txn::{}::{}", testnet_dd_account_address(), 1);
    println!("Tracing {}", txn_node);

    trace_node(&events[..], &txn_node);
}

/// This helper function creates 3 new accounts, mints funds, transfers funds
/// between the accounts and verifies that these operations succeed.
fn check_create_mint_transfer(mut client: ClientProxy) {
    // Create account 0, mint 10 coins and check balance
    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mintb", "0", "10", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(10.0, "Coin1".to_string())],
        client.get_balances(&["b", "0"]).unwrap(),
    ));

    // Create account 1, mint 1 coin, transfer 3 coins from account 0 to 1, check balances
    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mintb", "1", "1", "Coin1"], true)
        .unwrap();
    client
        .transfer_coins(&["tb", "0", "1", "3", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(7.0, "Coin1".to_string())],
        client.get_balances(&["b", "0"]).unwrap(),
    ));
    assert!(compare_balances(
        vec![(4.0, "Coin1".to_string())],
        client.get_balances(&["b", "1"]).unwrap(),
    ));

    // Create account 2, mint 15 coins and check balance
    client.create_next_account(false).unwrap();
    client
        .mint_coins(&["mintb", "2", "15", "Coin1"], true)
        .unwrap();
    assert!(compare_balances(
        vec![(15.0, "Coin1".to_string())],
        client.get_balances(&["b", "2"]).unwrap(),
    ));
}
<|endoftext|>