diff --git a/p2p/tests/common/mod.rs b/p2p/tests/common/mod.rs new file mode 100644 index 000000000..77105aef0 --- /dev/null +++ b/p2p/tests/common/mod.rs @@ -0,0 +1,58 @@ +// Copyright 2016 The Grin Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use mioco; +use mioco::tcp::TcpStream; +use std::io; +use std::sync::Arc; +use std::time; +use p2p; +use p2p::Peer; + +/// Server setup and teardown around the provided closure. +pub fn with_server(closure: F) where F: Fn(Arc) -> io::Result<()>, F: Send + 'static { + mioco::start(move || -> io::Result<()> { + // start a server in its own coroutine + let server = Arc::new(p2p::Server::new()); + let in_server = server.clone(); + mioco::spawn(move || -> io::Result<()> { + try!(in_server.start().map_err(|_| io::Error::last_os_error())); + Ok(()) + }); + + // giving server a little time to start + mioco::sleep(time::Duration::from_millis(50)); + + try!(closure(server.clone())); + + server.stop(); + Ok(()) + }).unwrap().unwrap(); +} + +pub fn connect_peer() -> io::Result> { + let addr = p2p::DEFAULT_LISTEN_ADDR.parse().unwrap(); + let tcp_client = TcpStream::connect(&addr).unwrap(); + let peer = try!(Peer::accept(tcp_client, &p2p::handshake::Handshake::new()).map_err(|_| io::Error::last_os_error())); + mioco::sleep(time::Duration::from_millis(50)); + + let peer = Arc::new(peer); + let in_peer = peer.clone(); + mioco::spawn(move || -> io::Result<()> { + in_peer.run(&p2p::DummyAdapter{}); + Ok(()) + }); + mioco::sleep(time::Duration::from_millis(50)); + Ok(peer.clone()) +} diff --git a/p2p/tests/network_conn.rs b/p2p/tests/peer_handshake.rs similarity index 100% rename from p2p/tests/network_conn.rs rename to p2p/tests/peer_handshake.rs diff --git a/p2p/tests/peer_tx_send.rs b/p2p/tests/peer_tx_send.rs new file mode 100644 index 000000000..07b86da20 --- /dev/null +++ b/p2p/tests/peer_tx_send.rs @@ -0,0 +1,82 @@ +// Copyright 2016 The Grin Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +extern crate grin_core as core; +extern crate grin_p2p as p2p; +extern crate mioco; +extern crate env_logger; +extern crate rand; +extern crate secp256k1zkp as secp; + +mod common; + +use rand::Rng; +use rand::os::OsRng; +use std::io; +use std::sync::Arc; +use std::time; + +use mioco::tcp::TcpStream; +use secp::Secp256k1; +use secp::key::SecretKey; + +use core::core::*; +use p2p::Peer; +use common::*; + +// Connects a client peer and send a transaction. +#[test] +fn peer_tx_send() { + with_server(|server| -> io::Result<()> { + // connect a client peer to the server + let peer = try!(connect_peer()); + let tx1 = tx2i1o(); + + peer.send_transaction(&tx1); + mioco::sleep(time::Duration::from_millis(50)); + let (sent,_) = peer.transmitted_bytes(); + assert!(sent > 1000); + + let s_peer = server.get_any_peer(); + let (_, recv) = s_peer.transmitted_bytes(); + assert!(recv > 1000); + + peer.stop(); + + Ok(()) + }); +} + +// utility producing a transaction with 2 inputs and a single outputs +pub fn tx2i1o() -> Transaction { + let mut rng = OsRng::new().unwrap(); + let ref secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit); + + let outh = core::core::hash::ZERO_HASH; + Transaction::new(vec![Input::OvertInput { + output: outh, + value: 10, + blindkey: SecretKey::new(secp, &mut rng), + }, + Input::OvertInput { + output: outh, + value: 11, + blindkey: SecretKey::new(secp, &mut rng), + }], + vec![Output::OvertOutput { + value: 20, + blindkey: SecretKey::new(secp, &mut rng), + }], + 1).blind(&secp).unwrap() +}