diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 44954f99d..cab703471 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -90,6 +90,8 @@ pub struct TestBlockChainClient { pub ancient_block: RwLock>, /// First block info. pub first_block: RwLock>, + /// Traces to return + pub traces: RwLock>>, } /// Used for generating test client blocks. @@ -151,6 +153,7 @@ impl TestBlockChainClient { latest_block_timestamp: RwLock::new(10_000_000), ancient_block: RwLock::new(None), first_block: RwLock::new(None), + traces: RwLock::new(None), }; client.add_blocks(1, EachBlockWith::Nothing); // add genesis block client.genesis_hash = client.last_hash.read().clone(); @@ -642,19 +645,19 @@ impl BlockChainClient for TestBlockChainClient { } fn filter_traces(&self, _filter: TraceFilter) -> Option> { - unimplemented!(); + self.traces.read().clone() } fn trace(&self, _trace: TraceId) -> Option { - unimplemented!(); + self.traces.read().clone().and_then(|vec| vec.into_iter().next()) } fn transaction_traces(&self, _trace: TransactionId) -> Option> { - unimplemented!(); + self.traces.read().clone() } fn block_traces(&self, _trace: BlockId) -> Option> { - unimplemented!(); + self.traces.read().clone() } fn queue_transactions(&self, transactions: Vec, _peer_id: usize) { diff --git a/ethcore/src/types/trace_types/localized.rs b/ethcore/src/types/trace_types/localized.rs index 57abea362..f65c47415 100644 --- a/ethcore/src/types/trace_types/localized.rs +++ b/ethcore/src/types/trace_types/localized.rs @@ -21,7 +21,7 @@ use super::trace::{Action, Res}; use header::BlockNumber; /// Localized trace. -#[derive(Debug, PartialEq, Binary)] +#[derive(Debug, PartialEq, Clone, Binary)] pub struct LocalizedTrace { /// Type of action performed by a transaction. pub action: Action, diff --git a/rpc/src/v1/tests/mocked/mod.rs b/rpc/src/v1/tests/mocked/mod.rs index 0ba0fc95c..0dbaa38f6 100644 --- a/rpc/src/v1/tests/mocked/mod.rs +++ b/rpc/src/v1/tests/mocked/mod.rs @@ -18,13 +18,14 @@ //! method calls properly. mod eth; +mod manage_network; mod net; -mod web3; -mod personal; mod parity; mod parity_accounts; mod parity_set; +mod personal; mod rpc; mod signer; mod signing; -mod manage_network; +mod traces; +mod web3; diff --git a/rpc/src/v1/tests/mocked/traces.rs b/rpc/src/v1/tests/mocked/traces.rs new file mode 100644 index 000000000..f9a9baa00 --- /dev/null +++ b/rpc/src/v1/tests/mocked/traces.rs @@ -0,0 +1,145 @@ +// Copyright 2015, 2016 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use std::sync::Arc; + +use ethcore::executed::{CallType, Executed}; +use ethcore::trace::trace::{Action, Res, Call}; +use ethcore::trace::LocalizedTrace; +use ethcore::client::{TestBlockChainClient}; + +use jsonrpc_core::{IoHandler, GenericIoHandler}; +use v1::tests::helpers::{TestMinerService}; +use v1::{Traces, TracesClient}; + +struct Tester { + _client: Arc, + _miner: Arc, + io: IoHandler, +} + +fn io() -> Tester { + let client = Arc::new(TestBlockChainClient::new()); + *client.traces.write() = Some(vec![LocalizedTrace { + action: Action::Call(Call { + from: 0xf.into(), + to: 0x10.into(), + value: 0x1.into(), + gas: 0x100.into(), + input: vec![1, 2, 3], + call_type: CallType::Call, + }), + result: Res::None, + subtraces: 0, + trace_address: vec![0], + transaction_number: 0, + transaction_hash: 5.into(), + block_number: 10, + block_hash: 10.into(), + }]); + *client.execution_result.write() = Some(Ok(Executed { + gas: 20_000.into(), + gas_used: 10_000.into(), + refunded: 0.into(), + cumulative_gas_used: 10_000.into(), + logs: vec![], + contracts_created: vec![], + output: vec![1, 2, 3], + trace: vec![], + vm_trace: None, + state_diff: None, + })); + let miner = Arc::new(TestMinerService::default()); + let traces = TracesClient::new(&client, &miner); + let io = IoHandler::new(); + io.add_delegate(traces.to_delegate()); + + Tester { + _client: client, + _miner: miner, + io: io, + } +} + +#[test] +fn rpc_trace_filter() { + let tester = io(); + + let request = r#"{"jsonrpc":"2.0","method":"trace_filter","params": [{}],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":[{"action":{"callType":"call","from":"0x000000000000000000000000000000000000000f","gas":"0x100","input":"0x010203","to":"0x0000000000000000000000000000000000000010","value":"0x1"},"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000a","blockNumber":10,"result":null,"subtraces":0,"traceAddress":[0],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000005","transactionPosition":0,"type":"call"}],"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + +#[test] +fn rpc_trace_block() { + let tester = io(); + + let request = r#"{"jsonrpc":"2.0","method":"trace_block","params": ["0x10"],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":[{"action":{"callType":"call","from":"0x000000000000000000000000000000000000000f","gas":"0x100","input":"0x010203","to":"0x0000000000000000000000000000000000000010","value":"0x1"},"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000a","blockNumber":10,"result":null,"subtraces":0,"traceAddress":[0],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000005","transactionPosition":0,"type":"call"}],"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + +#[test] +fn rpc_trace_transaction() { + let tester = io(); + + let request = r#"{"jsonrpc":"2.0","method":"trace_transaction","params":["0x0000000000000000000000000000000000000000000000000000000000000005"],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":[{"action":{"callType":"call","from":"0x000000000000000000000000000000000000000f","gas":"0x100","input":"0x010203","to":"0x0000000000000000000000000000000000000010","value":"0x1"},"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000a","blockNumber":10,"result":null,"subtraces":0,"traceAddress":[0],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000005","transactionPosition":0,"type":"call"}],"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + +#[test] +fn rpc_trace_get() { + let tester = io(); + + let request = r#"{"jsonrpc":"2.0","method":"trace_get","params":["0x0000000000000000000000000000000000000000000000000000000000000005", ["0","0","0"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"action":{"callType":"call","from":"0x000000000000000000000000000000000000000f","gas":"0x100","input":"0x010203","to":"0x0000000000000000000000000000000000000010","value":"0x1"},"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000a","blockNumber":10,"result":null,"subtraces":0,"traceAddress":[0],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000005","transactionPosition":0,"type":"call"},"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + +#[test] +fn rpc_trace_call() { + let tester = io(); + + let request = r#"{"jsonrpc":"2.0","method":"trace_call","params":[{}, ["stateDiff", "vmTrace", "trace"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"output":"0x010203","stateDiff":null,"trace":[],"vmTrace":null},"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + +#[test] +fn rpc_trace_raw_transaction() { + let tester = io(); + + let request = r#"{"jsonrpc":"2.0","method":"trace_rawTransaction","params":["0xf869018609184e72a0008276c094d46e8dd67c5d32be8058bb8eb970870f07244567849184e72a801ba0617f39c1a107b63302449c476d96a6cb17a5842fc98ff0c5bcf4d5c4d8166b95a009fdb6097c6196b9bbafc3a59f02f38d91baeef23d0c60a8e4f23c7714cea3a9", ["stateDiff", "vmTrace", "trace"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"output":"0x010203","stateDiff":null,"trace":[],"vmTrace":null},"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + +#[test] +fn rpc_trace_replay_transaction() { + let tester = io(); + + let request = r#"{"jsonrpc":"2.0","method":"trace_replayTransaction","params":["0x0000000000000000000000000000000000000000000000000000000000000005", ["trace", "stateDiff", "vmTrace"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"output":"0x010203","stateDiff":null,"trace":[],"vmTrace":null},"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +}