<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![cfg(test)]

extern crate capnp;
extern crate capnp_rpc;

#[macro_use]
extern crate gj;

use gj::{EventLoop, Promise};
use gj::io::unix;
use capnp::Error;
use capnp_rpc::{RpcSystem, rpc_twoparty_capnp, twoparty};

pub mod test_capnp {
  include!(concat!(env!("OUT_DIR"), "/test_capnp.rs"));
}

pub mod impls;
pub mod test_util;

#[test]
fn drop_rpc_system() {
    EventLoop::top_level(|wait_scope| {
        let (instream, _outstream) = try!(unix::Stream::new_pair());
        let (reader, writer) = instream.split();
        let network =
            Box::new(twoparty::VatNetwork::new(reader, writer,
                                               rpc_twoparty_capnp::Side::Client,
                                               Default::default()));
        let rpc_system = RpcSystem::new(network, None);
        drop(rpc_system);
        try!(Promise::<(),Error>::ok(()).wait(wait_scope));
        Ok(())
    }).expect("top level error");
}

fn set_up_rpc<F>(main: F)
    where F: FnOnce(test_capnp::bootstrap::Client) -> Promise<(), Error>,
          F: Send + 'static
{
    EventLoop::top_level(|wait_scope| {
        let (join_handle, stream) = try!(unix::spawn(|stream, wait_scope| {

            let (reader, writer) = stream.split();
            let mut network =
                Box::new(twoparty::VatNetwork::new(reader, writer,
                                                   rpc_twoparty_capnp::Side::Server,
                                                   Default::default()));
            let disconnect_promise = network.on_disconnect();
            let bootstrap =
                test_capnp::bootstrap::ToClient::new(impls::Bootstrap).from_server::<::capnp_rpc::Server>();

            let _rpc_system = RpcSystem::new(network, Some(bootstrap.client));
            try!(disconnect_promise.wait(wait_scope));
            Ok(())
        }));

        let (reader, writer) = stream.split();
        let network =
            Box::new(twoparty::VatNetwork::new(reader, writer,
                                               rpc_twoparty_capnp::Side::Client,
                                               Default::default()));

        let mut rpc_system = RpcSystem::new(network, None);
        let client: test_capnp::bootstrap::Client = rpc_system.bootstrap(rpc_twoparty_capnp::Side::Server);

        try!(main(client).wait(wait_scope));
        drop(rpc_system);
        join_handle.join().expect("thread exited unsuccessfully");
        Ok(())
    }).expect("top level error");
}

#[test]
fn do_nothing() {
    set_up_rpc(|_client| {
        Promise::ok(())
    });
}

#[test]
fn basic() {
    set_up_rpc(|client| {
        client.test_interface_request().send().promise.then(|response| {

            let client = pry!(pry!(response.get()).get_cap());
            let mut request1 = client.foo_request();
            request1.get().set_i(123);
            request1.get().set_j(true);
            let promise1 = request1.send().promise.then(|response| {
                if "foo" == pry!(pry!(response.get()).get_x()) {
                    Promise::ok(())
                } else {
                    Promise::err(Error::failed("expected X to equal 'foo'".to_string()))
                }
            });

            let request3 = client.bar_request();
            let promise3 = request3.send().promise.then_else(|result| {
                // We expect this call to fail.
                match result {
                    Ok(_) => {
                        Promise::err(Error::failed("expected bar() to fail".to_string()))
                    }
                    Err(_) => {
                        Promise::ok(())
                    }
                }
            });

            let mut request2 = client.baz_request();
            ::test_util::init_test_message(pry!(request2.get().get_s()));
            let promise2 = request2.send().promise.map(|_| Ok(()));

            Promise::all(vec![promise1, promise2, promise3].into_iter()).map(|_| Ok(()))
        })
    });
}

#[test]
fn pipelining() {
    set_up_rpc(|client| {
        client.test_pipeline_request().send().promise.then(|response| {
            let client = pry!(pry!(response.get()).get_cap());
            let mut request = client.get_cap_request();
            request.get().set_n(234);
            let server = impls::TestInterface::new();
            let chained_call_count = server.get_call_count();
            request.get().set_in_cap(
                ::test_capnp::test_interface::ToClient::new(server).from_server::<::capnp_rpc::Server>());

            let promise = request.send();

            let mut pipeline_request = promise.pipeline.get_out_box().get_cap().foo_request();
            pipeline_request.get().set_i(321);
            let pipeline_promise = pipeline_request.send();

            let pipeline_request2 = {
                let extends_client =
                    ::test_capnp::test_extends::Client { client: promise.pipeline.get_out_box().get_cap().client };
                extends_client.grault_request()
            };
            let pipeline_promise2 = pipeline_request2.send();

            drop(promise); // Just to be annoying, drop the original promise.

            if chained_call_count.get() != 0 {
                return Promise::err(Error::failed("expeced chained_call_count to equal 0".to_string()));
            }

            pipeline_promise.promise.then(move |response| {
                if pry!(pry!(response.get()).get_x()) != "bar" {
                    return Promise::err(Error::failed("expected x to equal 'bar'".to_string()));
                }
                pipeline_promise2.promise.then(move |response| {
                    ::test_util::CheckTestMessage::check_test_message(pry!(response.get()));
                    assert_eq!(chained_call_count.get(), 1);
                    Promise::ok(())
                })
            })
        })
    });
}

#[test]
fn null_capability() {
    let mut message = ::capnp::message::Builder::new_default();
    let root: ::test_capnp::test_all_types::Builder = message.get_root().unwrap();

    // In capnproto-c++, this would return a BrokenCap. Here, it returns a decode error.
    // Would it be worthwhile to try to match the C++ behavior here? We would need something
    // like the BrokenCapFactory singleton.
    assert!(root.get_interface_field().is_err());
}

#[test]
fn release_simple() {
    set_up_rpc(|client| {
        client.test_more_stuff_request().send().promise.then(|response| {
            let client = pry!(pry!(response.get()).get_cap());

            Promise::all(vec![
                client.get_handle_request().send().promise,
                client.get_handle_request().send().promise].into_iter()).then(move |responses| {
                let handle1 = pry!(pry!(responses[0].get()).get_handle());
                let handle2 = pry!(pry!(responses[1].get()).get_handle());

                let client1 = client.clone();
                let client2 = client.clone();
                client.get_handle_count_request().send().promise.map(|response| {
                    if try!(response.get()).get_count() != 2 {
                        Err(Error::failed("expected handle count to equal 2".to_string()))
                    } else {
                        Ok(())
                    }
                }).then(move |()| {
                    drop(handle1);
                    client1.get_handle_count_request().send().promise.map(|response| {
                        if try!(response.get()).get_count() != 1 {
                            Err(Error::failed("expected handle count to equal 1".to_string()))
                        } else {
                            Ok(())
                        }
                    })
                }).then(move |()| {
                    drop(handle2);
                    client2.get_handle_count_request().send().promise.map(|response| {
                        if try!(response.get()).get_count() != 0 {
                            Err(Error::failed("expected handle count to equal 0".to_string()))
                        } else {
                            Ok(())
                        }
                    })
                })
            })
        })
    });
}

#[test]
fn promise_resolve() {
    set_up_rpc(|client| {
        client.test_more_stuff_request().send().promise.then(|response| {
            let client = pry!(pry!(response.get()).get_cap());

            let mut request = client.call_foo_request();
            let mut request2 = client.call_foo_when_resolved_request();

            let (paf_promise, paf_fulfiller) =
                Promise::<::test_capnp::test_interface::Client, Error>::and_fulfiller();

            {
                let mut fork = paf_promise.fork();
                let cap1 = ::capnp_rpc::new_promise_client(fork.add_branch().map(|c| Ok(c.client)));
                let cap2 = ::capnp_rpc::new_promise_client(fork.add_branch().map(|c| Ok(c.client)));
                request.get().set_cap(cap1);
                request2.get().set_cap(cap2);
            }

            let promise = request.send().promise;
            let promise2 = request2.send().promise;

            // Make sure getCap() has been called on the server side by sending another call and waiting
            // for it.
            let client2 = ::test_capnp::test_call_order::Client { client: client.clone().client };
            client2.get_call_sequence_request().send().promise.then(move |_response| {
                let server = impls::TestInterface::new();

                paf_fulfiller.fulfill(
                    ::test_capnp::test_interface::ToClient::new(server).from_server::<::capnp_rpc::Server>());

                promise.then(move |response| {
                    if pry!(pry!(response.get()).get_s()) != "bar" {
                        return Promise::err(Error::failed("expected s to equal 'bar'".to_string()));
                    }
                    promise2.then(move |response| {
                        if pry!(pry!(response.get()).get_s()) != "bar" {
                            return Promise::err(Error::failed("expected s to equal 'bar'".to_string()));
                        }

                        Promise::ok(())
                    })
                })
            })
        })
    });
}

fn get_call_sequence(client: &::test_capnp::test_call_order::Client, expected: u32)
                     -> ::capnp::capability::RemotePromise<::test_capnp::test_call_order::get_call_sequence_results::Owned>
{
    let mut req = client.get_call_sequence_request();
    req.get().set_expected(expected);
    req.send()
}

#[test]
fn embargo_success() {
    set_up_rpc(|client| {
        client.test_more_stuff_request().send().promise.then(|response| {
            let client = pry!(pry!(response.get()).get_cap());

            let server = ::impls::TestCallOrder::new();

            // ugh, we need upcasting.
            let client2 = ::test_capnp::test_call_order::Client { client: client.clone().client };
            let early_call = client2.get_call_sequence_request().send();
            drop(client2);

            let mut echo_request = client.echo_request();
            echo_request.get().set_cap(
                ::test_capnp::test_call_order::ToClient::new(server).from_server::<::capnp_rpc::Server>());
            let echo = echo_request.send();

            let pipeline = echo.pipeline.get_cap();

            let call0 = get_call_sequence(&pipeline, 0);
            let call1 = get_call_sequence(&pipeline, 1);

            early_call.promise.then(move |_early_call_response| {
                let call2 = get_call_sequence(&pipeline, 2);
                echo.promise.then(move |_echo_response| {
                    let call3 = get_call_sequence(&pipeline, 3);
                    let call4 = get_call_sequence(&pipeline, 4);
                    let call5 = get_call_sequence(&pipeline, 5);
                    Promise::all(vec![call0.promise,
                                      call1.promise,
                                      call2.promise,
                                      call3.promise,
                                      call4.promise,
                                      call5.promise].into_iter()).map(|responses| {
                        let mut counter = 0;
                        for r in responses.into_iter() {
                            if counter != try!(r.get()).get_n() {
                                return Err(Error::failed(
                                    "calls arrived out of order".to_string()))
                            }
                            counter += 1;
                        }
                        Ok(())
                    })
                })
            })
        })
    });
}

#[test]
fn echo_destruction() {
    set_up_rpc(|client| {
        client.test_more_stuff_request().send().promise.then(|response| {
            let client = pry!(pry!(response.get()).get_cap());

            let (promise, fulfiller) =
                Promise::<::test_capnp::test_call_order::Client, Error>::and_fulfiller();

            let cap = ::capnp_rpc::new_promise_client(promise.map(|c| Ok(c.client)));

            // ugh, we need upcasting.
            let client2 = ::test_capnp::test_call_order::Client { client: client.clone().client };
            let early_call = client2.get_call_sequence_request().send();
            drop(client2);

            let mut echo_request = client.echo_request();
            echo_request.get().set_cap(cap);
            let echo = echo_request.send();

            let pipeline = echo.pipeline.get_cap();

            early_call.promise.then(move |_early_call_response| {
                let _ = get_call_sequence(&pipeline, 2);
                echo.promise.then(move |_echo_response| {
                    fulfiller.reject(Error::failed("foo".to_string()));
                    Promise::ok(())
                })
            })
        })
    });
}
<commit_msg>ReadWrapper to help debug<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![cfg(test)]

extern crate capnp;
extern crate capnp_rpc;

#[macro_use]
extern crate gj;

use gj::{EventLoop, Promise};
use gj::io::{AsyncRead, unix};
use capnp::Error;
use capnp_rpc::{RpcSystem, rpc_twoparty_capnp, twoparty};

pub mod test_capnp {
  include!(concat!(env!("OUT_DIR"), "/test_capnp.rs"));
}

pub mod impls;
pub mod test_util;

struct ReadWrapper<R> where R: AsyncRead {
    inner: R,
    output_file: ::std::fs::File,
}

//::std::fs::File::create("~/Desktop/test.dat").unwrap(),
impl <R> ReadWrapper<R> where R: AsyncRead {
    fn new(inner: R, output_file: ::std::fs::File) -> ReadWrapper<R> {
        ReadWrapper {
            inner: inner,
            output_file: output_file,
        }
    }
}

impl <R> AsyncRead for ReadWrapper<R> where R: AsyncRead {
    fn try_read<T>(self, buf: T, min_bytes: usize)
                   -> Promise<(ReadWrapper<R>, T, usize), ::gj::io::Error<(ReadWrapper<R>, T)>>
        where T: AsMut<[u8]>
    {
        let ReadWrapper {inner, mut output_file} = self;
        inner.try_read(buf, min_bytes).map_else(|r| match r {
            Ok((r, mut buf, n)) => {
                use std::io::Write;
                output_file.write(&buf.as_mut()[0..n]).unwrap();
                Ok((ReadWrapper::new(r, output_file), buf, n))
            }
            Err(::gj::io::Error { state: (r, buf), error }) =>
                Err(::gj::io::Error::new((ReadWrapper::new(r, output_file), buf), error)),
        })
    }
}

#[test]
fn drop_rpc_system() {
    EventLoop::top_level(|wait_scope| {
        let (instream, _outstream) = try!(unix::Stream::new_pair());
        let (reader, writer) = instream.split();
        let network =
            Box::new(twoparty::VatNetwork::new(reader, writer,
                                               rpc_twoparty_capnp::Side::Client,
                                               Default::default()));
        let rpc_system = RpcSystem::new(network, None);
        drop(rpc_system);
        try!(Promise::<(),Error>::ok(()).wait(wait_scope));
        Ok(())
    }).expect("top level error");
}

fn set_up_rpc<F>(main: F)
    where F: FnOnce(test_capnp::bootstrap::Client) -> Promise<(), Error>,
          F: Send + 'static
{
    EventLoop::top_level(|wait_scope| {
        let (join_handle, stream) = try!(unix::spawn(|stream, wait_scope| {

            let (reader, writer) = stream.split();
            let mut network =
                Box::new(twoparty::VatNetwork::new(reader, writer,
                                                   rpc_twoparty_capnp::Side::Server,
                                                   Default::default()));
            let disconnect_promise = network.on_disconnect();
            let bootstrap =
                test_capnp::bootstrap::ToClient::new(impls::Bootstrap).from_server::<::capnp_rpc::Server>();

            let _rpc_system = RpcSystem::new(network, Some(bootstrap.client));
            try!(disconnect_promise.wait(wait_scope));
            Ok(())
        }));

        let (reader, writer) = stream.split();
        let network =
            Box::new(twoparty::VatNetwork::new(reader, writer,
                                               rpc_twoparty_capnp::Side::Client,
                                               Default::default()));

        let mut rpc_system = RpcSystem::new(network, None);
        let client: test_capnp::bootstrap::Client = rpc_system.bootstrap(rpc_twoparty_capnp::Side::Server);

        try!(main(client).wait(wait_scope));
        drop(rpc_system);
        join_handle.join().expect("thread exited unsuccessfully");
        Ok(())
    }).expect("top level error");
}

#[test]
fn do_nothing() {
    set_up_rpc(|_client| {
        Promise::ok(())
    });
}

#[test]
fn basic() {
    set_up_rpc(|client| {
        client.test_interface_request().send().promise.then(|response| {

            let client = pry!(pry!(response.get()).get_cap());
            let mut request1 = client.foo_request();
            request1.get().set_i(123);
            request1.get().set_j(true);
            let promise1 = request1.send().promise.then(|response| {
                if "foo" == pry!(pry!(response.get()).get_x()) {
                    Promise::ok(())
                } else {
                    Promise::err(Error::failed("expected X to equal 'foo'".to_string()))
                }
            });

            let request3 = client.bar_request();
            let promise3 = request3.send().promise.then_else(|result| {
                // We expect this call to fail.
                match result {
                    Ok(_) => {
                        Promise::err(Error::failed("expected bar() to fail".to_string()))
                    }
                    Err(_) => {
                        Promise::ok(())
                    }
                }
            });

            let mut request2 = client.baz_request();
            ::test_util::init_test_message(pry!(request2.get().get_s()));
            let promise2 = request2.send().promise.map(|_| Ok(()));

            Promise::all(vec![promise1, promise2, promise3].into_iter()).map(|_| Ok(()))
        })
    });
}

#[test]
fn pipelining() {
    set_up_rpc(|client| {
        client.test_pipeline_request().send().promise.then(|response| {
            let client = pry!(pry!(response.get()).get_cap());
            let mut request = client.get_cap_request();
            request.get().set_n(234);
            let server = impls::TestInterface::new();
            let chained_call_count = server.get_call_count();
            request.get().set_in_cap(
                ::test_capnp::test_interface::ToClient::new(server).from_server::<::capnp_rpc::Server>());

            let promise = request.send();

            let mut pipeline_request = promise.pipeline.get_out_box().get_cap().foo_request();
            pipeline_request.get().set_i(321);
            let pipeline_promise = pipeline_request.send();

            let pipeline_request2 = {
                let extends_client =
                    ::test_capnp::test_extends::Client { client: promise.pipeline.get_out_box().get_cap().client };
                extends_client.grault_request()
            };
            let pipeline_promise2 = pipeline_request2.send();

            drop(promise); // Just to be annoying, drop the original promise.

            if chained_call_count.get() != 0 {
                return Promise::err(Error::failed("expeced chained_call_count to equal 0".to_string()));
            }

            pipeline_promise.promise.then(move |response| {
                if pry!(pry!(response.get()).get_x()) != "bar" {
                    return Promise::err(Error::failed("expected x to equal 'bar'".to_string()));
                }
                pipeline_promise2.promise.then(move |response| {
                    ::test_util::CheckTestMessage::check_test_message(pry!(response.get()));
                    assert_eq!(chained_call_count.get(), 1);
                    Promise::ok(())
                })
            })
        })
    });
}

#[test]
fn null_capability() {
    let mut message = ::capnp::message::Builder::new_default();
    let root: ::test_capnp::test_all_types::Builder = message.get_root().unwrap();

    // In capnproto-c++, this would return a BrokenCap. Here, it returns a decode error.
    // Would it be worthwhile to try to match the C++ behavior here? We would need something
    // like the BrokenCapFactory singleton.
    assert!(root.get_interface_field().is_err());
}

#[test]
fn release_simple() {
    set_up_rpc(|client| {
        client.test_more_stuff_request().send().promise.then(|response| {
            let client = pry!(pry!(response.get()).get_cap());

            Promise::all(vec![
                client.get_handle_request().send().promise,
                client.get_handle_request().send().promise].into_iter()).then(move |responses| {
                let handle1 = pry!(pry!(responses[0].get()).get_handle());
                let handle2 = pry!(pry!(responses[1].get()).get_handle());

                let client1 = client.clone();
                let client2 = client.clone();
                client.get_handle_count_request().send().promise.map(|response| {
                    if try!(response.get()).get_count() != 2 {
                        Err(Error::failed("expected handle count to equal 2".to_string()))
                    } else {
                        Ok(())
                    }
                }).then(move |()| {
                    drop(handle1);
                    client1.get_handle_count_request().send().promise.map(|response| {
                        if try!(response.get()).get_count() != 1 {
                            Err(Error::failed("expected handle count to equal 1".to_string()))
                        } else {
                            Ok(())
                        }
                    })
                }).then(move |()| {
                    drop(handle2);
                    client2.get_handle_count_request().send().promise.map(|response| {
                        if try!(response.get()).get_count() != 0 {
                            Err(Error::failed("expected handle count to equal 0".to_string()))
                        } else {
                            Ok(())
                        }
                    })
                })
            })
        })
    });
}

#[test]
fn promise_resolve() {
    set_up_rpc(|client| {
        client.test_more_stuff_request().send().promise.then(|response| {
            let client = pry!(pry!(response.get()).get_cap());

            let mut request = client.call_foo_request();
            let mut request2 = client.call_foo_when_resolved_request();

            let (paf_promise, paf_fulfiller) =
                Promise::<::test_capnp::test_interface::Client, Error>::and_fulfiller();

            {
                let mut fork = paf_promise.fork();
                let cap1 = ::capnp_rpc::new_promise_client(fork.add_branch().map(|c| Ok(c.client)));
                let cap2 = ::capnp_rpc::new_promise_client(fork.add_branch().map(|c| Ok(c.client)));
                request.get().set_cap(cap1);
                request2.get().set_cap(cap2);
            }

            let promise = request.send().promise;
            let promise2 = request2.send().promise;

            // Make sure getCap() has been called on the server side by sending another call and waiting
            // for it.
            let client2 = ::test_capnp::test_call_order::Client { client: client.clone().client };
            client2.get_call_sequence_request().send().promise.then(move |_response| {
                let server = impls::TestInterface::new();

                paf_fulfiller.fulfill(
                    ::test_capnp::test_interface::ToClient::new(server).from_server::<::capnp_rpc::Server>());

                promise.then(move |response| {
                    if pry!(pry!(response.get()).get_s()) != "bar" {
                        return Promise::err(Error::failed("expected s to equal 'bar'".to_string()));
                    }
                    promise2.then(move |response| {
                        if pry!(pry!(response.get()).get_s()) != "bar" {
                            return Promise::err(Error::failed("expected s to equal 'bar'".to_string()));
                        }

                        Promise::ok(())
                    })
                })
            })
        })
    });
}

fn get_call_sequence(client: &::test_capnp::test_call_order::Client, expected: u32)
                     -> ::capnp::capability::RemotePromise<::test_capnp::test_call_order::get_call_sequence_results::Owned>
{
    let mut req = client.get_call_sequence_request();
    req.get().set_expected(expected);
    req.send()
}

#[test]
fn embargo_success() {
    set_up_rpc(|client| {
        client.test_more_stuff_request().send().promise.then(|response| {
            let client = pry!(pry!(response.get()).get_cap());

            let server = ::impls::TestCallOrder::new();

            // ugh, we need upcasting.
            let client2 = ::test_capnp::test_call_order::Client { client: client.clone().client };
            let early_call = client2.get_call_sequence_request().send();
            drop(client2);

            let mut echo_request = client.echo_request();
            echo_request.get().set_cap(
                ::test_capnp::test_call_order::ToClient::new(server).from_server::<::capnp_rpc::Server>());
            let echo = echo_request.send();

            let pipeline = echo.pipeline.get_cap();

            let call0 = get_call_sequence(&pipeline, 0);
            let call1 = get_call_sequence(&pipeline, 1);

            early_call.promise.then(move |_early_call_response| {
                let call2 = get_call_sequence(&pipeline, 2);
                echo.promise.then(move |_echo_response| {
                    let call3 = get_call_sequence(&pipeline, 3);
                    let call4 = get_call_sequence(&pipeline, 4);
                    let call5 = get_call_sequence(&pipeline, 5);
                    Promise::all(vec![call0.promise,
                                      call1.promise,
                                      call2.promise,
                                      call3.promise,
                                      call4.promise,
                                      call5.promise].into_iter()).map(|responses| {
                        let mut counter = 0;
                        for r in responses.into_iter() {
                            if counter != try!(r.get()).get_n() {
                                return Err(Error::failed(
                                    "calls arrived out of order".to_string()))
                            }
                            counter += 1;
                        }
                        Ok(())
                    })
                })
            })
        })
    });
}

#[test]
fn echo_destruction() {
    set_up_rpc(|client| {
        client.test_more_stuff_request().send().promise.then(|response| {
            let client = pry!(pry!(response.get()).get_cap());

            let (promise, fulfiller) =
                Promise::<::test_capnp::test_call_order::Client, Error>::and_fulfiller();

            let cap = ::capnp_rpc::new_promise_client(promise.map(|c| Ok(c.client)));

            // ugh, we need upcasting.
            let client2 = ::test_capnp::test_call_order::Client { client: client.clone().client };
            let early_call = client2.get_call_sequence_request().send();
            drop(client2);

            let mut echo_request = client.echo_request();
            echo_request.get().set_cap(cap);
            let echo = echo_request.send();

            let pipeline = echo.pipeline.get_cap();

            early_call.promise.then(move |_early_call_response| {
                let _ = get_call_sequence(&pipeline, 2);
                echo.promise.then(move |_echo_response| {
                    fulfiller.reject(Error::failed("foo".to_string()));
                    Promise::ok(())
                })
            })
        })
    });
}
<|endoftext|>


<commit_before>use super::super::{Grid, Coord, FiniteSearchQueue};
use super::*;

#[derive(Clone, Copy)]
struct FieldGrp {
    unmet_num: i32,
    unmet_sum: i32,
    unused: Cand,
}
pub struct Field<'a> {
    dic: &'a Dictionary,
    shape: FieldShape,
    grps: Vec<FieldGrp>,
    val: Vec<i32>,
    cand: Vec<Cand>,
    inconsistent: bool,
    queue: FiniteSearchQueue
}
impl<'a> Field<'a> {
    pub fn new(problem: &Grid<Clue>, dic: &'a Dictionary) -> Field<'a> {
        let n_cells = (problem.height() * problem.width()) as usize;
        let mut has_clue = Grid::new(problem.height(), problem.width(), false);
        for i in 0..n_cells {
            if let Clue::Clue { vertical: _, horizontal: _ } = problem[i] {
                has_clue[i] = true;
            }
        }
        let shape = FieldShape::new(&has_clue);

        let mut grps = vec![FieldGrp {
            unmet_num: 0,
            unmet_sum: 0,
            unused: 0,
        }; shape.group_to_cells.len()];
        let n_groups = grps.len();

        for i in 0..shape.group_to_cells.len() {
            let loc = shape.clue_locations[i];
            let clue_val = match loc {
                ClueLocation::Vertical(v) => match problem[v as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: v, horizontal: _ } => v,
                },
                ClueLocation::Horizontal(h) => match problem[h as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: _, horizontal: h } => h,
                },
            };
            let mut n_cells = 0;
            for _ in shape.group_to_cells[i] {
                n_cells += 1;
            }
            grps[i] = FieldGrp {
                unmet_num: n_cells,
                unmet_sum: clue_val,
                unused: CAND_ALL,
            };
        }

        Field {
            dic: dic,
            shape: shape,
            grps: grps,
            val: vec![UNDECIDED; n_cells],
            cand: vec![CAND_ALL; n_cells],
            inconsistent: false,
            queue: FiniteSearchQueue::new(n_groups as i32),
        }
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn height(&self) -> i32 {
        self.shape.has_clue.height()
    }
    pub fn width(&self) -> i32 {
        self.shape.has_clue.width()
    }
    pub fn val(&self, loc: Coord) -> i32 {
        self.val[self.location(loc)]
    }
    pub fn decide(&mut self, loc: Coord, val: i32) {
        let loc = self.location(loc);

        self.queue.start();
        self.decide_int(loc, val);
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();

    }
    pub fn check_all(&mut self) {
        self.queue.start();
        for i in 0..(self.grps.len() as i32) {
            self.queue.push(i);
        }
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();
    }
    fn location(&self, loc: Coord) -> usize {
        self.shape.has_clue.index(loc)
    }
    fn decide_int(&mut self, loc: usize, val: i32) {
        if self.val[loc] != UNDECIDED {
            if self.val[loc] != val {
                self.inconsistent = true;
            }
            return;
        }

        self.val[loc] = val;
        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.grps[g1 as usize].unmet_num -= 1;
        self.grps[g1 as usize].unmet_sum -= val;
        if (self.grps[g1 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g1 as usize].unused &= !(1 << (val - 1) as Cand);
        self.grps[g2 as usize].unmet_num -= 1;
        self.grps[g2 as usize].unmet_sum -= val;
        if (self.grps[g2 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g2 as usize].unused &= !(1 << (val - 1) as Cand);

        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn limit_cand(&mut self, loc: usize, lim: Cand) {
        if self.cand[loc] & lim == self.cand[loc] {
            return;
        }
        self.cand[loc] &= lim;

        let current_cand = self.cand[loc];
        if current_cand == 0 {
            self.inconsistent = true;
            return;
        }
        if current_cand.count_ones() == 1 {
            self.decide_int(loc, (current_cand.trailing_zeros() + 1) as i32);
        }

        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn check_group(&mut self, gid: i32) {
        let grp = self.grps[gid as usize];
        let (imperative, allowed) = self.dic.at(grp.unmet_num, grp.unmet_sum, grp.unused);

        // unique position technique
        if imperative != 0 {
            let mut uniq = 0;
            let mut mult = 0;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    mult |= uniq & self.cand[c as usize];
                    uniq |= self.cand[c as usize];
                }
            }
            uniq &= imperative & !mult;
            if uniq != 0 {
                for c in self.shape.group_to_cells[gid as usize] {
                    if self.val[c as usize] == UNDECIDED && (self.cand[c as usize] & uniq) != 0 {
                        let val = ((self.cand[c as usize] & uniq).trailing_zeros() + 1) as i32;
                        self.decide_int(c as usize, val);
                    }
                }
            }
        }

        // candidate limitation
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] == UNDECIDED {
                self.limit_cand(c as usize, allowed);
            }
        }

        // two-cells propagation (TODO: improve complexity)
        let grp = self.grps[gid as usize];
        if grp.unmet_num == 2 {
            let mut c1 = -1;
            let mut c2 = -1;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    if c1 == -1 {
                        c1 = c;
                    } else {
                        c2 = c;
                    }
                }
            }
            for i in 1..(MAX_VAL + 1) {
                if (self.cand[c1 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    self.limit_cand(c2 as usize, !(1 << (grp.unmet_sum - i - 1) as Cand));
                }
                if (self.cand[c2 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    self.limit_cand(c1 as usize, !(1 << (grp.unmet_sum - i - 1) as Cand));
                }
            }
        }

        // naked pair (TODO: improve complexity)
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            for d in self.shape.group_to_cells[gid as usize] {
                if self.val[d as usize] != -1 { continue; }
                if c != d && self.cand[c as usize] == self.cand[d as usize] && self.cand[c as usize].count_ones() == 2 {
                    for e in self.shape.group_to_cells[gid as usize] {
                        if c != e && d != e {
                            let lim = !self.cand[c as usize];
                            self.limit_cand(e as usize, lim);
                        }
                    }
                }
            }
        }

        // min-max method
        let grp = self.grps[gid as usize];
        let mut min_sum = 0;
        let mut max_sum = 0;
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];
            min_sum += cand.trailing_zeros() + 1;
            max_sum += 32 - cand.leading_zeros();
        }
        let mut lim_list = vec![];
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];

            let current_max = grp.unmet_sum - (min_sum - (cand.trailing_zeros() + 1)) as i32;
            let current_min = grp.unmet_sum - (max_sum - (32 - cand.leading_zeros())) as i32;

            let mut lim = CAND_ALL;
            if current_max <= 8 {
                lim &= (1 << current_max as Cand) - 1;
            }
            if current_min >= 2 {
                lim &= !((1 << (current_min as Cand - 1)) - 1);
            }
            if lim != CAND_ALL {
                lim_list.push((c, lim));
            }
        }
        for (c, l) in lim_list {
            self.limit_cand(c as usize, l);
        }
    }
}

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

    #[test]
    fn test_field() {
        let dic = Dictionary::default();
        let mut problem_base = Grid::new(3, 3, Clue::NoClue);
        problem_base[Coord { y: 0, x: 0 }] = Clue::Clue { horizontal: -1, vertical: -1 };
        problem_base[Coord { y: 0, x: 1 }] = Clue::Clue { horizontal: -1, vertical: 3 };
        problem_base[Coord { y: 0, x: 2 }] = Clue::Clue { horizontal: -1, vertical: 8 };
        problem_base[Coord { y: 1, x: 0 }] = Clue::Clue { horizontal: 4, vertical: -1 };
        problem_base[Coord { y: 2, x: 0 }] = Clue::Clue { horizontal: 7, vertical: -1 };

        let mut field = Field::new(&problem_base, &dic);
        field.check_all();

        assert_eq!(field.val(Coord { y: 1, x: 1 }), 1);
        assert_eq!(field.val(Coord { y: 1, x: 2 }), 3);
        assert_eq!(field.val(Coord { y: 2, x: 1 }), 2);
        assert_eq!(field.val(Coord { y: 2, x: 2 }), 5);
        assert_eq!(field.inconsistent(), false);
    }
}
<commit_msg>Kakuro: use eliminate_cand_from_group in Field<commit_after>use super::super::{Grid, Coord, FiniteSearchQueue};
use super::*;

#[derive(Clone, Copy)]
struct FieldGrp {
    unmet_num: i32,
    unmet_sum: i32,
    unused: Cand,
}
pub struct Field<'a> {
    dic: &'a Dictionary,
    shape: FieldShape,
    grps: Vec<FieldGrp>,
    val: Vec<i32>,
    cand: Vec<Cand>,
    inconsistent: bool,
    queue: FiniteSearchQueue
}
impl<'a> Field<'a> {
    pub fn new(problem: &Grid<Clue>, dic: &'a Dictionary) -> Field<'a> {
        let n_cells = (problem.height() * problem.width()) as usize;
        let mut has_clue = Grid::new(problem.height(), problem.width(), false);
        for i in 0..n_cells {
            if let Clue::Clue { vertical: _, horizontal: _ } = problem[i] {
                has_clue[i] = true;
            }
        }
        let shape = FieldShape::new(&has_clue);

        let mut grps = vec![FieldGrp {
            unmet_num: 0,
            unmet_sum: 0,
            unused: 0,
        }; shape.group_to_cells.len()];
        let n_groups = grps.len();

        for i in 0..shape.group_to_cells.len() {
            let loc = shape.clue_locations[i];
            let clue_val = match loc {
                ClueLocation::Vertical(v) => match problem[v as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: v, horizontal: _ } => v,
                },
                ClueLocation::Horizontal(h) => match problem[h as usize] {
                    Clue::NoClue => panic!("unexpected condition"),
                    Clue::Clue { vertical: _, horizontal: h } => h,
                },
            };
            let mut n_cells = 0;
            for _ in shape.group_to_cells[i] {
                n_cells += 1;
            }
            grps[i] = FieldGrp {
                unmet_num: n_cells,
                unmet_sum: clue_val,
                unused: CAND_ALL,
            };
        }

        Field {
            dic: dic,
            shape: shape,
            grps: grps,
            val: vec![UNDECIDED; n_cells],
            cand: vec![CAND_ALL; n_cells],
            inconsistent: false,
            queue: FiniteSearchQueue::new(n_groups as i32),
        }
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn height(&self) -> i32 {
        self.shape.has_clue.height()
    }
    pub fn width(&self) -> i32 {
        self.shape.has_clue.width()
    }
    pub fn val(&self, loc: Coord) -> i32 {
        self.val[self.location(loc)]
    }
    pub fn decide(&mut self, loc: Coord, val: i32) {
        let loc = self.location(loc);

        self.queue.start();
        self.decide_int(loc, val);
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();

    }
    pub fn check_all(&mut self) {
        self.queue.start();
        for i in 0..(self.grps.len() as i32) {
            self.queue.push(i);
        }
        while !self.queue.empty() {
            let g = self.queue.pop();
            self.check_group(g);
        }
        self.queue.finish();
    }
    fn location(&self, loc: Coord) -> usize {
        self.shape.has_clue.index(loc)
    }
    fn decide_int(&mut self, loc: usize, val: i32) {
        if self.val[loc] != UNDECIDED {
            if self.val[loc] != val {
                self.inconsistent = true;
            }
            return;
        }

        self.val[loc] = val;
        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.grps[g1 as usize].unmet_num -= 1;
        self.grps[g1 as usize].unmet_sum -= val;
        if (self.grps[g1 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g1 as usize].unused &= !(1 << (val - 1) as Cand);
        self.grps[g2 as usize].unmet_num -= 1;
        self.grps[g2 as usize].unmet_sum -= val;
        if (self.grps[g2 as usize].unused & (1 << (val - 1) as Cand)) == 0 {
            self.inconsistent = true;
            return;
        }
        self.grps[g2 as usize].unused &= !(1 << (val - 1) as Cand);

        self.eliminate_cand_from_group(g1, val, loc as i32);
        self.eliminate_cand_from_group(g2, val, loc as i32);

        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn eliminate_cand_from_group(&mut self, grp: i32, rem_cand: i32, cur: i32) {
        let cand = !(1 << (rem_cand - 1) as Cand);
        for c in self.shape.group_to_cells[grp as usize] {
            if c != cur {
                self.limit_cand(c as usize, cand);
            }
        }
    }
    fn limit_cand(&mut self, loc: usize, lim: Cand) {
        if self.cand[loc] & lim == self.cand[loc] {
            return;
        }
        self.cand[loc] &= lim;

        let current_cand = self.cand[loc];
        if current_cand == 0 {
            self.inconsistent = true;
            return;
        }
        if current_cand.count_ones() == 1 {
            self.decide_int(loc, (current_cand.trailing_zeros() + 1) as i32);
        }

        let (g1, g2) = self.shape.cell_to_groups[loc];
        self.queue.push(g1);
        self.queue.push(g2);
    }
    fn check_group(&mut self, gid: i32) {
        let grp = self.grps[gid as usize];
        let (imperative, allowed) = self.dic.at(grp.unmet_num, grp.unmet_sum, grp.unused);

        // unique position technique
        if imperative != 0 {
            let mut uniq = 0;
            let mut mult = 0;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    mult |= uniq & self.cand[c as usize];
                    uniq |= self.cand[c as usize];
                }
            }
            uniq &= imperative & !mult;
            if uniq != 0 {
                for c in self.shape.group_to_cells[gid as usize] {
                    if self.val[c as usize] == UNDECIDED && (self.cand[c as usize] & uniq) != 0 {
                        let val = ((self.cand[c as usize] & uniq).trailing_zeros() + 1) as i32;
                        self.decide_int(c as usize, val);
                    }
                }
            }
        }

        // candidate limitation
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] == UNDECIDED {
                self.limit_cand(c as usize, allowed);
            }
        }

        // two-cells propagation (TODO: improve complexity)
        let grp = self.grps[gid as usize];
        if grp.unmet_num == 2 {
            let mut c1 = -1;
            let mut c2 = -1;
            for c in self.shape.group_to_cells[gid as usize] {
                if self.val[c as usize] == UNDECIDED {
                    if c1 == -1 {
                        c1 = c;
                    } else {
                        c2 = c;
                    }
                }
            }
            for i in 1..(MAX_VAL + 1) {
                if (self.cand[c1 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    self.limit_cand(c2 as usize, !(1 << (grp.unmet_sum - i - 1) as Cand));
                }
                if (self.cand[c2 as usize] & (1 << (i - 1) as Cand) == 0) && 1 <= (grp.unmet_sum - i) && (grp.unmet_sum - i) <= MAX_VAL {
                    self.limit_cand(c1 as usize, !(1 << (grp.unmet_sum - i - 1) as Cand));
                }
            }
        }

        // naked pair (TODO: improve complexity)
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            for d in self.shape.group_to_cells[gid as usize] {
                if self.val[d as usize] != -1 { continue; }
                if c != d && self.cand[c as usize] == self.cand[d as usize] && self.cand[c as usize].count_ones() == 2 {
                    for e in self.shape.group_to_cells[gid as usize] {
                        if c != e && d != e {
                            let lim = !self.cand[c as usize];
                            self.limit_cand(e as usize, lim);
                        }
                    }
                }
            }
        }

        // min-max method
        let grp = self.grps[gid as usize];
        let mut min_sum = 0;
        let mut max_sum = 0;
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];
            min_sum += cand.trailing_zeros() + 1;
            max_sum += 32 - cand.leading_zeros();
        }
        let mut lim_list = vec![];
        for c in self.shape.group_to_cells[gid as usize] {
            if self.val[c as usize] != -1 { continue; }
            let cand = self.cand[c as usize];

            let current_max = grp.unmet_sum - (min_sum - (cand.trailing_zeros() + 1)) as i32;
            let current_min = grp.unmet_sum - (max_sum - (32 - cand.leading_zeros())) as i32;

            let mut lim = CAND_ALL;
            if current_max <= 8 {
                lim &= (1 << current_max as Cand) - 1;
            }
            if current_min >= 2 {
                lim &= !((1 << (current_min as Cand - 1)) - 1);
            }
            if lim != CAND_ALL {
                lim_list.push((c, lim));
            }
        }
        for (c, l) in lim_list {
            self.limit_cand(c as usize, l);
        }
    }
}

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

    #[test]
    fn test_field() {
        let dic = Dictionary::default();
        let mut problem_base = Grid::new(3, 3, Clue::NoClue);
        problem_base[Coord { y: 0, x: 0 }] = Clue::Clue { horizontal: -1, vertical: -1 };
        problem_base[Coord { y: 0, x: 1 }] = Clue::Clue { horizontal: -1, vertical: 3 };
        problem_base[Coord { y: 0, x: 2 }] = Clue::Clue { horizontal: -1, vertical: 8 };
        problem_base[Coord { y: 1, x: 0 }] = Clue::Clue { horizontal: 4, vertical: -1 };
        problem_base[Coord { y: 2, x: 0 }] = Clue::Clue { horizontal: 7, vertical: -1 };

        let mut field = Field::new(&problem_base, &dic);
        field.check_all();

        assert_eq!(field.val(Coord { y: 1, x: 1 }), 1);
        assert_eq!(field.val(Coord { y: 1, x: 2 }), 3);
        assert_eq!(field.val(Coord { y: 2, x: 1 }), 2);
        assert_eq!(field.val(Coord { y: 2, x: 2 }), 5);
        assert_eq!(field.inconsistent(), false);
    }
}
<|endoftext|>


<commit_before>use super::*;
use toml::*;

use std::fs::File;

#[derive(Debug, RustcDecodable)]
pub struct Config {
    site: Option<SiteConfig>,
    directories: Option<DirConfig>,
}

#[derive(Debug, RustcDecodable)]
struct SiteConfig {
    name: Option<String>,
    template: Option<String>,
    author: Option<Vec<String>>,
}

#[derive(Debug, RustcDecodable)]
struct DirConfig {
    out: Option<String>,
    source: Option<String>,
    images: Option<String>,
}

impl Config {
    pub fn new() -> Config {
        let config_file = File::open("kryll.toml");
        let config_str = handle_file_string(config_file, "kryll.toml");

        let config_decode: Config = decode_str(&config_str).unwrap();
        config_decode
    }
}
<commit_msg>Update config.rs<commit_after>use super::*;
use toml::*;

use std::fs::File;

#[derive(Debug, RustcDecodable)]
pub struct Config {
    site: Option<SiteConfig>,
    directories: Option<DirConfig>,
}

#[derive(Debug, RustcDecodable)]
struct SiteConfig {
    name: Option<String>,
    template: Option<String>,
    author: Option<Vec<String>>,
}

#[derive(Debug, RustcDecodable)]
struct DirConfig {
    out: Option<String>,
    source: Option<String>,
    images: Option<String>,
}

impl Config {
    pub fn new() -> Config {
        let config_file = File::open(".kryll");
        let config_str = handle_file_string(config_file, ".kryll");

        let config_decode: Config = decode_str(&config_str).unwrap();
        config_decode
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate crayon;
#[macro_use]
extern crate lazy_static;
extern crate rand;

use crayon::prelude::*;
use std::sync::{Arc, RwLock};
use rand::{Rng, SeedableRng, XorShiftRng};

#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
struct Position {
    x: u32,
    y: u32,
}

#[derive(Debug, Clone, Default)]
struct Reference {
    value: Arc<RwLock<usize>>,
}

impl Drop for Reference {
    fn drop(&mut self) {
        *self.value.write().unwrap() += 1;
    }
}

declare_component!(Position, VecArena);
declare_component!(Reference, HashMapArena);

#[test]
fn basic() {
    let mut world = World::new();
    world.register::<Position>();

    let e1 = world.create();
    world.add::<Position>(e1, Position { x: 1, y: 2 });
    assert!(world.has::<Position>(e1));

    {
        let p = world.get::<Position>(e1).unwrap();
        assert_eq!(p, Position { x: 1, y: 2 });
    }

    {
        let mut arena = world.arena_mut::<Position>();

        let p = arena.get_mut(e1).unwrap();
        p.x = 2;
        p.y = 5;
    }

    {
        let p = world.get::<Position>(e1).unwrap();
        assert_eq!(p, Position { x: 2, y: 5 });
    }

    world.remove::<Position>(e1);
    assert!(!world.has::<Position>(e1));
    assert!(world.get::<Position>(e1).is_none());
}

#[test]
fn free() {
    let mut world = World::new();
    world.register::<Position>();
    world.register::<Reference>();

    let e1 = world.create();
    assert!(world.is_alive(e1));
    assert!(!world.has::<Position>(e1));
    assert!(world.get::<Position>(e1).is_none());

    world.add::<Position>(e1, Position { x: 1, y: 2 });
    assert!(world.has::<Position>(e1));
    world.get::<Position>(e1).unwrap();

    world.free(e1);
    assert!(!world.is_alive(e1));
    assert!(!world.has::<Position>(e1));
    assert!(world.get::<Position>(e1).is_none());

    let mut entities = Vec::new();
    let rc = Arc::new(RwLock::new(0));
    for i in 0..10 {
        let e = world.create();
        let shadow = rc.clone();
        entities.push(e);

        world.add::<Reference>(e, Reference { value: shadow });
        if i % 2 == 0 {
            world.add::<Position>(e, Position { x: 1, y: 2 });
        }
    }

    assert_eq!(*rc.read().unwrap(), 0);
    for i in 0..10 {
        world.free(entities[i]);
        assert_eq!(*rc.read().unwrap(), i + 1);
    }
    assert_eq!(*rc.read().unwrap(), 10);
}

#[test]
fn duplicated_add() {
    let mut world = World::new();
    world.register::<Position>();

    let e1 = world.create();
    assert!(world.add::<Position>(e1, Position { x: 1, y: 2 }) == None);
    assert!(world.add::<Position>(e1, Position { x: 2, y: 4 }) == Some(Position { x: 1, y: 2 }));

    assert!(world.get::<Position>(e1).unwrap() == Position { x: 2, y: 4 })
}

#[test]
fn random_allocate() {
    let mut generator = XorShiftRng::from_seed([0, 1, 2, 3]);
    let mut world = World::new();
    world.register::<Position>();
    world.register::<Reference>();

    let mut v = vec![];
    for i in 3..10 {
        let p = generator.next_u32() % i + 1;
        let r = generator.next_u32() % i + 1;
        for j in 0..100 {
            if j % p == 0 {
                let e = world.create();
                world.add::<Position>(e,
                                      Position {
                                          x: e.index(),
                                          y: e.version(),
                                      });
                if j % r == 0 {
                    world.add_with_default::<Reference>(e);
                }
                v.push(e);
            }
        }

        let size = v.len() / 2;
        for _ in 0..size {
            let len = v.len();
            world.free(v.swap_remove(generator.next_u32() as usize % len));
        }
    }

    for i in v {
        assert_eq!(world.get::<Position>(i).unwrap(),
                   Position {
                       x: i.index(),
                       y: i.version(),
                   });
    }
}

#[test]
fn iter_with() {
    let mut world = World::new();
    world.register::<Position>();
    world.register::<Reference>();

    let mut v = vec![];
    for i in 0..100 {
        let e = world.create();

        if i % 2 == 0 {
            world.add::<Position>(e,
                                  Position {
                                      x: e.index(),
                                      y: e.version(),
                                  });
        }

        if i % 3 == 0 {
            world.add_with_default::<Reference>(e);
        }

        if i % 2 == 0 && i % 3 == 0 {
            v.push(e);
        }
    }

    {
        let (view, arenas) = world.view_with_2::<Position, Reference>();
        for e in view {
            let p = Position {
                x: e.index(),
                y: e.version(),
            };

            assert_eq!(*arenas.0.get(e).unwrap(), p);
        }
    }

    {
        let (view, mut arenas) = world.view_with_2::<Position, Reference>();
        for e in view {
            arenas.0.get_mut(e).unwrap().x += e.version();
            *arenas.1.get_mut(e).unwrap().value.write().unwrap() += 1;
        }
    }

    {
        let (view, arenas) = world.view_with_2::<Position, Reference>();
        let mut iterator = view.into_iter();
        for e in &v {
            let i = iterator.next().unwrap();
            let p = Position {
                x: e.index() + e.version(),
                y: e.version(),
            };

            assert_eq!(i, *e);
            assert_eq!(*arenas.0.get(*e).unwrap(), p);
            assert_eq!(*arenas.1.get(*e).unwrap().value.read().unwrap(), 1);
        }
    }
}

#[test]
#[should_panic]
fn invalid_view() {
    let mut world = World::new();
    world.register::<Position>();

    let _i1 = world.view_with::<Position>();
    world.view_with::<Position>();
}

#[test]
fn builder() {
    let mut world = World::new();
    world.register::<Position>();
    world.register::<Reference>();

    let e1 = world.build().with_default::<Position>().finish();
    assert!(world.has::<Position>(e1));
    assert!(!world.has::<Reference>(e1));
}<commit_msg>Fixed a test case that might cause deadlock.<commit_after>#[macro_use]
extern crate crayon;
#[macro_use]
extern crate lazy_static;
extern crate rand;

use crayon::prelude::*;
use std::sync::{Arc, RwLock};
use rand::{Rng, SeedableRng, XorShiftRng};

#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
struct Position {
    x: u32,
    y: u32,
}

#[derive(Debug, Clone, Default)]
struct Reference {
    value: Arc<RwLock<usize>>,
}

impl Drop for Reference {
    fn drop(&mut self) {
        *self.value.write().unwrap() += 1;
    }
}

declare_component!(Position, VecArena);
declare_component!(Reference, HashMapArena);

#[test]
fn basic() {
    let mut world = World::new();
    world.register::<Position>();

    let e1 = world.create();
    world.add::<Position>(e1, Position { x: 1, y: 2 });
    assert!(world.has::<Position>(e1));

    {
        let p = world.get::<Position>(e1).unwrap();
        assert_eq!(p, Position { x: 1, y: 2 });
    }

    {
        let mut arena = world.arena_mut::<Position>();

        let p = arena.get_mut(e1).unwrap();
        p.x = 2;
        p.y = 5;
    }

    {
        let p = world.get::<Position>(e1).unwrap();
        assert_eq!(p, Position { x: 2, y: 5 });
    }

    world.remove::<Position>(e1);
    assert!(!world.has::<Position>(e1));
    assert!(world.get::<Position>(e1).is_none());
}

#[test]
fn free() {
    let mut world = World::new();
    world.register::<Position>();
    world.register::<Reference>();

    let e1 = world.create();
    assert!(world.is_alive(e1));
    assert!(!world.has::<Position>(e1));
    assert!(world.get::<Position>(e1).is_none());

    world.add::<Position>(e1, Position { x: 1, y: 2 });
    assert!(world.has::<Position>(e1));
    world.get::<Position>(e1).unwrap();

    world.free(e1);
    assert!(!world.is_alive(e1));
    assert!(!world.has::<Position>(e1));
    assert!(world.get::<Position>(e1).is_none());

    let mut entities = Vec::new();
    let rc = Arc::new(RwLock::new(0));
    for i in 0..10 {
        let e = world.create();
        let shadow = rc.clone();
        entities.push(e);

        world.add::<Reference>(e, Reference { value: shadow });
        if i % 2 == 0 {
            world.add::<Position>(e, Position { x: 1, y: 2 });
        }
    }

    assert_eq!(*rc.read().unwrap(), 0);
    for i in 0..10 {
        world.free(entities[i]);
        assert_eq!(*rc.read().unwrap(), i + 1);
    }
    assert_eq!(*rc.read().unwrap(), 10);
}

#[test]
fn duplicated_add() {
    let mut world = World::new();
    world.register::<Position>();

    let e1 = world.create();
    assert!(world.add::<Position>(e1, Position { x: 1, y: 2 }) == None);
    assert!(world.add::<Position>(e1, Position { x: 2, y: 4 }) == Some(Position { x: 1, y: 2 }));

    assert!(world.get::<Position>(e1).unwrap() == Position { x: 2, y: 4 })
}

#[test]
fn random_allocate() {
    let mut generator = XorShiftRng::from_seed([0, 1, 2, 3]);
    let mut world = World::new();
    world.register::<Position>();
    world.register::<Reference>();

    let mut v = vec![];
    for i in 3..10 {
        let p = generator.next_u32() % i + 1;
        let r = generator.next_u32() % i + 1;
        for j in 0..100 {
            if j % p == 0 {
                let e = world.create();
                world.add::<Position>(e,
                                      Position {
                                          x: e.index(),
                                          y: e.version(),
                                      });
                if j % r == 0 {
                    world.add_with_default::<Reference>(e);
                }
                v.push(e);
            }
        }

        let size = v.len() / 2;
        for _ in 0..size {
            let len = v.len();
            world.free(v.swap_remove(generator.next_u32() as usize % len));
        }
    }

    for i in v {
        assert_eq!(world.get::<Position>(i).unwrap(),
                   Position {
                       x: i.index(),
                       y: i.version(),
                   });
    }
}

#[test]
fn iter_with() {
    let mut world = World::new();
    world.register::<Position>();
    world.register::<Reference>();

    let mut v = vec![];
    for i in 0..100 {
        let e = world.create();

        if i % 2 == 0 {
            world.add::<Position>(e,
                                  Position {
                                      x: e.index(),
                                      y: e.version(),
                                  });
        }

        if i % 3 == 0 {
            world.add_with_default::<Reference>(e);
        }

        if i % 2 == 0 && i % 3 == 0 {
            v.push(e);
        }
    }

    {
        let (view, arenas) = world.view_with_2::<Position, Reference>();
        for e in view {
            let p = Position {
                x: e.index(),
                y: e.version(),
            };

            assert_eq!(*arenas.0.get(e).unwrap(), p);
        }
    }

    {
        let (view, mut arenas) = world.view_with_2::<Position, Reference>();
        for e in view {
            arenas.0.get_mut(e).unwrap().x += e.version();
            *arenas.1.get_mut(e).unwrap().value.write().unwrap() += 1;
        }
    }

    {
        let (view, arenas) = world.view_with_2::<Position, Reference>();
        let mut iterator = view.into_iter();
        for e in &v {
            let i = iterator.next().unwrap();
            let p = Position {
                x: e.index() + e.version(),
                y: e.version(),
            };

            assert_eq!(i, *e);
            assert_eq!(*arenas.0.get(*e).unwrap(), p);
            assert_eq!(*arenas.1.get(*e).unwrap().value.read().unwrap(), 1);
        }
    }
}

// #[test]
// #[should_panic]
// fn invalid_view() {
//     let mut world = World::new();
//     world.register::<Position>();
//     let _i1 = world.view_with::<Position>();
//     world.view_with::<Position>();
// }

#[test]
fn builder() {
    let mut world = World::new();
    world.register::<Position>();
    world.register::<Reference>();

    let e1 = world.build().with_default::<Position>().finish();
    assert!(world.has::<Position>(e1));
    assert!(!world.has::<Reference>(e1));
}<|endoftext|>


<commit_before>extern crate multiaddr;

use multiaddr::*;

#[test]
fn protocols_to_u16() {
    assert_eq!(ProtocolTypes::TCP.to_code(), 6u16);
}

#[test]
fn protocols_from_u16() {
    assert_eq!(ProtocolTypes::from_code(6u16), Some(ProtocolTypes::TCP));
    assert_eq!(ProtocolTypes::from_code(455u16), None);
}

#[test]
fn protocols_to_size() {
    assert_eq!(ProtocolTypes::TCP.to_size(), 16);
}

#[test]
fn protocols_to_name() {
    assert_eq!(ProtocolTypes::TCP.to_name(), "tcp");
}

#[test]
fn multiaddr_eq() {
    assert!(
        Multiaddr::new("/ip4/127.0.0.1").unwrap() == Multiaddr::new("/ip4/127.0.0.1").unwrap()
    );
    assert!(
        Multiaddr::new("/ip4/127.0.0.1").unwrap() != Multiaddr::new("/ip4/128.0.0.1").unwrap()
    );
}

fn assert_bytes(source: &str, target: &[u8], protocols: Vec<ProtocolTypes>) -> () {
    let address = Multiaddr::new(source).unwrap();
    println!("source {:?}, target {:?}", source, target);
    assert_eq!(address.to_bytes(), target);
    assert_eq!(address.protocols(), protocols);
}

#[test]
fn byte_formats() {
    assert_bytes("/ip4/1.2.3.4", &[0, 4, 1, 2, 3, 4], vec![ProtocolTypes::IP4]);
    assert_bytes("/ip4/0.0.0.0", &[0, 4, 0, 0, 0, 0], vec![ProtocolTypes::IP4]);
    assert_bytes("/ip6/::1", &[
        0, 41,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
    ], vec![ProtocolTypes::IP6]);
    assert_bytes("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21", &[
        0, 41,
        38, 1, 0, 9, 79, 129, 151, 0, 128, 62, 202, 101, 102, 232, 12, 33
    ], vec![ProtocolTypes::IP6]);
    // assert_bytes("/onion/timaq4ygg2iegci7:1234", &[], vec![ProtocolTypes::Onion]);
    // assert_bytes("/onion/timaq4ygg2iegci7:80/http", &[], vec![ProtocolTypes::Onion]);
    assert_bytes("/udp/0", &[0, 17, 0, 0], vec![ProtocolTypes::UDP]);
    assert_bytes("/tcp/0", &[0, 6, 0, 0], vec![ProtocolTypes::TCP]);
    assert_bytes("/sctp/0", &[0, 132, 0, 0], vec![ProtocolTypes::SCTP]);
    assert_bytes("/udp/1234", &[0, 17, 4, 210], vec![ProtocolTypes::UDP]);
    assert_bytes("/tcp/1234", &[0, 6, 4, 210], vec![ProtocolTypes::TCP]);
    assert_bytes("/sctp/1234", &[0, 132, 4, 210], vec![ProtocolTypes::SCTP]);
    assert_bytes("/udp/65535", &[0, 17, 255, 255], vec![ProtocolTypes::UDP]);
    assert_bytes("/tcp/65535", &[0, 6, 255, 255], vec![ProtocolTypes::TCP]);
    // assert_bytes("/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", &[], vec![ProtocolTypes::IPFS]);
    assert_bytes("/udp/1234/sctp/1234", &[
        0, 17, 4, 210,
        0, 132, 4, 210
    ], vec![ProtocolTypes::UDP, ProtocolTypes::SCTP]);
    assert_bytes("/udp/1234/udt", &[
        0, 17, 4, 210,
        1, 46
    ], vec![ProtocolTypes::UDP, ProtocolTypes::UDT]);
    assert_bytes("/udp/1234/utp", &[
        0, 17, 4, 210,
        1, 45
    ], vec![ProtocolTypes::UDP, ProtocolTypes::UTP]);
    assert_bytes("/tcp/1234/http", &[
        0, 6, 4, 210,
        1, 224
    ], vec![ProtocolTypes::TCP, ProtocolTypes::HTTP]);
    assert_bytes("/tcp/1234/https", &[
        0, 6, 4, 210,
        1, 187
    ], vec![ProtocolTypes::TCP, ProtocolTypes::HTTPS]);
    // assert_bytes("/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", &[
    // ], vec![ProtocolTypes::IPFS, ProtocolTypes::TCP]);
    assert_bytes("/ip4/127.0.0.1/udp/1234", &[
        0, 4, 127, 0, 0, 1,
        0, 17, 4, 210
    ], vec![ProtocolTypes::IP4, ProtocolTypes::UDP]);
    assert_bytes("/ip4/127.0.0.1/udp/0", &[
        0, 4, 127, 0, 0, 1,
        0, 17, 0, 0
    ], vec![ProtocolTypes::IP4, ProtocolTypes::UDP]);
    assert_bytes("/ip4/127.0.0.1/tcp/1234", &[
        0, 4, 127, 0, 0, 1,
        0, 6, 4, 210
    ], vec![ProtocolTypes::IP4, ProtocolTypes::TCP]);
    assert_bytes("/ip4/127.0.0.1/tcp/1234/", &[
        0, 4, 127, 0, 0, 1,
        0, 6, 4, 210
    ], vec![ProtocolTypes::IP4, ProtocolTypes::TCP]);
    // assert_bytes("/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", &[], vec![]);
    // assert_bytes("/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", &[], vec![]);
}

#[test]
fn multiaddr_new_fail() {
    let addresses = [
        "/ip4",
	"/ip4/::1",
	"/ip4/fdpsofodsajfdoisa",
	"/ip6",
	"/udp",
	"/tcp",
	"/sctp",
	"/udp/65536",
	"/tcp/65536",
	"/onion/9imaq4ygg2iegci7:80",
	"/onion/aaimaq4ygg2iegci7:80",
	"/onion/timaq4ygg2iegci7:0",
	"/onion/timaq4ygg2iegci7:-1",
	"/onion/timaq4ygg2iegci7",
	"/onion/timaq4ygg2iegci@:666",
	"/udp/1234/sctp",
	"/udp/1234/udt/1234",
	"/udp/1234/utp/1234",
	"/ip4/127.0.0.1/udp/jfodsajfidosajfoidsa",
	"/ip4/127.0.0.1/udp",
	"/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa",
	"/ip4/127.0.0.1/tcp",
	"/ip4/127.0.0.1/ipfs",
	"/ip4/127.0.0.1/ipfs/tcp",
    ];

    for address in &addresses {
        assert!(Multiaddr::new(address).is_err());
    }
}
<commit_msg>Better equality tests<commit_after>extern crate multiaddr;

use multiaddr::*;

#[test]
fn protocols_to_u16() {
    assert_eq!(ProtocolTypes::TCP.to_code(), 6u16);
}

#[test]
fn protocols_from_u16() {
    assert_eq!(ProtocolTypes::from_code(6u16), Some(ProtocolTypes::TCP));
    assert_eq!(ProtocolTypes::from_code(455u16), None);
}

#[test]
fn protocols_to_size() {
    assert_eq!(ProtocolTypes::TCP.to_size(), 16);
}

#[test]
fn protocols_to_name() {
    assert_eq!(ProtocolTypes::TCP.to_name(), "tcp");
}

#[test]
fn multiaddr_eq() {
    let m1 = Multiaddr::new("/ip4/127.0.0.1/udp/1234").unwrap();
    let m2 = Multiaddr::new("/ip4/127.0.0.1/tcp/1234").unwrap();
    let m3 = Multiaddr::new("/ip4/127.0.0.1/tcp/1234").unwrap();
    let m4 = Multiaddr::new("/ip4/127.0.0.1/tcp/1234/").unwrap();

    assert!(m1 != m2);
    assert!(m2 != m1);
    assert!(m2 == m3);
    assert!(m1 == m1);
    assert!(m2 == m4);
    assert!(m4 == m3);
}

fn assert_bytes(source: &str, target: &[u8], protocols: Vec<ProtocolTypes>) -> () {
    let address = Multiaddr::new(source).unwrap();
    println!("source {:?}, target {:?}", source, target);
    assert_eq!(address.to_bytes(), target);
    assert_eq!(address.protocols(), protocols);
}

#[test]
fn byte_formats() {
    assert_bytes("/ip4/1.2.3.4", &[0, 4, 1, 2, 3, 4], vec![ProtocolTypes::IP4]);
    assert_bytes("/ip4/0.0.0.0", &[0, 4, 0, 0, 0, 0], vec![ProtocolTypes::IP4]);
    assert_bytes("/ip6/::1", &[
        0, 41,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
    ], vec![ProtocolTypes::IP6]);
    assert_bytes("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21", &[
        0, 41,
        38, 1, 0, 9, 79, 129, 151, 0, 128, 62, 202, 101, 102, 232, 12, 33
    ], vec![ProtocolTypes::IP6]);
    // assert_bytes("/onion/timaq4ygg2iegci7:1234", &[], vec![ProtocolTypes::Onion]);
    // assert_bytes("/onion/timaq4ygg2iegci7:80/http", &[], vec![ProtocolTypes::Onion]);
    assert_bytes("/udp/0", &[0, 17, 0, 0], vec![ProtocolTypes::UDP]);
    assert_bytes("/tcp/0", &[0, 6, 0, 0], vec![ProtocolTypes::TCP]);
    assert_bytes("/sctp/0", &[0, 132, 0, 0], vec![ProtocolTypes::SCTP]);
    assert_bytes("/udp/1234", &[0, 17, 4, 210], vec![ProtocolTypes::UDP]);
    assert_bytes("/tcp/1234", &[0, 6, 4, 210], vec![ProtocolTypes::TCP]);
    assert_bytes("/sctp/1234", &[0, 132, 4, 210], vec![ProtocolTypes::SCTP]);
    assert_bytes("/udp/65535", &[0, 17, 255, 255], vec![ProtocolTypes::UDP]);
    assert_bytes("/tcp/65535", &[0, 6, 255, 255], vec![ProtocolTypes::TCP]);
    // assert_bytes("/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", &[], vec![ProtocolTypes::IPFS]);
    assert_bytes("/udp/1234/sctp/1234", &[
        0, 17, 4, 210,
        0, 132, 4, 210
    ], vec![ProtocolTypes::UDP, ProtocolTypes::SCTP]);
    assert_bytes("/udp/1234/udt", &[
        0, 17, 4, 210,
        1, 46
    ], vec![ProtocolTypes::UDP, ProtocolTypes::UDT]);
    assert_bytes("/udp/1234/utp", &[
        0, 17, 4, 210,
        1, 45
    ], vec![ProtocolTypes::UDP, ProtocolTypes::UTP]);
    assert_bytes("/tcp/1234/http", &[
        0, 6, 4, 210,
        1, 224
    ], vec![ProtocolTypes::TCP, ProtocolTypes::HTTP]);
    assert_bytes("/tcp/1234/https", &[
        0, 6, 4, 210,
        1, 187
    ], vec![ProtocolTypes::TCP, ProtocolTypes::HTTPS]);
    // assert_bytes("/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", &[
    // ], vec![ProtocolTypes::IPFS, ProtocolTypes::TCP]);
    assert_bytes("/ip4/127.0.0.1/udp/1234", &[
        0, 4, 127, 0, 0, 1,
        0, 17, 4, 210
    ], vec![ProtocolTypes::IP4, ProtocolTypes::UDP]);
    assert_bytes("/ip4/127.0.0.1/udp/0", &[
        0, 4, 127, 0, 0, 1,
        0, 17, 0, 0
    ], vec![ProtocolTypes::IP4, ProtocolTypes::UDP]);
    assert_bytes("/ip4/127.0.0.1/tcp/1234", &[
        0, 4, 127, 0, 0, 1,
        0, 6, 4, 210
    ], vec![ProtocolTypes::IP4, ProtocolTypes::TCP]);
    assert_bytes("/ip4/127.0.0.1/tcp/1234/", &[
        0, 4, 127, 0, 0, 1,
        0, 6, 4, 210
    ], vec![ProtocolTypes::IP4, ProtocolTypes::TCP]);
    // assert_bytes("/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", &[], vec![]);
    // assert_bytes("/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", &[], vec![]);
}

#[test]
fn multiaddr_new_fail() {
    let addresses = [
        "/ip4",
	"/ip4/::1",
	"/ip4/fdpsofodsajfdoisa",
	"/ip6",
	"/udp",
	"/tcp",
	"/sctp",
	"/udp/65536",
	"/tcp/65536",
	"/onion/9imaq4ygg2iegci7:80",
	"/onion/aaimaq4ygg2iegci7:80",
	"/onion/timaq4ygg2iegci7:0",
	"/onion/timaq4ygg2iegci7:-1",
	"/onion/timaq4ygg2iegci7",
	"/onion/timaq4ygg2iegci@:666",
	"/udp/1234/sctp",
	"/udp/1234/udt/1234",
	"/udp/1234/utp/1234",
	"/ip4/127.0.0.1/udp/jfodsajfidosajfoidsa",
	"/ip4/127.0.0.1/udp",
	"/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa",
	"/ip4/127.0.0.1/tcp",
	"/ip4/127.0.0.1/ipfs",
	"/ip4/127.0.0.1/ipfs/tcp",
    ];

    for address in &addresses {
        assert!(Multiaddr::new(address).is_err());
    }
}
<|endoftext|>


<commit_before>extern crate mtl;
extern crate cocoa;

use mtl::{CompileOptions, Device, LanguageVersion, SpecificLanguageVersion};
use mtl::LibraryErrorType;
use mtl::{FromRaw, FromRawError, IntoRaw};
use mtl::sys::{MTLCompileOptions, MTLLanguageVersion};
use cocoa::base::{BOOL, nil};
use cocoa::foundation::NSString;

#[test]
fn get_device() {
    let device = Device::system_default_device();
    assert!(device.is_ok());
}

#[test]
fn get_all_devices() {
    let all_devices = Device::enumerate_all_system_devices();
    assert!(!all_devices.is_empty());
    for device in all_devices {
        assert!(device.is_ok());
    }
}

#[test]
fn get_device_name() {
    let device = Device::system_default_device().unwrap();
    assert!(!device.name().into_owned().is_empty());
}

#[test]
fn set_get_command_queue_label() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();

    const DUMMY_COMMAND_QUEUE_NAME: &'static str = "foo";
    command_queue.set_label(&DUMMY_COMMAND_QUEUE_NAME);

    assert_eq!(command_queue.label(),
               DUMMY_COMMAND_QUEUE_NAME);
}

#[test]
fn insert_debug_capture_boundary_on_command_queue() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();
    command_queue.insert_debug_capture_boundary();

    // if nothing panics/fails here, everything is okay
}

#[test]
fn device_from_to_raw() {
    let device = Device::system_default_device().unwrap();
    let raw = device.into_raw();
    let device = Device::from_raw(raw);
    assert!(device.is_ok());
}

#[test]
fn device_from_wrong_type() {
    let some_string = unsafe { NSString::alloc(nil).init_str("Hello") };
    let device_result = Device::from_raw(some_string);
    match device_result {
        Result::Err(FromRawError::WrongPointerType) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn device_from_nullptr() {
    let device_result = Device::from_raw(nil);
    match device_result {
        Result::Err(FromRawError::NilPointer) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn compile_opts_creation_is_correct() {
    let fast_math_enabled = true;
    let options = CompileOptions::default()
                      .fast_math_enabled(fast_math_enabled)
                      .language_version(LanguageVersion::Specific(SpecificLanguageVersion::Version_1_0))
                      .with_macro("Foo", 54)
                      .with_macro("Bar", 32.0)
                      .with_macro("Baz", "Hi")
                      .mtl_compile_options();

    unsafe {
        assert_eq!(fast_math_enabled as BOOL, options.fastMathEnabled());
        assert_eq!(options.languageVersion(),
                   MTLLanguageVersion::MTLLanguageVersion1_0);
    }
}

#[test]
fn create_invalid_shader() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"abcdefghijklmnopqrstuvwxyz";
    match device.new_library_with_source(&BAD_SHADER, &Default::default()) {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(error) => {
            if let LibraryErrorType::SourceError = error.error_type {
                assert!(true);
            } else {
                panic!("Incorrect error type");
            }
        }
    }
}

#[test]
fn device_create_library_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    // Shader source taken from http://metalbyexample.com/up-and-running-2/
    const SHADER: &'static str = r"
        using namespace metal;

        struct ColoredVertex
        {
            float4 position [[position]];
            float4 color;
        };

        vertex ColoredVertex vertex_main(constant float4 *position [[buffer(0)]],
                                         constant float4 *color [[buffer(1)]],
                                         uint vid [[vertex_id]])
        {
            ColoredVertex vert;
            vert.position = position[vid];
            vert.color = color[vid];
            return vert;
        }

        fragment float4 fragment_main(ColoredVertex vert [[stage_in]])
        {
            return vert.color;
        }
    ";
    let library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}
<commit_msg>Alphebetise use statements<commit_after>extern crate mtl;
extern crate cocoa;

use cocoa::base::{BOOL, nil};
use cocoa::foundation::NSString;
use mtl::{CompileOptions, Device, LanguageVersion, SpecificLanguageVersion};
use mtl::LibraryErrorType;
use mtl::{FromRaw, FromRawError, IntoRaw};
use mtl::sys::{MTLCompileOptions, MTLLanguageVersion};

#[test]
fn get_device() {
    let device = Device::system_default_device();
    assert!(device.is_ok());
}

#[test]
fn get_all_devices() {
    let all_devices = Device::enumerate_all_system_devices();
    assert!(!all_devices.is_empty());
    for device in all_devices {
        assert!(device.is_ok());
    }
}

#[test]
fn get_device_name() {
    let device = Device::system_default_device().unwrap();
    assert!(!device.name().into_owned().is_empty());
}

#[test]
fn set_get_command_queue_label() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();

    const DUMMY_COMMAND_QUEUE_NAME: &'static str = "foo";
    command_queue.set_label(&DUMMY_COMMAND_QUEUE_NAME);

    assert_eq!(command_queue.label(),
               DUMMY_COMMAND_QUEUE_NAME);
}

#[test]
fn insert_debug_capture_boundary_on_command_queue() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();
    command_queue.insert_debug_capture_boundary();

    // if nothing panics/fails here, everything is okay
}

#[test]
fn device_from_to_raw() {
    let device = Device::system_default_device().unwrap();
    let raw = device.into_raw();
    let device = Device::from_raw(raw);
    assert!(device.is_ok());
}

#[test]
fn device_from_wrong_type() {
    let some_string = unsafe { NSString::alloc(nil).init_str("Hello") };
    let device_result = Device::from_raw(some_string);
    match device_result {
        Result::Err(FromRawError::WrongPointerType) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn device_from_nullptr() {
    let device_result = Device::from_raw(nil);
    match device_result {
        Result::Err(FromRawError::NilPointer) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn compile_opts_creation_is_correct() {
    let fast_math_enabled = true;
    let options = CompileOptions::default()
                      .fast_math_enabled(fast_math_enabled)
                      .language_version(LanguageVersion::Specific(SpecificLanguageVersion::Version_1_0))
                      .with_macro("Foo", 54)
                      .with_macro("Bar", 32.0)
                      .with_macro("Baz", "Hi")
                      .mtl_compile_options();

    unsafe {
        assert_eq!(fast_math_enabled as BOOL, options.fastMathEnabled());
        assert_eq!(options.languageVersion(),
                   MTLLanguageVersion::MTLLanguageVersion1_0);
    }
}

#[test]
fn create_invalid_shader() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"abcdefghijklmnopqrstuvwxyz";
    match device.new_library_with_source(&BAD_SHADER, &Default::default()) {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(error) => {
            if let LibraryErrorType::SourceError = error.error_type {
                assert!(true);
            } else {
                panic!("Incorrect error type");
            }
        }
    }
}

#[test]
fn device_create_library_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    // Shader source taken from http://metalbyexample.com/up-and-running-2/
    const SHADER: &'static str = r"
        using namespace metal;

        struct ColoredVertex
        {
            float4 position [[position]];
            float4 color;
        };

        vertex ColoredVertex vertex_main(constant float4 *position [[buffer(0)]],
                                         constant float4 *color [[buffer(1)]],
                                         uint vid [[vertex_id]])
        {
            ColoredVertex vert;
            vert.position = position[vid];
            vert.color = color[vid];
            return vert;
        }

        fragment float4 fragment_main(ColoredVertex vert [[stage_in]])
        {
            return vert.color;
        }
    ";
    let library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}
<|endoftext|>


<commit_before>use std::collections::{BinaryHeap, HashMap};
use std::str::FromStr;
use temperature::circuit::ThreeDICE;
use temperature::{self, Simulator};
use threed_ice::{StackElement, System};

use config::Config;
use profile::Profile;
use {Error, ID, Job, Result};

pub struct Platform {
    pub units: usize,
    pub elements: HashMap<ElementKind, BinaryHeap<Element>>,
    pub simulator: Simulator,
    pub power: Profile,
    pub temperature: Profile,
}

time! {
    #[derive(Clone, Copy, Debug)]
    pub struct Element {
        pub id: ID,
        pub kind: ElementKind,
    }
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum ElementKind {
    Core,
    L3,
}

impl Platform {
    pub fn new(config: &Config) -> Result<Platform> {
        let path = path!(config, "a stack description");

        info!(target: "platform", "Reading {:?}...", &path);
        let system = ok!(System::new(&path));

        let mut units = 0;
        let mut elements = HashMap::new();
        for element in system.stack.elements.iter().rev() {
            let die = match element {
                &StackElement::Die(ref die) => die,
                _ => continue,
            };
            for element in die.floorplan.elements.iter() {
                let kind = try!(ElementKind::from_str(&element.id));
                let id = ID::new("element");
                let heap = elements.entry(kind).or_insert_with(|| BinaryHeap::new());
                heap.push(time!(0.0, Element { id: id, kind: kind }));
                units += 1;
            }
        }

        let config = {
            let config = some!(config.branch("temperature"),
                               "a temperature configuration is required");
            try!(new_temperature_config(&config))
        };

        info!(target: "platform", "Constructing a thermal circuit...");
        let simulator = ok!(Simulator::new(&ok!(ThreeDICE::from(&system)), &config));

        Ok(Platform {
            units: units,
            elements: elements,
            simulator: simulator,
            power: Profile::new(units, config.time_step),
            temperature: Profile::new(units, config.time_step),
        })
    }

    pub fn next(&mut self, job: &Job) -> Option<(f64, f64)> {
        use std::f64::EPSILON;

        let pattern = &job.pattern;

        let units = pattern.units;
        if self.units < units {
            error!(target: "platform", "There are no enough processing elements for {}.", job);
            return None;
        }

        let mut available = 0f64;
        let mut hosts = vec![];
        for element in &pattern.elements {
            match self.elements.get_mut(&element.kind).and_then(|heap| heap.pop()) {
                Some(host) => {
                    if host.is_exclusive() {
                        available = available.max(host.time);
                    }
                    hosts.push(host);
                },
                _ => break,
            }
        }

        macro_rules! push_back(
            () => (for host in hosts.drain(..) {
                self.elements.get_mut(&host.kind).unwrap().push(host);
            })
        );

        if hosts.len() != units {
            error!(target: "platform", "Failed to allocate resources for {}.", job);
            push_back!();
            return None;
        }

        let start = job.arrival.max(available) + EPSILON;
        let finish = start + pattern.duration();

        for i in 0..units {
            let element = &pattern.elements[i];
            let mut data = element.dynamic_power.clone();
            for value in &mut data {
                *value += element.leakage_power;
            }
            self.power.accumulate(hosts[i].number(), start, pattern.time_step, &data);
        }

        for host in &mut hosts {
            host.time = finish;
        }
        push_back!();

        Some((start, finish))
    }
}

impl Element {
    #[inline(always)]
    pub fn number(&self) -> usize {
        self.id.number()
    }

    #[inline(always)]
    pub fn is_exclusive(&self) -> bool {
        self.kind == ElementKind::Core
    }
}

impl FromStr for ElementKind {
    type Err = Error;

    fn from_str(id: &str) -> Result<Self> {
        let lower = id.to_lowercase();
        if lower.starts_with("core") {
            return Ok(ElementKind::Core);
        } else if lower.starts_with("l3") {
            return Ok(ElementKind::L3);
        }
        raise!("found an unknown id {:?}", id);
    }
}

fn new_temperature_config(config: &Config) -> Result<temperature::Config> {
    Ok(temperature::Config {
        ambience: *some!(config.get::<f64>("ambience"), "an ambient temperature is required"),
        time_step: *some!(config.get::<f64>("time_step"), "a time step is required"),
    })
}

#[cfg(test)]
mod tests {
    use config::Config;
    use super::{ElementKind, Platform};

    #[test]
    fn new() {
        let config = Config::new("tests/fixtures/streamer.toml").unwrap()
                            .branch("platform").unwrap();
        let platform = Platform::new(&config).unwrap();
        assert_eq!(platform.elements[&ElementKind::Core].len(), 4);
        assert_eq!(platform.elements[&ElementKind::L3].len(), 1);
    }
}
<commit_msg>A cosmetic change<commit_after>use std::collections::{BinaryHeap, HashMap};
use std::str::FromStr;
use temperature::circuit::ThreeDICE;
use temperature::{self, Simulator};
use threed_ice::{StackElement, System};

use config::Config;
use profile::Profile;
use {Error, ID, Job, Result};

pub struct Platform {
    pub units: usize,
    pub elements: HashMap<ElementKind, BinaryHeap<Element>>,
    pub simulator: Simulator,
    pub power: Profile,
    pub temperature: Profile,
}

time! {
    #[derive(Clone, Copy, Debug)]
    pub struct Element {
        pub id: ID,
        pub kind: ElementKind,
    }
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum ElementKind {
    Core,
    L3,
}

impl Platform {
    pub fn new(config: &Config) -> Result<Platform> {
        let path = path!(config, "a stack description");

        info!(target: "platform", "Reading {:?}...", &path);
        let system = ok!(System::new(&path));

        let mut units = 0;
        let mut elements = HashMap::new();
        for element in system.stack.elements.iter().rev() {
            let die = match element {
                &StackElement::Die(ref die) => die,
                _ => continue,
            };
            for element in die.floorplan.elements.iter() {
                let kind = try!(ElementKind::from_str(&element.id));
                let id = ID::new("element");
                let heap = elements.entry(kind).or_insert_with(|| BinaryHeap::new());
                heap.push(time!(0.0, Element { id: id, kind: kind }));
                units += 1;
            }
        }

        let config = {
            let config = some!(config.branch("temperature"),
                               "a temperature configuration is required");
            try!(new_temperature_config(&config))
        };

        info!(target: "platform", "Constructing a thermal circuit...");
        let simulator = ok!(Simulator::new(&ok!(ThreeDICE::from(&system)), &config));

        Ok(Platform {
            units: units,
            elements: elements,
            simulator: simulator,
            power: Profile::new(units, config.time_step),
            temperature: Profile::new(units, config.time_step),
        })
    }

    pub fn next(&mut self, job: &Job) -> Option<(f64, f64)> {
        use std::f64::EPSILON;

        let pattern = &job.pattern;

        let units = pattern.units;
        if self.units < units {
            error!(target: "platform", "There are no enough processing elements for {}.", job);
            return None;
        }

        let mut available = 0f64;
        let mut hosts = vec![];
        for element in &pattern.elements {
            match self.elements.get_mut(&element.kind).and_then(|heap| heap.pop()) {
                Some(host) => {
                    if host.is_exclusive() {
                        available = available.max(host.time);
                    }
                    hosts.push(host);
                },
                _ => break,
            }
        }

        macro_rules! push_back(
            () => (for host in hosts.drain(..) {
                self.elements.get_mut(&host.kind).unwrap().push(host);
            });
        );

        if hosts.len() != units {
            error!(target: "platform", "Failed to allocate resources for {}.", job);
            push_back!();
            return None;
        }

        let start = job.arrival.max(available) + EPSILON;
        let finish = start + pattern.duration();

        for i in 0..units {
            let element = &pattern.elements[i];
            let mut power = element.dynamic_power.clone();
            for power in &mut power {
                *power += element.leakage_power;
            }
            self.power.accumulate(hosts[i].number(), start, pattern.time_step, &power);
        }

        for host in &mut hosts {
            host.time = finish;
        }
        push_back!();

        Some((start, finish))
    }
}

impl Element {
    #[inline(always)]
    pub fn number(&self) -> usize {
        self.id.number()
    }

    #[inline(always)]
    pub fn is_exclusive(&self) -> bool {
        self.kind == ElementKind::Core
    }
}

impl FromStr for ElementKind {
    type Err = Error;

    fn from_str(id: &str) -> Result<Self> {
        let lower = id.to_lowercase();
        if lower.starts_with("core") {
            return Ok(ElementKind::Core);
        } else if lower.starts_with("l3") {
            return Ok(ElementKind::L3);
        }
        raise!("found an unknown id {:?}", id);
    }
}

fn new_temperature_config(config: &Config) -> Result<temperature::Config> {
    Ok(temperature::Config {
        ambience: *some!(config.get::<f64>("ambience"), "an ambient temperature is required"),
        time_step: *some!(config.get::<f64>("time_step"), "a time step is required"),
    })
}

#[cfg(test)]
mod tests {
    use config::Config;
    use super::{ElementKind, Platform};

    #[test]
    fn new() {
        let config = Config::new("tests/fixtures/streamer.toml").unwrap()
                            .branch("platform").unwrap();
        let platform = Platform::new(&config).unwrap();
        assert_eq!(platform.elements[&ElementKind::Core].len(), 4);
        assert_eq!(platform.elements[&ElementKind::L3].len(), 1);
    }
}
<|endoftext|>