-
Notifications
You must be signed in to change notification settings - Fork 360
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
Abstracting API out of tests internals so it is clearly owned by App
#368
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
too-many-arguments-threshold = 10 |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -30,7 +30,8 @@ pub struct App<C = Empty> | |||||
where | ||||||
C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, | ||||||
{ | ||||||
pub router: Router<C>, | ||||||
router: Router<C>, | ||||||
api: Box<dyn Api>, | ||||||
storage: Box<dyn Storage>, | ||||||
block: BlockInfo, | ||||||
} | ||||||
|
@@ -41,7 +42,7 @@ where | |||||
{ | ||||||
fn raw_query(&self, bin_request: &[u8]) -> QuerierResult { | ||||||
self.router | ||||||
.querier(self.storage.as_ref(), &self.block) | ||||||
.querier(self.api.as_ref(), self.storage.as_ref(), &self.block) | ||||||
.raw_query(bin_request) | ||||||
} | ||||||
} | ||||||
|
@@ -62,14 +63,15 @@ where | |||||
C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, | ||||||
{ | ||||||
pub fn new( | ||||||
api: Box<dyn Api>, | ||||||
api: impl Api + 'static, | ||||||
block: BlockInfo, | ||||||
bank: impl Bank + 'static, | ||||||
storage: Box<dyn Storage>, | ||||||
storage: impl Storage + 'static, | ||||||
) -> Self { | ||||||
App { | ||||||
router: Router::new(api, bank), | ||||||
storage, | ||||||
router: Router::new(bank), | ||||||
api: Box::new(api), | ||||||
storage: Box::new(storage), | ||||||
block, | ||||||
} | ||||||
} | ||||||
|
@@ -106,10 +108,16 @@ where | |||||
// meaning, wrap current state, all writes go to a cache, only when execute | ||||||
// returns a success do we flush it (otherwise drop it) | ||||||
|
||||||
let (block, router) = (&self.block, &self.router); | ||||||
transactional(self.storage.as_mut(), |write_cache, _| { | ||||||
let Self { | ||||||
block, | ||||||
router, | ||||||
api, | ||||||
storage, | ||||||
} = self; | ||||||
|
||||||
transactional(storage.as_mut(), |write_cache, _| { | ||||||
msgs.into_iter() | ||||||
.map(|msg| router.execute(write_cache, block, sender.clone(), msg)) | ||||||
.map(|msg| router.execute(api.as_ref(), write_cache, block, sender.clone(), msg)) | ||||||
.collect() | ||||||
}) | ||||||
} | ||||||
|
@@ -144,6 +152,7 @@ where | |||||
) -> Result<AppResponse, String> { | ||||||
let msg = to_vec(msg).map_err(|e| e.to_string())?; | ||||||
self.router.wasm.sudo( | ||||||
self.api.as_ref(), | ||||||
contract_addr.into(), | ||||||
self.storage.as_mut(), | ||||||
&self.router, | ||||||
|
@@ -153,10 +162,7 @@ where | |||||
} | ||||||
} | ||||||
|
||||||
pub struct Router<C> | ||||||
where | ||||||
C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, | ||||||
{ | ||||||
pub struct Router<C> { | ||||||
pub wasm: Box<dyn Wasm<C>>, | ||||||
pub bank: Box<dyn Bank>, | ||||||
} | ||||||
|
@@ -165,20 +171,22 @@ impl<C> Router<C> | |||||
where | ||||||
C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, | ||||||
{ | ||||||
pub fn new(api: Box<dyn Api>, bank: impl Bank + 'static) -> Self { | ||||||
pub(super) fn new(bank: impl Bank + 'static) -> Self { | ||||||
Router { | ||||||
wasm: Box::new(WasmKeeper::new(api)), | ||||||
wasm: Box::new(WasmKeeper::new()), | ||||||
bank: Box::new(bank), | ||||||
} | ||||||
} | ||||||
|
||||||
pub fn querier<'a>( | ||||||
&'a self, | ||||||
api: &'a dyn Api, | ||||||
storage: &'a dyn Storage, | ||||||
block_info: &'a BlockInfo, | ||||||
) -> RouterQuerier<'a, C> { | ||||||
RouterQuerier { | ||||||
router: self, | ||||||
api, | ||||||
storage, | ||||||
block_info, | ||||||
} | ||||||
|
@@ -189,29 +197,31 @@ where | |||||
/// QuerierWrapper to interact with | ||||||
pub fn query( | ||||||
&self, | ||||||
api: &dyn Api, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great solution to this problem... pass it in! |
||||||
storage: &dyn Storage, | ||||||
block: &BlockInfo, | ||||||
request: QueryRequest<Empty>, | ||||||
) -> Result<Binary, String> { | ||||||
match request { | ||||||
QueryRequest::Wasm(req) => { | ||||||
self.wasm | ||||||
.query(storage, &self.querier(storage, block), block, req) | ||||||
.query(api, storage, &self.querier(api, storage, block), block, req) | ||||||
} | ||||||
QueryRequest::Bank(req) => self.bank.query(storage, req), | ||||||
QueryRequest::Bank(req) => self.bank.query(api, storage, req), | ||||||
_ => unimplemented!(), | ||||||
} | ||||||
} | ||||||
|
||||||
pub fn execute( | ||||||
&self, | ||||||
api: &dyn Api, | ||||||
storage: &mut dyn Storage, | ||||||
block: &BlockInfo, | ||||||
sender: Addr, | ||||||
msg: CosmosMsg<C>, | ||||||
) -> Result<AppResponse, String> { | ||||||
match msg { | ||||||
CosmosMsg::Wasm(msg) => self.wasm.execute(storage, &self, block, sender, msg), | ||||||
CosmosMsg::Wasm(msg) => self.wasm.execute(api, storage, &self, block, sender, msg), | ||||||
CosmosMsg::Bank(msg) => self.bank.execute(storage, sender, msg), | ||||||
_ => unimplemented!(), | ||||||
} | ||||||
|
@@ -223,16 +233,23 @@ where | |||||
C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, | ||||||
{ | ||||||
router: &'a Router<C>, | ||||||
api: &'a dyn Api, | ||||||
storage: &'a dyn Storage, | ||||||
block_info: &'a BlockInfo, | ||||||
} | ||||||
impl<'a, C> RouterQuerier<'a, C> | ||||||
where | ||||||
C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, | ||||||
{ | ||||||
pub fn new(router: &'a Router<C>, storage: &'a dyn Storage, block_info: &'a BlockInfo) -> Self { | ||||||
pub fn new( | ||||||
router: &'a Router<C>, | ||||||
api: &'a dyn Api, | ||||||
storage: &'a dyn Storage, | ||||||
block_info: &'a BlockInfo, | ||||||
) -> Self { | ||||||
Self { | ||||||
router, | ||||||
api, | ||||||
storage, | ||||||
block_info, | ||||||
} | ||||||
|
@@ -256,7 +273,7 @@ where | |||||
}; | ||||||
let contract_result: ContractResult<Binary> = self | ||||||
.router | ||||||
.query(self.storage, self.block_info, request) | ||||||
.query(self.api, self.storage, self.block_info, request) | ||||||
.into(); | ||||||
SystemResult::Ok(contract_result) | ||||||
} | ||||||
|
@@ -278,18 +295,18 @@ mod test { | |||||
|
||||||
fn mock_app() -> App { | ||||||
let env = mock_env(); | ||||||
let api = Box::new(MockApi::default()); | ||||||
let api = MockApi::default(); | ||||||
let bank = BankKeeper::new(); | ||||||
|
||||||
App::new(api, env.block, bank, Box::new(MockStorage::new())) | ||||||
App::new(api, env.block, bank, MockStorage::new()) | ||||||
} | ||||||
|
||||||
fn custom_app() -> App<CustomMsg> { | ||||||
let env = mock_env(); | ||||||
let api = Box::new(MockApi::default()); | ||||||
let api = MockApi::default(); | ||||||
let bank = BankKeeper::new(); | ||||||
|
||||||
App::new(api, env.block, bank, Box::new(MockStorage::new())) | ||||||
App::new(api, env.block, bank, MockStorage::new()) | ||||||
} | ||||||
|
||||||
fn get_balance<C>(app: &App<C>, addr: &Addr) -> Vec<Coin> | ||||||
|
@@ -717,14 +734,19 @@ mod test { | |||||
// TODO: check error? | ||||||
} | ||||||
|
||||||
fn query_router<C>(router: &Router<C>, storage: &dyn Storage, rcpt: &Addr) -> Vec<Coin> | ||||||
fn query_router<C>( | ||||||
router: &Router<C>, | ||||||
api: &dyn Api, | ||||||
storage: &dyn Storage, | ||||||
rcpt: &Addr, | ||||||
) -> Vec<Coin> | ||||||
where | ||||||
C: Clone + fmt::Debug + PartialEq + JsonSchema, | ||||||
{ | ||||||
let query = BankQuery::AllBalances { | ||||||
address: rcpt.into(), | ||||||
}; | ||||||
let res = router.bank.query(storage, query).unwrap(); | ||||||
let res = router.bank.query(api, storage, query).unwrap(); | ||||||
let val: AllBalanceResponse = from_slice(&res).unwrap(); | ||||||
val.amount | ||||||
} | ||||||
|
@@ -758,11 +780,17 @@ mod test { | |||||
amount: coins(25, "eth"), | ||||||
}; | ||||||
app.router | ||||||
.execute(&mut cache, &app.block, owner.clone(), msg.into()) | ||||||
.execute( | ||||||
app.api.as_ref(), | ||||||
&mut cache, | ||||||
&app.block, | ||||||
owner.clone(), | ||||||
msg.into(), | ||||||
) | ||||||
.unwrap(); | ||||||
|
||||||
// shows up in cache | ||||||
let cached_rcpt = query_router(&app.router, &cache, &rcpt); | ||||||
let cached_rcpt = query_router(&app.router, app.api.as_ref(), &cache, &rcpt); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
here and elsewhere? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Honestly I personally find There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's OK. It just seems nice to me to have all parameters referenced in more or less the same way (with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then I will change it, I somehow agree with you. Today I was working on other think at afternoon, but I will do it as first thing at the morning an merge this (as you approved I assume there are no other issues). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Either way. I'll defer to both your judgement for handling boxes (feel free to update other usages if desired... maybe as a separate PR) |
||||||
assert_eq!(coins(25, "eth"), cached_rcpt); | ||||||
let router_rcpt = query_app(&app, &rcpt); | ||||||
assert_eq!(router_rcpt, vec![]); | ||||||
|
@@ -774,13 +802,13 @@ mod test { | |||||
amount: coins(12, "eth"), | ||||||
}; | ||||||
app.router | ||||||
.execute(cache2, &app.block, owner, msg.into()) | ||||||
.execute(app.api.as_ref(), cache2, &app.block, owner, msg.into()) | ||||||
.unwrap(); | ||||||
|
||||||
// shows up in 2nd cache | ||||||
let cached_rcpt = query_router(&app.router, read, &rcpt); | ||||||
let cached_rcpt = query_router(&app.router, app.api.as_ref(), read, &rcpt); | ||||||
assert_eq!(coins(25, "eth"), cached_rcpt); | ||||||
let cached2_rcpt = query_router(&app.router, cache2, &rcpt); | ||||||
let cached2_rcpt = query_router(&app.router, app.api.as_ref(), cache2, &rcpt); | ||||||
assert_eq!(coins(37, "eth"), cached2_rcpt); | ||||||
Ok(()) | ||||||
}) | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice to remove Box from the public API. Better this way.
(And on reflection from you, I think maybe generics for eg. Bank implementation makes sense.. but that is a different refactor).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would actually prefer to be generic over all those things (like
Api
andStorage
), as internal optimizer tells me there is additional overhead of v-call here, but... come on, those are tests. This makes usage easier, as additional type hints are never an issue. I would not do that unless there is an actual need (I found sometimes dyn traits doesn't play well with typesystem, but I don't think here is a case).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you look at
Deps
andDepsMut
we usedyn
forStorage
,Api
andQuerier
. That change was made in 0.10 or 0.11. This made writing contracts much, much easier, especially for Rust newcomers.I am very happy with that and would avoid re-introducing generics there. But for all other types, I am open. I just got in the habit after seeing how much that simplified the code.