Add initial (failing) REST api tests

This commit is contained in:
Paul Hauner
2019-11-12 18:11:05 +11:00
parent 41805611d0
commit 7b5a868f4a
8 changed files with 304 additions and 38 deletions

View File

@@ -55,7 +55,7 @@
use prometheus::{HistogramOpts, HistogramTimer, Opts};
pub use prometheus::{Histogram, IntCounter, IntGauge, Result};
pub use prometheus::{Encoder, Histogram, IntCounter, IntGauge, Result, TextEncoder};
/// Collect all the metrics for reporting.
pub fn gather() -> Vec<prometheus::proto::MetricFamily> {

View File

@@ -12,3 +12,6 @@ url = "1.2"
serde = "1.0"
futures = "0.1.25"
types = { path = "../../../eth2/types" }
rest_api = { path = "../../../beacon_node/rest_api" }
hex = "0.3"
eth2_ssz = { path = "../../../eth2/utils/ssz" }

View File

@@ -6,9 +6,10 @@
use futures::{Future, IntoFuture};
use reqwest::r#async::{Client, RequestBuilder};
use serde::Deserialize;
use ssz::Encode;
use std::marker::PhantomData;
use std::net::SocketAddr;
use types::{BeaconBlock, BeaconState, EthSpec};
use types::{BeaconBlock, BeaconState, EthSpec, Signature};
use types::{Hash256, Slot};
use url::Url;
@@ -53,16 +54,55 @@ impl<E: EthSpec> HttpClient<E> {
Beacon(self.clone())
}
pub fn validator(&self) -> Validator<E> {
Validator(self.clone())
}
fn url(&self, path: &str) -> Result<Url, Error> {
self.url.join(path).map_err(|e| e.into())
}
pub fn get(&self, path: &str) -> Result<RequestBuilder, Error> {
// TODO: add timeout
self.url(path)
.map(|url| Client::new().get(&url.to_string()))
}
}
/// Provides the functions on the `/beacon` endpoint of the node.
#[derive(Clone)]
pub struct Validator<E>(HttpClient<E>);
impl<E: EthSpec> Validator<E> {
fn url(&self, path: &str) -> Result<Url, Error> {
self.0
.url("validator/")
.and_then(move |url| url.join(path).map_err(Error::from))
.map_err(Into::into)
}
/// Requests a new (unsigned) block from the beacon node.
pub fn block(
&self,
slot: Slot,
randao_reveal: Signature,
) -> impl Future<Item = BeaconBlock<E>, Error = Error> {
let client = self.0.clone();
self.url("block")
.into_future()
.and_then(move |mut url| {
url.query_pairs_mut()
.append_pair("slot", &format!("{}", slot.as_u64()));
url.query_pairs_mut()
.append_pair("randao_reveal", &signature_as_string(&randao_reveal));
client.get(&url.to_string())
})
.and_then(|builder| builder.send().map_err(Error::from))
.and_then(|response| response.error_for_status().map_err(Error::from))
.and_then(|mut success| success.json::<BeaconBlock<E>>().map_err(Error::from))
}
}
/// Provides the functions on the `/beacon` endpoint of the node.
#[derive(Clone)]
pub struct Beacon<E>(HttpClient<E>);
@@ -76,16 +116,32 @@ impl<E: EthSpec> Beacon<E> {
}
/// Returns the block and block root at the given slot.
pub fn block_at_slot(
pub fn block_by_slot(
&self,
slot: Slot,
) -> impl Future<Item = (BeaconBlock<E>, Hash256), Error = Error> {
self.block("slot", format!("{}", slot.as_u64()))
}
/// Returns the block and block root at the given root.
pub fn block_by_root(
&self,
root: Hash256,
) -> impl Future<Item = (BeaconBlock<E>, Hash256), Error = Error> {
self.block("root", root_as_string(root))
}
/// Returns the block and block root at the given slot.
fn block(
&self,
query_key: &'static str,
query_param: String,
) -> impl Future<Item = (BeaconBlock<E>, Hash256), Error = Error> {
let client = self.0.clone();
self.url("block")
.into_future()
.and_then(move |mut url| {
url.query_pairs_mut()
.append_pair("slot", &format!("{}", slot.as_u64()));
url.query_pairs_mut().append_pair(query_key, &query_param);
client.get(&url.to_string())
})
.and_then(|builder| builder.send().map_err(Error::from))
@@ -95,16 +151,32 @@ impl<E: EthSpec> Beacon<E> {
}
/// Returns the state and state root at the given slot.
pub fn state_at_slot(
pub fn state_by_slot(
&self,
slot: Slot,
) -> impl Future<Item = (BeaconState<E>, Hash256), Error = Error> {
self.state("slot", format!("{}", slot.as_u64()))
}
/// Returns the state and state root at the given root.
pub fn state_by_root(
&self,
root: Hash256,
) -> impl Future<Item = (BeaconState<E>, Hash256), Error = Error> {
self.state("root", root_as_string(root))
}
/// Returns the state and state root at the given slot.
fn state(
&self,
query_key: &'static str,
query_param: String,
) -> impl Future<Item = (BeaconState<E>, Hash256), Error = Error> {
let client = self.0.clone();
self.url("state")
.into_future()
.and_then(move |mut url| {
url.query_pairs_mut()
.append_pair("slot", &format!("{}", slot.as_u64()));
url.query_pairs_mut().append_pair(query_key, &query_param);
client.get(&url.to_string())
})
.and_then(|builder| builder.send().map_err(Error::from))
@@ -128,6 +200,14 @@ pub struct StateResponse<T: EthSpec> {
pub root: Hash256,
}
fn root_as_string(root: Hash256) -> String {
format!("0x{:?}", root)
}
fn signature_as_string(signature: &Signature) -> String {
format!("0x{}", hex::encode(signature.as_ssz_bytes()))
}
impl From<reqwest::Error> for Error {
fn from(e: reqwest::Error) -> Error {
Error::ReqwestError(e)