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" }