mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 14:48:08 -05:00
explorerd/rpc: added test coverage for invalid/missing parameters
This commit expands the test suite by adding RPC tests that cover invalid/missing parameters, unsupported data types, unparsable inputs, and invalid numeric ranges. It also includes a test case to ensure `ping_darkfid` properly handles error when invoked under a disconnected darkfid endpoint. New test modules include: - **rpc/mod/tests**: Tests to ensure that `ping_darkfid` correctly handles non-empty parameters and scenarios where it is invoked with a disconnected darkfid endpoint - **rpc/blocks/tests**: Tests verifying that invalid/missing parameters for fetching blocks produce the expected error responses - **rpc/transaction/tests**: Tests confirming that incorrect/missing parameters for retrieving transactions are properly handled - **rpc/contracts/tests**: Tests ensuring invalid/missing parameter handling for retrieving native contracts data - **rpc/statistics/tests**: Tests confirming that invalid/missing parameters for retrieving statistics result in correct error handling Other updates: - Set the default test log level to 'Off' in test_mod.rs - Removed the `TEST_DATA_DIR` constant until the test cases are updated to run on a copy of the test `explorerdb` - Removed the `test_data/explorerd_0` folder until the test cases are updated to use a copy of the test `explorerdb` Running Tests: cargo test rpc
This commit is contained in:
@@ -55,8 +55,6 @@ mod error;
|
||||
|
||||
/// Test utilities used for unit and integration testing
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)]
|
||||
// TODO: Remove when test code that utilizes the new utility functions is checked in
|
||||
mod test_utils;
|
||||
|
||||
const CONFIG_FILE: &str = "explorerd_config.toml";
|
||||
|
||||
@@ -156,3 +156,155 @@ impl Explorerd {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Test module for validating the functionality of RPC methods related to explorer blocks.
|
||||
/// Focuses on ensuring proper error handling for invalid parameters across several use cases,
|
||||
/// including cases with missing values, unsupported types, invalid ranges, and unparsable inputs.
|
||||
mod tests {
|
||||
|
||||
use tinyjson::JsonValue;
|
||||
|
||||
use darkfi::rpc::{
|
||||
jsonrpc::{ErrorCode, JsonRequest, JsonResult},
|
||||
server::RequestHandler,
|
||||
};
|
||||
|
||||
use crate::test_utils::{
|
||||
setup, validate_invalid_rpc_header_hash, validate_invalid_rpc_parameter,
|
||||
};
|
||||
|
||||
#[test]
|
||||
/// Tests the handling of invalid parameters for the `blocks.get_last_n_blocks` JSON-RPC method.
|
||||
/// Verifies that missing and an invalid `num_last_blocks` value results in an appropriate error.
|
||||
fn test_blocks_get_last_n_blocks_invalid_params() {
|
||||
smol::block_on(async {
|
||||
// Define rpc_method and parameter names
|
||||
let rpc_method = "blocks.get_last_n_blocks";
|
||||
let parameter_name = "num_last_blocks";
|
||||
|
||||
// Set up the Explorerd instance
|
||||
let explorerd = setup();
|
||||
|
||||
// Test for missing `start` parameter
|
||||
validate_invalid_rpc_parameter(
|
||||
&explorerd,
|
||||
rpc_method,
|
||||
&[],
|
||||
ErrorCode::InvalidParams.code(),
|
||||
&format!("Parameter '{}' at index 0 is missing", parameter_name),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Test for invalid num_last_blocks parameter
|
||||
validate_invalid_rpc_parameter(
|
||||
&explorerd,
|
||||
rpc_method,
|
||||
&[JsonValue::String("invalid_number".to_string())],
|
||||
ErrorCode::InvalidParams.code(),
|
||||
&format!("Parameter '{}' is not a supported number type", parameter_name),
|
||||
)
|
||||
.await;
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Tests the handling of invalid parameters for the `blocks.get_blocks_in_heights_range`
|
||||
/// JSON-RPC method. Verifies that invalid/missing `start` or `end` parameter values, or an
|
||||
/// invalid range where `start` is greater than `end`, result in appropriate errors.
|
||||
fn test_blocks_get_blocks_in_heights_range_invalid_params() {
|
||||
smol::block_on(async {
|
||||
// Define rpc_method and parameter names
|
||||
let rpc_method = "blocks.get_blocks_in_heights_range";
|
||||
let start_parameter_name = "start";
|
||||
let end_parameter_name = "end";
|
||||
|
||||
// Set up the Explorerd instance
|
||||
let explorerd = setup();
|
||||
|
||||
// Test for missing `start` parameter
|
||||
validate_invalid_rpc_parameter(
|
||||
&explorerd,
|
||||
rpc_method,
|
||||
&[],
|
||||
ErrorCode::InvalidParams.code(),
|
||||
&format!("Parameter '{}' at index 0 is missing", start_parameter_name),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Test for invalid `start` parameter
|
||||
validate_invalid_rpc_parameter(
|
||||
&explorerd,
|
||||
rpc_method,
|
||||
&[JsonValue::String("invalid_number".to_string()), JsonValue::Number(10.0)],
|
||||
ErrorCode::InvalidParams.code(),
|
||||
&format!("Parameter '{start_parameter_name}' is not a supported number type"),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Test for invalid `end` parameter
|
||||
validate_invalid_rpc_parameter(
|
||||
&explorerd,
|
||||
rpc_method,
|
||||
&[JsonValue::Number(10.0)],
|
||||
ErrorCode::InvalidParams.code(),
|
||||
&format!("Parameter '{}' at index 1 is missing", end_parameter_name),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Test for invalid `end` parameter
|
||||
validate_invalid_rpc_parameter(
|
||||
&explorerd,
|
||||
rpc_method,
|
||||
&[JsonValue::Number(10.0), JsonValue::String("invalid_number".to_string())],
|
||||
ErrorCode::InvalidParams.code(),
|
||||
&format!("Parameter '{end_parameter_name}' is not a supported number type"),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Test invalid range where `start` > `end`
|
||||
let request = JsonRequest {
|
||||
id: 1,
|
||||
jsonrpc: "2.0",
|
||||
method: rpc_method.to_string(),
|
||||
params: JsonValue::Array(vec![JsonValue::Number(20.0), JsonValue::Number(10.0)]),
|
||||
};
|
||||
|
||||
let response = explorerd.handle_request(request).await;
|
||||
|
||||
// Verify that `start > end` error is raised
|
||||
match response {
|
||||
JsonResult::Error(actual_error) => {
|
||||
let expected_error_code = ErrorCode::InvalidParams.code();
|
||||
assert_eq!(
|
||||
actual_error.error.code,
|
||||
expected_error_code
|
||||
);
|
||||
assert_eq!(
|
||||
actual_error.error.message,
|
||||
"Invalid range: start (20) cannot be greater than end (10)"
|
||||
);
|
||||
}
|
||||
_ => panic!(
|
||||
"Expected a JSON error response for method: {rpc_method}, but got something else",
|
||||
),
|
||||
}
|
||||
});
|
||||
}
|
||||
#[test]
|
||||
/// Tests the handling of invalid parameters for the `blocks.get_block_by_hash` JSON-RPC method.
|
||||
/// Verifies that an invalid `header_hash` value, either a numeric type or invalid hash string,
|
||||
/// results in appropriate error.
|
||||
fn test_blocks_get_block_by_hash_invalid_params() {
|
||||
smol::block_on(async {
|
||||
// Define the RPC method name
|
||||
let rpc_method = "blocks.get_block_by_hash";
|
||||
|
||||
// Set up the explorerd
|
||||
let explorerd = setup();
|
||||
|
||||
// Validate when provided with an invalid tx hash
|
||||
validate_invalid_rpc_header_hash(&explorerd, rpc_method);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,3 +126,73 @@ impl Explorerd {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Test module for validating the functionality of RPC methods related to explorer contracts.
|
||||
/// Focuses on ensuring proper error handling for invalid parameters across several use cases,
|
||||
/// including cases with missing values, unsupported types, and unparsable inputs.
|
||||
mod tests {
|
||||
|
||||
use tinyjson::JsonValue;
|
||||
|
||||
use darkfi::rpc::jsonrpc::ErrorCode;
|
||||
|
||||
use crate::test_utils::{
|
||||
setup, validate_empty_rpc_parameters, validate_invalid_rpc_contract_id,
|
||||
validate_invalid_rpc_parameter,
|
||||
};
|
||||
|
||||
#[test]
|
||||
/// Tests the `contracts.get_native_contracts` method to ensure it correctly handles cases where
|
||||
/// empty parameters are supplied, returning an expected result or error response.
|
||||
fn test_contracts_get_native_contracts_empty_params() {
|
||||
smol::block_on(async {
|
||||
validate_empty_rpc_parameters(&setup(), "contracts.get_native_contracts").await;
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Tests the `contracts.get_contract_source_code_paths` method to ensure it correctly handles cases
|
||||
/// with invalid or missing `contract_id` parameters, returning appropriate error responses.
|
||||
fn test_contracts_get_contract_source_code_paths_invalid_params() {
|
||||
validate_invalid_rpc_contract_id(&setup(), "contracts.get_contract_source_code_paths");
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Tests the `contracts.get_contract_source` method to ensure it correctly handles cases
|
||||
/// with invalid or missing parameters, returning appropriate error responses.
|
||||
fn test_contracts_get_contract_source_invalid_params() {
|
||||
let test_method = "contracts.get_contract_source";
|
||||
let parameter_name = "source_path";
|
||||
|
||||
smol::block_on(async {
|
||||
// Set up the explorerd instance
|
||||
let explorerd = setup();
|
||||
|
||||
validate_invalid_rpc_contract_id(&explorerd, test_method);
|
||||
|
||||
// Test for missing `source_path` parameter
|
||||
validate_invalid_rpc_parameter(
|
||||
&explorerd,
|
||||
test_method,
|
||||
&[JsonValue::String("BZHKGQ26bzmBithTQYTJtjo2QdCqpkR9tjSBopT4yf4o".to_string())],
|
||||
ErrorCode::InvalidParams.code(),
|
||||
&format!("Parameter '{}' at index 1 is missing", parameter_name),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Test for invalid `source_path` parameter
|
||||
validate_invalid_rpc_parameter(
|
||||
&explorerd,
|
||||
test_method,
|
||||
&[
|
||||
JsonValue::String("BZHKGQ26bzmBithTQYTJtjo2QdCqpkR9tjSBopT4yf4o".to_string()),
|
||||
JsonValue::Number(123.0), // Invalid `source_path` type
|
||||
],
|
||||
ErrorCode::InvalidParams.code(),
|
||||
&format!("Parameter '{}' is not a valid string", parameter_name),
|
||||
)
|
||||
.await;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,3 +339,60 @@ fn log_request_failure(req_method: &str, params: &JsonValue, error: &JsonError)
|
||||
// Log the error
|
||||
error!(target: &log_target, "{}", error_message);
|
||||
}
|
||||
|
||||
/// Test module for validating API functions within this `mod.rs` file. It ensures that the core API
|
||||
/// functions behave as expected and that they handle invalid parameters properly.
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use tinyjson::JsonValue;
|
||||
|
||||
use darkfi::rpc::jsonrpc::JsonRequest;
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
error::ERROR_CODE_PING_DARKFID_FAILED,
|
||||
test_utils::{setup, validate_empty_rpc_parameters},
|
||||
};
|
||||
|
||||
#[test]
|
||||
/// Validates the failure scenario of the `ping_darkfid` JSON-RPC method by sending a request
|
||||
/// to a disconnected darkfid endpoint, ensuring the response is an error with the expected
|
||||
/// code and message.
|
||||
fn test_ping_darkfid_failure() {
|
||||
smol::block_on(async {
|
||||
// Set up the Explorerd instance
|
||||
let explorerd = setup();
|
||||
|
||||
// Prepare a JSON-RPC request for `ping_darkfid`
|
||||
let request = JsonRequest {
|
||||
id: 1,
|
||||
jsonrpc: "2.0",
|
||||
method: "ping_darkfid".to_string(),
|
||||
params: JsonValue::Array(vec![]),
|
||||
};
|
||||
|
||||
// Call `handle_request` on the Explorerd instance
|
||||
let response = explorerd.handle_request(request).await;
|
||||
|
||||
// Verify the response is a `JsonError` with the `PingFailed` error code
|
||||
match response {
|
||||
JsonResult::Error(actual_error) => {
|
||||
let expected_error_code = ERROR_CODE_PING_DARKFID_FAILED;
|
||||
let expected_error_msg = "Ping darkfid failed: Not connected, is the explorer running in no-sync mode?";
|
||||
assert_eq!(actual_error.error.code, expected_error_code);
|
||||
assert_eq!(actual_error.error.message, expected_error_msg);
|
||||
}
|
||||
_ => panic!("Expected a JSON object for the response, but got something else"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Tests the `ping_darkfid` method to ensure it correctly handles cases where non-empty parameters
|
||||
/// are supplied, returning an expected error response.
|
||||
#[test]
|
||||
fn test_ping_darkfid_empty_params() {
|
||||
smol::block_on(async {
|
||||
validate_empty_rpc_parameters(&setup(), "ping_darkfid").await;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,3 +103,30 @@ impl Explorerd {
|
||||
Ok(statistics.to_json_array())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Test module for validating the functionality of RPC methods related to explorer statistics.
|
||||
/// Focuses on ensuring proper error handling for invalid parameters across several use cases.
|
||||
mod tests {
|
||||
|
||||
use crate::test_utils::{setup, validate_empty_rpc_parameters};
|
||||
|
||||
/// Tests all RPC-related statistics calls when provided with empty parameters, ensuring they
|
||||
/// handle the input correctly and return appropriate validation responses.
|
||||
#[test]
|
||||
fn test_statistics_rpc_calls_for_empty_parameters() {
|
||||
smol::block_on(async {
|
||||
let explorerd = setup();
|
||||
|
||||
let rpc_methods = [
|
||||
"statistics.get_latest_metric_statistics",
|
||||
"statistics.get_metric_statistics",
|
||||
"statistics.get_basic_statistics",
|
||||
];
|
||||
|
||||
for rpc_method in rpc_methods.iter() {
|
||||
validate_empty_rpc_parameters(&explorerd, rpc_method).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,3 +83,45 @@ impl Explorerd {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Test module for validating the functionality of RPC methods related to explorer transactions.
|
||||
/// Focuses on ensuring proper error handling for invalid parameters across several use cases,
|
||||
/// including cases with missing values, unsupported types, and unparsable inputs.
|
||||
mod tests {
|
||||
|
||||
use crate::test_utils::{
|
||||
setup, validate_invalid_rpc_header_hash, validate_invalid_rpc_tx_hash,
|
||||
};
|
||||
|
||||
#[test]
|
||||
/// Tests the handling of invalid parameters for the `transactions.get_transactions_by_header_hash` JSON-RPC method.
|
||||
/// Verifies that missing and an invalid `header_hash` value results in an appropriate error.
|
||||
fn test_transactions_get_transactions_by_header_hash() {
|
||||
smol::block_on(async {
|
||||
// Define the RPC method name
|
||||
let rpc_method = "transactions.get_transactions_by_header_hash";
|
||||
|
||||
// Set up the explorerd
|
||||
let explorerd = setup();
|
||||
|
||||
// Validate when provided with an invalid header hash
|
||||
validate_invalid_rpc_header_hash(&explorerd, rpc_method);
|
||||
});
|
||||
}
|
||||
#[test]
|
||||
/// Tests the handling of invalid parameters for the `transactions.get_transaction_by_hash` JSON-RPC method.
|
||||
/// Verifies that missing and an invalid `tx_hash` value results in an appropriate error.
|
||||
fn test_transactions_get_transaction_by_hash() {
|
||||
smol::block_on(async {
|
||||
// Define the RPC method name
|
||||
let rpc_method = "transactions.get_transaction_by_hash";
|
||||
|
||||
// Set up the explorerd
|
||||
let explorerd = setup();
|
||||
|
||||
// Validate when provided with an invalid tx hash
|
||||
validate_invalid_rpc_tx_hash(&explorerd, rpc_method);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ use std::sync::{Arc, Mutex};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use smol::Executor;
|
||||
use tempdir::TempDir;
|
||||
use tinyjson::JsonValue;
|
||||
use url::Url;
|
||||
|
||||
@@ -30,8 +31,6 @@ use darkfi::rpc::{
|
||||
|
||||
use crate::Explorerd;
|
||||
|
||||
const TEST_DATA_DIR: &str = "src/test_utils/test_data";
|
||||
|
||||
// Defines a global `Explorerd` instance shared across all tests
|
||||
lazy_static! {
|
||||
static ref EXPLORERD_INSTANCE: Mutex<Option<Arc<Explorerd>>> = Mutex::new(None);
|
||||
@@ -73,10 +72,13 @@ pub fn setup() -> Arc<Explorerd> {
|
||||
|
||||
if instance.is_none() {
|
||||
// Initialize logger for the first time
|
||||
init_logger(simplelog::LevelFilter::Info, vec!["sled", "runtime", "net"]);
|
||||
init_logger(simplelog::LevelFilter::Off, vec!["sled", "runtime", "net"]);
|
||||
|
||||
// Prepare parameters for Explorerd::new
|
||||
let db_path = format!("{}/explorerd_0", TEST_DATA_DIR);
|
||||
let temp_dir = TempDir::new("explorerd").expect("Failed to create temp dir");
|
||||
let db_path_buf = temp_dir.path().join("explorerd_0");
|
||||
let db_path =
|
||||
db_path_buf.to_str().expect("Failed to convert db_path to string").to_string();
|
||||
let darkfid_endpoint = Url::parse("http://127.0.0.1:8240").expect("Invalid URL");
|
||||
let executor = Arc::new(Executor::new());
|
||||
|
||||
@@ -130,12 +132,12 @@ pub async fn validate_invalid_rpc_parameter(
|
||||
/// Auxiliary function that validates the handling of non-empty parameters when they are supposed
|
||||
/// to be empty for the given RPC `method`. It uses the provided [`Explorerd`] instance to ensure
|
||||
/// that unexpected non-empty parameters result in the expected error for invalid parameters.
|
||||
pub async fn validate_empty_rpc_parameters(explorerd: &Explorerd, method: String) {
|
||||
pub async fn validate_empty_rpc_parameters(explorerd: &Explorerd, method: &str) {
|
||||
// Prepare a JSON-RPC request for `ping_darkfid`
|
||||
let request = JsonRequest {
|
||||
id: 1,
|
||||
jsonrpc: "2.0",
|
||||
method,
|
||||
method: method.to_string(),
|
||||
params: JsonValue::Array(vec![JsonValue::String("non_empty_param".to_string())]),
|
||||
};
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +0,0 @@
|
||||
segment_size: 524288
|
||||
use_compression: false
|
||||
version: 0.34
|
||||
vQ<>
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user