-
Notifications
You must be signed in to change notification settings - Fork 49
binaries: rpc-compat/
#422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Would this be better as an integration test rather than a separate binary? |
|
The testing space is
In the If the purpose of the integration test is to run all tests in CI it could be done with:
Although running the tests in CI also runs into a few problems:
I guess the second could be solved with something like |
|
Discussed in monero-project/meta#1176 monero-project/meta#1185. Rough plan for cuprate-rpc-compat (this PR)what
For a set of defined This binary must:
exceptionsExceptions to type/value equality assertions:
cli api* = required
--monerod <ADDR> * The `monerod` node to use.
--cuprated <ADDR> * The `cuprated` node to use.
--test-set <TEST_SET> The set of RPC tests to run. Default = Full.
--endpoints <ENDPOINTS> Endpoints to run tests on. Default = All.
--methods <METHODS> JSON-RPC methods to run tests on. Default = All.ciname: cuprate-rpc-compat
on:
# when there are changes to relevent directories
jobs:
ci:
runs-on: ubuntu-latest
# ... all required pre-steps
- name: Test
run: |
cargo run --release --bin cuprate-rpc-compat -- --test-set ci --monerod $ADDR --cuprated $ADDR2remaining questions/problems
internal signaturesNot working code, just the general shape. //! base data structures + test generation code
struct Config {/*...*/}
enum Endpoint {/*...*/}
enum Method {/*...*/}
enum TestSet {
/// Specific subset of tests meant for CI.
Ci,
/// Subset of important tests (e.g. key blocks for `get_block`).
Core,
/// All tests possible (e.g. all blocks for `get_block`).
Full,
}
/// TODO: generic handling for {json,epee} such that
/// serde and epee is handled outside of any test.
///
/// `type Request; type Response` could be added to `RpcCall`
struct Test {
request: Request,
/// (monerod, cuprated) responses
test_fn: fn(Response, Response),
}
impl Config {
fn endpoint_enabled(&self, Endpoint) -> bool;
fn method_enabled(&self, Method) -> bool;
/// generates the tests for the given test-set
fn generate_tests(&self, top_height: u64) -> HashSet<Test> {
// this is where we define test cases (can be anywhere,
// although we must define the creation of these somewhere)
//
// it can be something like:
(0..top_height)
.map(|height| format!(r#"{"jsonrpc":"2.0","method":"get_block_count","params":{"height":{height}}}"#))
.collect();
// or a 1-off special case or anything in-between.
// TODO: maybe define the full set of tests, then define
// the other sets by selectively `.take()`ing.
match self.test_set {
Self::Ci => /* define tests for ci */,
Self::Core => /* ... */,
Self::Full => /* define all tests */,
}
}
}//! value assertion test fn examples
/// example test fn for `get_block`
fn get_block(monerod: Response, cuprated: Response) {
use serde_json::from_str;
use cuprate_types::json::Block;
let block_monerod = from_str::<Block>(&monerod.json).unwrap();
let block_cuprated = from_str::<Block>(&cuprated.json).unwrap();
assert_eq!(block_monerod, block_cuprated);
/* ... test other fields ... */
}
/// example test fn for `calc_pow`
fn calc_pow(monerod: Response, cuprated: Response) {
assert_eq!(monerod.result, cuprated.result);
}
/// example test fn for `get_info`
fn get_info(monerod: Response, cuprated: Response) {
assert_eq!(monerod.adjusted_time, cuprated.adjusted_time);
// ignored
// assert_eq!(monerod.busy_syncing, cuprated.busy_syncing);
// assert_eq!(monerod.database_size, cuprated.database_size);
/* ... test other fields ... */
}//! rpc client
struct Block {/*...*/}
struct RpcClient {
config: Config,
/* ... */
}
// -> (monerod, cuprated)
impl RpcClient {
fn new() -> Self;
fn top_height(self) -> (u64, u64);
fn call(&self, Request) -> (Response, Response);
fn test(&self, test: Test) {
// TODO: logging:
{
struct Log {
test_name: Option<String>, // if None, just the request or endpoint?
request: Request,
endpoint: EndpointOrMethod,
}
let log: Log = todo!();
println!("{log}");
}
let (monerod, cuprated) = self.call(test.request);
test.test_fn(monerod, cuprated);
}
}fn main() {
let config = todo!();
let mut rpc_client = RpcClient::new()
if todo!("any test requires blocks") {
rpc_client.get_blocks();
}
let tests = config.generate_tests();
for test in tests {
rpc_client.test(test);
}
} |
What
Adds a binary for testing RPC compatibility between
monerodandcuprated.See
binaries/rpc-compat/README.md.Where
cuprate-rpc-compat = { path = "/binaries/rpc-compat" }