mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-22 11:39:26 +00:00
test-utils: add crate::rpc::data
module (#231)
Some checks failed
Audit / audit (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / typo (push) Has been cancelled
CI / ci (macos-latest, stable, bash) (push) Has been cancelled
CI / ci (ubuntu-latest, stable, bash) (push) Has been cancelled
CI / ci (windows-latest, stable-x86_64-pc-windows-gnu, msys2 {0}) (push) Has been cancelled
Deny / audit (push) Has been cancelled
Doc / build (push) Has been cancelled
Doc / deploy (push) Has been cancelled
Some checks failed
Audit / audit (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / typo (push) Has been cancelled
CI / ci (macos-latest, stable, bash) (push) Has been cancelled
CI / ci (ubuntu-latest, stable, bash) (push) Has been cancelled
CI / ci (windows-latest, stable-x86_64-pc-windows-gnu, msys2 {0}) (push) Has been cancelled
Deny / audit (push) Has been cancelled
Doc / build (push) Has been cancelled
Doc / deploy (push) Has been cancelled
* test-utils: add `crate::rpc::types` module * test-utils: conditional json doc-tests * json: add test data, fix macro doc tests * json: add all data * other: add all data * bin: add skeleton * docs * move type to correct file * rpc: `client/{client,constants}.rs` -> `client.rs` * lib.rs: remove `clippy::module_inception`
This commit is contained in:
parent
0a88ea13fc
commit
aa718e224f
13 changed files with 2400 additions and 49 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -785,6 +785,7 @@ dependencies = [
|
|||
"hex",
|
||||
"hex-literal",
|
||||
"monero-serai",
|
||||
"paste",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
[package]
|
||||
name = "cuprate-test-utils"
|
||||
name = "cuprate-test-utils"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Boog900", "hinto-janai"]
|
||||
|
||||
[dependencies]
|
||||
cuprate-types = { path = "../types" }
|
||||
cuprate-helper = { path = "../helper", features = ["map"] }
|
||||
cuprate-wire = { path = "../net/wire" }
|
||||
cuprate-types = { path = "../types" }
|
||||
cuprate-helper = { path = "../helper", features = ["map"] }
|
||||
cuprate-wire = { path = "../net/wire" }
|
||||
cuprate-p2p-core = { path = "../p2p/p2p-core", features = ["borsh"] }
|
||||
|
||||
hex = { workspace = true }
|
||||
hex-literal = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
hex-literal = { workspace = true }
|
||||
monero-serai = { workspace = true, features = ["std", "http-rpc"] }
|
||||
futures = { workspace = true, features = ["std"] }
|
||||
async-trait = { workspace = true }
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
tokio-util = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
bytes = { workspace = true, features = ["std"] }
|
||||
tempfile = { workspace = true }
|
||||
|
||||
borsh = { workspace = true, features = ["derive"]}
|
||||
futures = { workspace = true, features = ["std"] }
|
||||
async-trait = { workspace = true }
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
tokio-util = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
bytes = { workspace = true, features = ["std"] }
|
||||
tempfile = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
borsh = { workspace = true, features = ["derive"]}
|
||||
|
||||
[dev-dependencies]
|
||||
hex = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
pretty_assertions = { workspace = true }
|
|
@ -7,3 +7,4 @@ It currently contains:
|
|||
- Code to spawn monerod instances and a testing network zone
|
||||
- Real raw and typed Monero data, e.g. `Block, Transaction`
|
||||
- An RPC client to generate types from `cuprate_types`
|
||||
- Raw RPC request/response strings and binary data
|
|
@ -292,7 +292,7 @@ mod tests {
|
|||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use crate::rpc::HttpRpcClient;
|
||||
use crate::rpc::client::HttpRpcClient;
|
||||
|
||||
/// Assert the defined blocks are the same compared to ones received from a local RPC call.
|
||||
#[ignore] // FIXME: doesn't work in CI, we need a real unrestricted node
|
||||
|
|
|
@ -12,7 +12,9 @@ use monero_serai::{
|
|||
|
||||
use cuprate_types::{VerifiedBlockInformation, VerifiedTransactionInformation};
|
||||
|
||||
use crate::rpc::constants::LOCALHOST_RPC_URL;
|
||||
//---------------------------------------------------------------------------------------------------- Constants
|
||||
/// The default URL used for Monero RPC connections.
|
||||
pub const LOCALHOST_RPC_URL: &str = "http://127.0.0.1:18081";
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- HttpRpcClient
|
||||
/// An HTTP RPC client for Monero.
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
//! RPC-related Constants.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Use
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Constants
|
||||
/// The default URL used for Monero RPC connections.
|
||||
pub const LOCALHOST_RPC_URL: &str = "http://127.0.0.1:18081";
|
55
test-utils/src/rpc/data/bin.rs
Normal file
55
test-utils/src/rpc/data/bin.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
//! Binary data from [`.bin` endpoints](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_blocksbin).
|
||||
//!
|
||||
//! TODO: Not implemented yet.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
use crate::rpc::data::macros::define_request_and_response;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
define_request_and_response! {
|
||||
get_blocksbin,
|
||||
GET_BLOCKS: &[u8],
|
||||
Request = &[];
|
||||
Response = &[];
|
||||
}
|
||||
|
||||
define_request_and_response! {
|
||||
get_blocks_by_heightbin,
|
||||
GET_BLOCKS_BY_HEIGHT: &[u8],
|
||||
Request = &[];
|
||||
Response = &[];
|
||||
}
|
||||
|
||||
define_request_and_response! {
|
||||
get_hashesbin,
|
||||
GET_HASHES: &[u8],
|
||||
Request = &[];
|
||||
Response = &[];
|
||||
}
|
||||
|
||||
define_request_and_response! {
|
||||
get_o_indexesbin,
|
||||
GET_O_INDEXES: &[u8],
|
||||
Request = &[];
|
||||
Response = &[];
|
||||
}
|
||||
|
||||
define_request_and_response! {
|
||||
get_outsbin,
|
||||
GET_OUTS: &[u8],
|
||||
Request = &[];
|
||||
Response = &[];
|
||||
}
|
||||
|
||||
define_request_and_response! {
|
||||
get_transaction_pool_hashesbin,
|
||||
GET_TRANSACTION_POOL_HASHES: &[u8],
|
||||
Request = &[];
|
||||
Response = &[];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
// use super::*;
|
||||
}
|
1292
test-utils/src/rpc/data/json.rs
Normal file
1292
test-utils/src/rpc/data/json.rs
Normal file
File diff suppressed because it is too large
Load diff
168
test-utils/src/rpc/data/macros.rs
Normal file
168
test-utils/src/rpc/data/macros.rs
Normal file
|
@ -0,0 +1,168 @@
|
|||
//! Macros.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_request_and_response
|
||||
/// A template for generating the RPC request and response `const` data.
|
||||
///
|
||||
/// See the [`crate::json`] module for example usage.
|
||||
///
|
||||
/// # Macro internals
|
||||
/// This macro uses:
|
||||
/// - [`define_request_and_response_doc`]
|
||||
/// - [`define_request_and_response_test`]
|
||||
macro_rules! define_request_and_response {
|
||||
(
|
||||
// The markdown tag for Monero daemon RPC documentation. Not necessarily the endpoint.
|
||||
//
|
||||
// Adding `(json)` after this will trigger the macro to automatically
|
||||
// add a `serde_json` test for the request/response data.
|
||||
$monero_daemon_rpc_doc_link:ident $(($test:ident))?,
|
||||
|
||||
// The base name.
|
||||
// Attributes added here will apply to _both_
|
||||
// request and response types.
|
||||
$( #[$attr:meta] )*
|
||||
$name:ident: $type:ty,
|
||||
|
||||
// The request type (and any doc comments, derives, etc).
|
||||
$( #[$request_attr:meta] )*
|
||||
Request = $request:expr;
|
||||
|
||||
// The response type (and any doc comments, derives, etc).
|
||||
$( #[$response_attr:meta] )*
|
||||
Response = $response:expr;
|
||||
) => { paste::paste! {
|
||||
#[doc = $crate::rpc::data::macros::define_request_and_response_doc!(
|
||||
"response" => [<$name:upper _RESPONSE>],
|
||||
$monero_daemon_rpc_doc_link,
|
||||
)]
|
||||
///
|
||||
$( #[$attr] )*
|
||||
///
|
||||
$( #[$request_attr] )*
|
||||
///
|
||||
$(
|
||||
#[doc = $crate::rpc::data::macros::define_request_and_response_doc_test!([<$name:upper _REQUEST>], $test)]
|
||||
)?
|
||||
pub const [<$name:upper _REQUEST>]: $type = $request;
|
||||
|
||||
#[doc = $crate::rpc::data::macros::define_request_and_response_doc!(
|
||||
"request" => [<$name:upper _REQUEST>],
|
||||
$monero_daemon_rpc_doc_link,
|
||||
)]
|
||||
///
|
||||
$( #[$attr] )*
|
||||
///
|
||||
$( #[$response_attr] )*
|
||||
///
|
||||
$(
|
||||
#[doc = $crate::rpc::data::macros::define_request_and_response_doc_test!([<$name:upper _RESPONSE>], $test)]
|
||||
)?
|
||||
pub const [<$name:upper _RESPONSE>]: $type = $response;
|
||||
}};
|
||||
}
|
||||
pub(super) use define_request_and_response;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_request_and_response_doc
|
||||
/// Generate documentation for the types generated
|
||||
/// by the [`define_request_and_response`] macro.
|
||||
///
|
||||
/// See it for more info on inputs.
|
||||
macro_rules! define_request_and_response_doc {
|
||||
(
|
||||
// This labels the last `[request]` or `[response]`
|
||||
// hyperlink in documentation. Input is either:
|
||||
// - "request"
|
||||
// - "response"
|
||||
//
|
||||
// Remember this is linking to the _other_ type,
|
||||
// so if defining a `Request` type, input should
|
||||
// be "response".
|
||||
$request_or_response:literal => $request_or_response_type:ident,
|
||||
$monero_daemon_rpc_doc_link:ident,
|
||||
) => {
|
||||
concat!(
|
||||
"",
|
||||
"[Documentation](",
|
||||
"https://www.getmonero.org/resources/developer-guides/daemon-rpc.html",
|
||||
"#",
|
||||
stringify!($monero_daemon_rpc_doc_link),
|
||||
"), [",
|
||||
$request_or_response,
|
||||
"](",
|
||||
stringify!($request_or_response_type),
|
||||
")."
|
||||
)
|
||||
};
|
||||
}
|
||||
pub(super) use define_request_and_response_doc;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- define_request_and_response_test
|
||||
/// Generate documentation for the types generated
|
||||
/// by the [`define_request_and_response`] macro.
|
||||
///
|
||||
/// See it for more info on inputs.
|
||||
macro_rules! define_request_and_response_doc_test {
|
||||
// `/json_rpc` doc test.
|
||||
(
|
||||
// The ident of the `const` request/response.
|
||||
$name:ident,
|
||||
json_rpc
|
||||
) => {
|
||||
concat!(
|
||||
"```rust\n",
|
||||
"use cuprate_test_utils::rpc::data::json::*;\n",
|
||||
"use serde_json::{to_value, Value};\n",
|
||||
"\n",
|
||||
"let value = serde_json::from_str::<Value>(&",
|
||||
stringify!($name),
|
||||
").unwrap();\n",
|
||||
"let Value::Object(map) = value else {\n",
|
||||
" panic!();\n",
|
||||
"};\n",
|
||||
"\n",
|
||||
r#"assert_eq!(map.get("jsonrpc").unwrap(), "2.0");"#,
|
||||
"\n",
|
||||
r#"map.get("id").unwrap();"#,
|
||||
"\n\n",
|
||||
r#"if map.get("method").is_some() {"#,
|
||||
"\n",
|
||||
r#" return;"#,
|
||||
"\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
r#"if map.get("result").is_none() {"#,
|
||||
"\n",
|
||||
r#" map.get("error").unwrap();"#,
|
||||
"\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
)
|
||||
};
|
||||
|
||||
// Other JSON endpoint doc test.
|
||||
(
|
||||
$name:ident,
|
||||
other
|
||||
) => {
|
||||
concat!(
|
||||
"```rust\n",
|
||||
"use cuprate_test_utils::rpc::data::other::*;\n",
|
||||
"use serde_json::{to_value, Value};\n",
|
||||
"\n",
|
||||
"let value = serde_json::from_str::<Value>(&",
|
||||
stringify!($name),
|
||||
");\n",
|
||||
"```\n",
|
||||
)
|
||||
};
|
||||
|
||||
// No doc test.
|
||||
(
|
||||
$name:ident,
|
||||
$test:ident,
|
||||
) => {
|
||||
""
|
||||
};
|
||||
}
|
||||
pub(super) use define_request_and_response_doc_test;
|
18
test-utils/src/rpc/data/mod.rs
Normal file
18
test-utils/src/rpc/data/mod.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
//! Monero RPC data.
|
||||
//!
|
||||
//! This module contains real `monerod` RPC requests/responses
|
||||
//! as `const` [`str`]s and byte arrays (binary).
|
||||
//!
|
||||
//! The strings include the JSON-RPC 2.0 portions of the JSON.
|
||||
//! - Tests exist within this crate that ensure the JSON is valid
|
||||
//! - Tests exist within Cuprate's `rpc/` crates that ensure these strings (de)serialize as valid types
|
||||
//!
|
||||
//! # Determinism
|
||||
//! Note that although both request/response data is defined,
|
||||
//! they aren't necessarily tied to each other, i.e. the request
|
||||
//! will not deterministically lead to the response.
|
||||
|
||||
pub mod bin;
|
||||
pub mod json;
|
||||
mod macros;
|
||||
pub mod other;
|
839
test-utils/src/rpc/data/other.rs
Normal file
839
test-utils/src/rpc/data/other.rs
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,25 +1,6 @@
|
|||
//! Monero RPC client.
|
||||
//! Monero RPC data & client.
|
||||
//!
|
||||
//! This module is a client for Monero RPC that maps the types
|
||||
//! into the native types used by Cuprate found in `cuprate_types`.
|
||||
//!
|
||||
//! # Usage
|
||||
//! ```rust,ignore
|
||||
//! #[tokio::main]
|
||||
//! async fn main() {
|
||||
//! // Create RPC client.
|
||||
//! let rpc = HttpRpcClient::new(None).await;
|
||||
//!
|
||||
//! // Collect 20 blocks.
|
||||
//! let mut vec: Vec<VerifiedBlockInformation> = vec![];
|
||||
//! for height in (3130269 - 20)..3130269 {
|
||||
//! vec.push(rpc.get_verified_block_information(height).await);
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//! This module has a `monerod` RPC [`client`] and some real request/response [`data`].
|
||||
|
||||
mod client;
|
||||
pub use client::HttpRpcClient;
|
||||
|
||||
mod constants;
|
||||
pub use constants::LOCALHOST_RPC_URL;
|
||||
pub mod client;
|
||||
pub mod data;
|
||||
|
|
|
@ -17,4 +17,5 @@ extend-ignore-identifiers-re = [
|
|||
extend-exclude = [
|
||||
"/misc/gpg_keys/",
|
||||
"cryptonight/",
|
||||
"/test-utils/src/rpc/data/json.rs",
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue