feat!(avm-server): Per-call current_peer_id (#381)

The current peer ID is passed as a new field of `TestRunParameters` named
`current_peer_id: String`, instead of creating an AVM with peer ID.

This is a breaking API change of `avm-interface` and `avm-server`.
This commit is contained in:
Ivan Boldyrev
2022-11-25 10:59:09 +03:00
committed by GitHub
parent 4e86da7eda
commit becdedc364
22 changed files with 206 additions and 85 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "air-test-utils"
version = "0.3.0"
version = "0.4.0"
description = "Test utils for the AIR interpreter"
authors = ["Fluence Labs"]
edition = "2018"
@ -26,5 +26,8 @@ once_cell = "1.16.0"
semver = "1.0.14"
serde_json = "1.0.89"
[dev-dependencies]
maplit = "1.0.2"
[features]
test_with_native_code = []

View File

@ -38,19 +38,23 @@ impl AirRunner for NativeAirRunner {
init_peer_id: impl Into<String>,
timestamp: u64,
ttl: u32,
override_current_peer_id: Option<String>,
call_results: avm_server::CallResults,
) -> Result<RawAVMOutcome, Box<dyn std::error::Error>> {
// some inner parts transformations
let raw_call_results = into_raw_result(call_results);
let raw_call_results = serde_json::to_vec(&raw_call_results).unwrap();
let current_peer_id =
override_current_peer_id.unwrap_or_else(|| self.current_peer_id.clone());
let outcome = air::execute_air(
air.into(),
prev_data.into(),
data.into(),
RunParameters {
init_peer_id: init_peer_id.into(),
current_peer_id: self.current_peer_id.clone(),
current_peer_id,
timestamp,
ttl,
},

View File

@ -37,6 +37,7 @@ pub trait AirRunner {
init_peer_id: impl Into<String>,
timestamp: u64,
ttl: u32,
override_current_peer_id: Option<String>,
call_results: avm_server::CallResults,
) -> Result<RawAVMOutcome, Box<dyn std::error::Error>>;
}
@ -51,6 +52,7 @@ pub struct TestRunParameters {
pub init_peer_id: String,
pub timestamp: u64,
pub ttl: u32,
pub override_current_peer_id: Option<String>,
}
impl<R: AirRunner> TestRunner<R> {
@ -69,6 +71,7 @@ impl<R: AirRunner> TestRunner<R> {
init_peer_id,
timestamp,
ttl,
override_current_peer_id,
} = test_run_params;
let mut call_results = HashMap::new();
@ -84,6 +87,7 @@ impl<R: AirRunner> TestRunner<R> {
init_peer_id.clone(),
timestamp,
ttl,
override_current_peer_id.clone(),
call_results,
)
.map_err(|e| e.to_string())?;
@ -128,6 +132,7 @@ impl TestRunParameters {
init_peer_id: init_peer_id.into(),
timestamp,
ttl,
override_current_peer_id: None,
}
}
@ -136,6 +141,7 @@ impl TestRunParameters {
init_peer_id: init_peer_id.into(),
timestamp: 0,
ttl: 0,
override_current_peer_id: None,
}
}
@ -144,6 +150,7 @@ impl TestRunParameters {
init_peer_id: String::new(),
timestamp,
ttl: 0,
override_current_peer_id: None,
}
}
@ -152,6 +159,73 @@ impl TestRunParameters {
init_peer_id: String::new(),
timestamp: 0,
ttl,
override_current_peer_id: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::call_services::{set_variables_call_service, VariableOptionSource};
use avm_interface::CallRequestParams;
use fstrings::f;
use fstrings::format_args_f;
use serde_json::json;
#[test]
fn test_override_current_peer_id() {
let spell_id = "spell_id";
let host_peer_id = "host_peer_id";
let script = f!(r#"(call "{}" ("service" "func") [])"#, spell_id);
let variables = maplit::hashmap! {
"func".to_owned() => json!("success"),
};
let mut client = create_avm(
set_variables_call_service(variables, VariableOptionSource::FunctionName),
host_peer_id,
);
let current_result_1 = client
.runner
.call(&script, "", "", spell_id, 0, 0, None, HashMap::new())
.expect("call should be success");
let expected_current_call_requests = HashMap::new();
let expected_current_next_peers_pks = vec![spell_id.to_owned()];
assert_eq!(
current_result_1.call_requests,
expected_current_call_requests
);
assert_eq!(
current_result_1.next_peer_pks,
expected_current_next_peers_pks
);
let spell_result_1 = client
.runner
.call(
script,
"",
"",
spell_id,
0,
0,
Some(spell_id.to_owned()),
HashMap::new(),
)
.expect("call should be success");
let expected_spell_call_requests = maplit::hashmap! {
1 => CallRequestParams::new("service", "func", vec![], vec![]),
};
let expected_spell_next_peers_pks = Vec::<String>::new();
assert_eq!(spell_result_1.call_requests, expected_spell_call_requests);
assert_eq!(spell_result_1.next_peer_pks, expected_spell_next_peers_pks);
}
}

View File

@ -24,15 +24,16 @@ use std::path::PathBuf;
const AVM_MAX_HEAP_SIZE: u64 = 10 * 1024 * 1024;
const AIR_WASM_PATH: &str = "../target/wasm32-wasi/debug/air_interpreter_server.wasm";
pub struct WasmAirRunner(object_pool::Reusable<'static, AVMRunner>);
pub struct WasmAirRunner {
current_peer_id: String,
runner: object_pool::Reusable<'static, AVMRunner>,
}
fn make_pooled_avm_runner() -> AVMRunner {
let fake_current_peer_id = "";
let logging_mask = i32::MAX;
AVMRunner::new(
PathBuf::from(AIR_WASM_PATH),
fake_current_peer_id,
Some(AVM_MAX_HEAP_SIZE),
logging_mask,
)
@ -51,10 +52,12 @@ impl AirRunner for WasmAirRunner {
)
});
let mut runner = pool.pull(make_pooled_avm_runner);
runner.set_peer_id(current_peer_id);
let runner = pool.pull(make_pooled_avm_runner);
Self(runner)
Self {
current_peer_id: current_peer_id.into(),
runner,
}
}
fn call(
@ -65,15 +68,20 @@ impl AirRunner for WasmAirRunner {
init_peer_id: impl Into<String>,
timestamp: u64,
ttl: u32,
override_current_peer_id: Option<String>,
call_results: avm_server::CallResults,
) -> Result<RawAVMOutcome, Box<dyn std::error::Error>> {
Ok(self.0.call(
let current_peer_id =
override_current_peer_id.unwrap_or_else(|| self.current_peer_id.clone());
Ok(self.runner.call(
air,
prev_data,
data,
init_peer_id,
timestamp,
ttl,
current_peer_id,
call_results,
)?)
}