Skip to content

Commit

Permalink
add mock for p2p and job traits
Browse files Browse the repository at this point in the history
  • Loading branch information
oac1771 committed Dec 16, 2024
1 parent 52d83db commit 904313d
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 6 deletions.
31 changes: 29 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ members = [
"crates/node",
"crates/runtime",
"crates/catalog",
"crates/utils",
"crates/utils",
"crates/scripts",
"crates/integration_tests",
"crates/integration_tests/test_macro",
Expand Down
1 change: 1 addition & 0 deletions crates/utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ sp-weights = { workspace = true, default-features = false }

catalog = { workspace = true }
async-stream = "0.3.6"
mockall = "0.13.1"

[dev-dependencies]
wabt = "0.9.0"
Expand Down
2 changes: 2 additions & 0 deletions crates/utils/src/services/job/job_handler.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{Job, JobT, RawResults, RawResultsT, Results, Val};
use codec::{Decode, Encode};
use mockall::automock;
use std::{
any::type_name,
fmt::Display,
Expand All @@ -10,6 +11,7 @@ use std::{
use tokio::{fs::File, io::AsyncReadExt};
use wasmtime::{Engine, ExternType, FuncType, Module, ValType};

#[automock(type Job=Job; type RawResults=RawResults; type Err=JobHandlerServiceError; type Results=Results;)]
pub trait JobHandlerService {
type Err;
type Job: JobT;
Expand Down
2 changes: 2 additions & 0 deletions crates/utils/src/services/job/job_runner.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use super::{Job, JobT, RawResults, RawResultsT};
use codec::{Decode, Encode};
use futures::Future;
use mockall::automock;
use tokio::task::JoinHandle;
use wasmtime::{Engine, ExternType, Func, FuncType, Instance, Linker, Module, Store, Val, ValType};

#[automock(type Job=Job; type RawResults=RawResults; type Err=WasmJobRunnerServiceError;)]
pub trait WasmJobRunnerService {
type Err;
type Job: JobT;
Expand Down
242 changes: 241 additions & 1 deletion crates/utils/src/services/p2p.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub trait NetworkClient {
&self,
topic: &str,
msg: Vec<u8>,
) -> impl Future<Output = Result<(), Self::Err>>;
) -> impl Future<Output = Result<(), Self::Err>> + Send;

fn send_request(
&self,
Expand Down Expand Up @@ -789,3 +789,243 @@ pub enum NetworkError {
#[error("{err}")]
SendClientRequest { err: String },
}

#[cfg(test)]
mod test {
use stream::iter;

use super::*;
use std::{
any::Any,
collections::HashMap,
marker::{Send, Sync},
};

struct Expectation<T> {
func: Option<Box<dyn Fn() -> T + Send + Sync>>,
}

impl<T> Expectation<T> {
fn _returns(&mut self, func: Box<dyn Fn() -> T + Send + Sync>) {
self.func = Some(func);
}
}

struct MockNodeClient {
expectations: HashMap<String, Box<dyn Any>>,
}

impl MockNodeClient {
fn _expect_publish_message(&mut self) -> &mut Expectation<Result<(), NetworkClientError>> {
self.expectations
.entry("publish_message".to_string())
.or_insert_with(|| {
Box::new(Expectation::<Result<(), NetworkClientError>> { func: None })
})
.downcast_mut::<Expectation<Result<(), NetworkClientError>>>()
.unwrap()
}

fn _expect_send_request(&mut self) -> &mut Expectation<Result<u64, NetworkClientError>> {
self.expectations
.entry("send_request".to_string())
.or_insert_with(|| {
Box::new(Expectation::<Result<u64, NetworkClientError>> { func: None })
})
.downcast_mut::<Expectation<Result<u64, NetworkClientError>>>()
.unwrap()
}

fn _expect_send_response(&mut self) -> &mut Expectation<Result<(), NetworkClientError>> {
self.expectations
.entry("send_response".to_string())
.or_insert_with(|| {
Box::new(Expectation::<Result<(), NetworkClientError>> { func: None })
})
.downcast_mut::<Expectation<Result<(), NetworkClientError>>>()
.unwrap()
}

fn _expect_get_gossip_nodes(
&mut self,
) -> &mut Expectation<Result<Vec<NetworkId>, NetworkClientError>> {
self.expectations
.entry("get_gossip_nodes".to_string())
.or_insert_with(|| {
Box::new(Expectation::<Result<Vec<NetworkId>, NetworkClientError>> {
func: None,
})
})
.downcast_mut::<Expectation<Result<Vec<NetworkId>, NetworkClientError>>>()
.unwrap()
}

fn _expect_get_local_network_id(
&mut self,
) -> &mut Expectation<Result<NetworkId, NetworkClientError>> {
self.expectations
.entry("get_local_network_id".to_string())
.or_insert_with(|| {
Box::new(Expectation::<Result<NetworkId, NetworkClientError>> { func: None })
})
.downcast_mut::<Expectation<Result<NetworkId, NetworkClientError>>>()
.unwrap()
}

fn _expect_gossip_msg_stream(&mut self) -> &mut Expectation<Vec<GossipMessage>> {
self.expectations
.entry("expect_gossip_msg_stream".to_string())
.or_insert_with(|| Box::new(Expectation::<Vec<GossipMessage>> { func: None }))
.downcast_mut::<Expectation<Vec<GossipMessage>>>()
.unwrap()
}

fn _expect_req_stream(&mut self) -> &mut Expectation<Vec<InboundP2pRequest>> {
self.expectations
.entry("expect_req_stream".to_string())
.or_insert_with(|| Box::new(Expectation::<Vec<InboundP2pRequest>> { func: None }))
.downcast_mut::<Expectation<Vec<InboundP2pRequest>>>()
.unwrap()
}

fn _expect_resp_stream(&mut self) -> &mut Expectation<Vec<InboundP2pResponse>> {
self.expectations
.entry("expect_resp_stream".to_string())
.or_insert_with(|| Box::new(Expectation::<Vec<InboundP2pResponse>> { func: None }))
.downcast_mut::<Expectation<Vec<InboundP2pResponse>>>()
.unwrap()
}
}

impl NetworkClient for MockNodeClient {
type Err = NetworkClientError;
type Id = u64;
type NetworkId = NetworkId;
type GossipMessage = GossipMessage;
type Request = InboundP2pRequest;
type Response = InboundP2pResponse;

fn publish_message(
&self,
_topic: &str,
_msg: Vec<u8>,
) -> impl Future<Output = Result<(), Self::Err>> + Send {
let expectation = self
.expectations
.get("publish_message")
.and_then(|e| e.downcast_ref::<Expectation<Result<(), NetworkClientError>>>())
.unwrap();

let func = expectation.func.as_ref().unwrap();

async { func() }
}

fn send_request(
&self,
_network_id: Self::NetworkId,
_payload: Vec<u8>,
) -> impl Future<Output = Result<Self::Id, Self::Err>> + Send {
let expectation = self
.expectations
.get("send_request")
.and_then(|e| e.downcast_ref::<Expectation<Result<u64, NetworkClientError>>>())
.unwrap();

let func = expectation.func.as_ref().unwrap();

async { func() }
}

fn send_response(
&self,
_id: Self::Id,
_payload: Vec<u8>,
) -> impl Future<Output = Result<(), Self::Err>> + Send {
let expectation = self
.expectations
.get("send_response")
.and_then(|e| e.downcast_ref::<Expectation<Result<(), NetworkClientError>>>())
.unwrap();

let func = expectation.func.as_ref().unwrap();

async { func() }
}

fn get_gossip_nodes(
&self,
_topic: &str,
) -> impl Future<Output = Result<impl Iterator<Item = Self::NetworkId>, Self::Err>> + Send
{
let expectation = self
.expectations
.get("get_gossip_nodes")
.and_then(|e| {
e.downcast_ref::<Expectation<Result<Vec<NetworkId>, NetworkClientError>>>()
})
.unwrap();

let func = expectation.func.as_ref().unwrap()().and_then(|x| Ok(x.into_iter()));

async { func }
}

fn get_local_network_id(
&self,
) -> impl Future<Output = Result<Self::NetworkId, Self::Err>> + Send {
let expectation = self
.expectations
.get("get_local_network_id")
.and_then(|e| {
e.downcast_ref::<Expectation<Result<NetworkId, NetworkClientError>>>()
})
.unwrap();

let func = expectation.func.as_ref().unwrap();

async { func() }
}

fn gossip_msg_stream(
&self,
) -> impl Future<Output = impl Stream<Item = Self::GossipMessage>> + Send {
let expectation = self
.expectations
.get("expect_gossip_msg_stream")
.and_then(|e| e.downcast_ref::<Expectation<Vec<GossipMessage>>>())
.unwrap();

let func = expectation.func.as_ref().unwrap()().into_iter();
let stream = iter(func);

async { stream }
}

fn req_stream(&self) -> impl Future<Output = impl Stream<Item = Self::Request>> + Send {
let expectation = self
.expectations
.get("expect_req_stream")
.and_then(|e| e.downcast_ref::<Expectation<Vec<InboundP2pRequest>>>())
.unwrap();

let func = expectation.func.as_ref().unwrap()().into_iter();
let stream = iter(func);

async { stream }
}

fn resp_stream(&self) -> impl Future<Output = impl Stream<Item = Self::Response>> + Send {
let expectation = self
.expectations
.get("expect_resp_stream")
.and_then(|e| e.downcast_ref::<Expectation<Vec<InboundP2pResponse>>>())
.unwrap();

let func = expectation.func.as_ref().unwrap()().into_iter();
let stream = iter(func);

async { stream }
}
}
}
21 changes: 19 additions & 2 deletions todo.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
refactor contract client so that it calls subxt client

create derive macro for mock stuff

refactor contract client so that it calls subxt client

- catalog
- make contract upgradeable

Expand All @@ -16,3 +16,20 @@ larger refactor:
- figure out how to use substrate wasm builder for ink contract to not need to use cargo contract cli
to build wasm binary


proc macro to describe iac state
- one mod macro like substrate pallet with inner attribute macros as resource objects
- can build dependcy tree from resource name mapping to instance of resource objects name:

#[name("Alice")]
struct User;

#[name("Bob")]
struct User;

#[name("Admin")]
struct UserGroup {
ids = [Alice.id, Bob.id]
}

// UserGroup depends on Users

0 comments on commit 904313d

Please sign in to comment.