Skip to content
Snippets Groups Projects
Commit 2d2799e3 authored by Éloïs's avatar Éloïs
Browse files

fix(gdev): add constant tx fees (2 cents by tx) to prevent #62

Fix #62
parent 38690cfe
No related branches found
No related tags found
1 merge request!63fix(gdev): add constant tx fees (2 cents by tx) to prevent #62
# Duniter-v2s integration tests
# Duniter-v2s end2end tests
## cucumber functionnal tests
......@@ -47,37 +47,9 @@ Feature: My awesome feature
Then We should observe that
```
### Test users
6 test users are provided:
- alice
- bob
- charlie
- dave
- eve
- ferdie
### genesis state
Each scenario bootstraps its own blockchain with its own genesis state.
By default, all scenarios use the same configuration for the genesis, which is located in the file
`/cucumber-genesis/default.json`.
### Steps
You can define a custom genesis state for each scenario with the tag `@genesis.confName`.
The genesis configuration must then be defined in a json file located at
`/cucumber-genesis/confName.json`.
You can also define a custom genesis at the feature level, all the scenarios of this feature will
then inherit the genesis configuration.
### Currency amounts
Amounts must be expressed as an integer of `ĞD` or `UD`, decimal numbers are not supported.
If you need more precision, you can express amounts in cents of ĞD (write `cĞD`), or in thousandths
of UD (write `mUD`).
Each scenario is a list of steps. In our context (blockchain), only the `When` and `Then` steps make sense, `Given` being the genesis.
#### When
......@@ -95,23 +67,54 @@ List of possible actions:
Example: `alice should have 10 ĞD`
### Universal dividend creation
#### Then
- Check the current UD amount
Usage: `Current UD amount should be {amount}.{cents} ĞD`
Example: `Current UD amount should be 10.00 ĞD`
- Check the monetary mass
Usage: `Monetary mass should be {amount}.{cents} ĞD`
Example: `Monetary mass should be 30.00 ĞD`
### Test users
6 test users are provided:
- alice
- bob
- charlie
- dave
- eve
- ferdie
### Currency amounts
Amounts must be expressed as an integer of `ĞD` or `UD`, decimal numbers are not supported.
If you need more precision, you can express amounts in cents of ĞD (write `cĞD`), or in thousandths
of UD (write `mUD`).
### genesis state
Each scenario bootstraps its own blockchain with its own genesis state.
By default, all scenarios use the same configuration for the genesis, which is located in the file
`/cucumber-genesis/default.json`.
You can define a custom genesis state for each scenario with the tag `@genesis.confName`.
The genesis configuration must then be defined in a json file located at
`/cucumber-genesis/confName.json`.
You can also define a custom genesis at the feature level, all the scenarios of this feature will
then inherit the genesis configuration.
### ignoreErrors
For some scenarios, you may need to perform an action (When) that fails voluntarily, in this case you must add the tag @ignoreErrors to your scenario, otherwise it will be considered as failed
### Run cucumber functional tests
To run the cucumber tests, you will need to have the rust toolchain installed locally.
......
......@@ -26,6 +26,7 @@ Feature: Balance transfer
"""
Then eve should have 2 ĞD
@ignoreErrors
Scenario: Create a new account without any founds
Then eve should have 0 ĞD
When eve send 0 ĞD to alice
......
@genesis.default
Feature: Balance transfer all
Scenario: If alice sends all her ĞDs to Dave, Dave will get 8 ĞD
When alice sends all her ĞDs to dave
Scenario: If bob sends all his ĞDs to Dave
When bob sends all her ĞDs to dave
"""
Alice is a smith member, as such she is not allowed to empty her account completely,
if she tries to do so, the existence deposit (2 ĞD) must remain.
Bob is a member, as such he is not allowed to empty his account completely,
if he tries to do so, the existence deposit (2 ĞD) must remain.
"""
Then alice should have 2 ĞD
Then dave should have 8 ĞD
Then bob should have 2 ĞD
"""
10 ĞD (initial Bob balance) - 2 ĞD (Existential deposit) - 0.02 ĞD (transaction fees)
"""
Then dave should have 798 cĞD
......@@ -29,33 +29,44 @@ use std::sync::{
};
#[derive(WorldInit)]
pub struct DuniterWorld(Option<DuniterWorldInner>);
pub struct DuniterWorld {
ignore_errors: bool,
inner: Option<DuniterWorldInner>,
}
impl DuniterWorld {
// Write methods
async fn init(&mut self, maybe_genesis_conf_file: Option<PathBuf>) {
if let Some(ref mut inner) = self.0 {
if let Some(ref mut inner) = self.inner {
inner.kill();
}
self.inner = Some(DuniterWorldInner::new(maybe_genesis_conf_file).await);
}
fn kill(&mut self) {
if let Some(ref mut inner) = self.inner {
inner.kill();
}
self.0 = Some(DuniterWorldInner::new(maybe_genesis_conf_file).await);
}
fn set_ignore_errors(&mut self, ignore_errors: bool) {
self.ignore_errors = ignore_errors;
}
// Read methods
fn api(&self) -> &Api {
if let Some(ref inner) = self.0 {
if let Some(ref inner) = self.inner {
&inner.api
} else {
panic!("uninit")
}
}
fn client(&self) -> &Client {
if let Some(ref inner) = self.0 {
if let Some(ref inner) = self.inner {
&inner.client
} else {
panic!("uninit")
}
}
fn kill(&mut self) {
if let Some(ref mut inner) = self.0 {
inner.kill();
}
fn ignore_errors(&self) -> bool {
self.ignore_errors
}
}
......@@ -71,7 +82,10 @@ impl World for DuniterWorld {
type Error = Infallible;
async fn new() -> std::result::Result<Self, Infallible> {
Ok(DuniterWorld(None))
Ok(Self {
ignore_errors: false,
inner: None,
})
}
}
......@@ -148,10 +162,16 @@ async fn transfer(
let to = AccountKeyring::from_str(&to).expect("unknown to");
let (amount, is_ud) = parse_amount(amount, &unit);
if is_ud {
let res = if is_ud {
common::balances::transfer_ud(world.api(), world.client(), from, amount, to).await
} else {
common::balances::transfer(world.api(), world.client(), from, amount, to).await
};
if world.ignore_errors() {
Ok(())
} else {
res
}
}
......@@ -164,13 +184,18 @@ async fn send_all_to(world: &mut DuniterWorld, from: String, to: String) -> Resu
common::balances::transfer_all(world.api(), world.client(), from, to).await
}
#[then(regex = r"([a-zA-Z]+) should have (\d+) ĞD")]
async fn should_have(world: &mut DuniterWorld, who: String, amount: u64) -> Result<()> {
#[then(regex = r"([a-zA-Z]+) should have (\d+) (ĞD|cĞD)")]
async fn should_have(
world: &mut DuniterWorld,
who: String,
amount: u64,
unit: String,
) -> Result<()> {
// Parse inputs
let who = AccountKeyring::from_str(&who)
.expect("unknown to")
.to_account_id();
let amount = amount * 100;
let (amount, _is_ud) = parse_amount(amount, &unit);
let who_account = world.api().storage().system().account(who, None).await?;
assert_eq!(who_account.data.free, amount);
......@@ -250,6 +275,7 @@ async fn main() {
"{}.json",
genesis_conf_name(&feature.tags, &scenario.tags)
));
world.set_ignore_errors(ignore_errors(&scenario.tags));
Box::pin(world.init(Some(genesis_conf_file_path)))
})
.after(move |_feature, _rule, _scenario, maybe_world| {
......@@ -280,3 +306,12 @@ fn genesis_conf_name(feature_tags: &[String], scenario_tags: &[String]) -> Strin
}
"default".to_owned()
}
fn ignore_errors(scenario_tags: &[String]) -> bool {
for tag in scenario_tags {
if tag == "ignoreErrors" {
return true;
}
}
false
}
......@@ -17,7 +17,7 @@
pub use frame_support::weights::{
Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial,
};
use sp_arithmetic::traits::{BaseArithmetic, Unsigned, Zero};
use sp_arithmetic::traits::{BaseArithmetic, One, Unsigned};
pub struct WeightToFeeImpl<T>(sp_std::marker::PhantomData<T>);
......@@ -35,8 +35,8 @@ where
degree: 1,
})
}
// Force disable fees
// Force constant fees
fn calc(_weight: &Weight) -> Self::Balance {
Zero::zero()
One::one()
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment