From 33630d5257a3c4a391703a3f505c837228e95615 Mon Sep 17 00:00:00 2001 From: Hugo Trentesaux <hugo.trentesaux@lilo.org> Date: Wed, 15 Jun 2022 23:00:56 +0200 Subject: [PATCH] tests(cucumber): add certification (!56) * tests(cucumber): improve regex * tests(cucumber): add certification --- Cargo.lock | 1 + end2end-tests/Cargo.toml | 1 + .../cucumber-features/certification.feature | 12 ++++ end2end-tests/cucumber-genesis/wot.json | 66 +++++++++++++++++++ end2end-tests/tests/common/cert.rs | 43 ++++++++++++ end2end-tests/tests/common/mod.rs | 2 + end2end-tests/tests/cucumber_tests.rs | 61 ++++++++++++++++- 7 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 end2end-tests/cucumber-features/certification.feature create mode 100644 end2end-tests/cucumber-genesis/wot.json create mode 100644 end2end-tests/tests/common/cert.rs diff --git a/Cargo.lock b/Cargo.lock index f7fbb6a6a..3908137f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1517,6 +1517,7 @@ dependencies = [ name = "duniter-end2end-tests" version = "3.0.0" dependencies = [ + "anyhow", "async-trait", "clap", "ctrlc", diff --git a/end2end-tests/Cargo.toml b/end2end-tests/Cargo.toml index 8d7b445ee..09aae7a49 100644 --- a/end2end-tests/Cargo.toml +++ b/end2end-tests/Cargo.toml @@ -9,6 +9,7 @@ repository = 'https://git.duniter.org/nodes/rust/duniter-v2s' version = '3.0.0' [dev-dependencies] +anyhow = "1.0" async-trait = "0.1" clap = { version = "3.0", features = ["derive"] } ctrlc = "3.2.2" diff --git a/end2end-tests/cucumber-features/certification.feature b/end2end-tests/cucumber-features/certification.feature new file mode 100644 index 000000000..4f749bece --- /dev/null +++ b/end2end-tests/cucumber-features/certification.feature @@ -0,0 +1,12 @@ +@genesis.wot + +Feature: Certification + + Scenario: Dave certifies Alice + When dave certifies alice + Then alice should be certified by dave + + @ignoreErrors + Scenario: Dave certifies Alice (but dave is not certified by charlie, this test should fail) + When dave certifies alice + Then dave should be certified by charlie \ No newline at end of file diff --git a/end2end-tests/cucumber-genesis/wot.json b/end2end-tests/cucumber-genesis/wot.json new file mode 100644 index 000000000..988e6857f --- /dev/null +++ b/end2end-tests/cucumber-genesis/wot.json @@ -0,0 +1,66 @@ +{ + "first_ud": 1000, + "first_ud_reeval": 100, + "identities": { + "Alice": { + "balance": 1000, + "certs": ["Bob", "Charlie", "Dave"], + "pubkey": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + }, + "Bob": { + "balance": 1000, + "certs": ["Alice", "Charlie", "Dave"], + "pubkey": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" + }, + "Charlie": { + "balance": 1000, + "certs": ["Alice", "Bob"], + "pubkey": "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y" + }, + "Dave": { + "balance": 1000, + "certs": [], + "pubkey": "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy" + } + }, + "parameters": { + "babe_epoch_duration": 30, + "cert_period": 15, + "cert_max_by_issuer": 10, + "cert_min_received_cert_to_issue_cert": 2, + "cert_renewable_period": 50, + "cert_validity_period": 1000, + "idty_confirm_period": 40, + "idty_creation_period": 50, + "membership_period": 1000, + "membership_renewable_period": 50, + "pending_membership_period": 500, + "ud_creation_period": 10, + "ud_reeval_period": 100, + "smith_cert_period": 15, + "smith_cert_max_by_issuer": 8, + "smith_cert_min_received_cert_to_issue_cert": 2, + "smith_cert_renewable_period": 50, + "smith_cert_validity_period": 1000, + "smith_membership_period": 1000, + "smith_membership_renewable_period": 20, + "smith_pending_membership_period": 500, + "smiths_wot_first_cert_issuable_on": 20, + "smiths_wot_min_cert_for_membership": 2, + "wot_first_cert_issuable_on": 20, + "wot_min_cert_for_create_idty_right": 2, + "wot_min_cert_for_membership": 2 + }, + "smiths": { + "Alice": { + "certs": ["Bob", "Charlie"] + }, + "Bob": { + "certs": ["Alice", "Charlie"] + }, + "Charlie": { + "certs": ["Alice", "Bob"] + } + }, + "sudo_key": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" +} diff --git a/end2end-tests/tests/common/cert.rs b/end2end-tests/tests/common/cert.rs new file mode 100644 index 000000000..021dfa2ea --- /dev/null +++ b/end2end-tests/tests/common/cert.rs @@ -0,0 +1,43 @@ +// Copyright 2021 Axiom-Team +// +// This file is part of Substrate-Libre-Currency. +// +// Substrate-Libre-Currency is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// Substrate-Libre-Currency is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. + +use super::node_runtime::runtime_types::gdev_runtime; +use super::node_runtime::runtime_types::pallet_certification; +use super::*; +use sp_keyring::AccountKeyring; +use subxt::{sp_runtime::MultiAddress, PairSigner}; + +pub async fn certify( + api: &Api, + client: &Client, + from: AccountKeyring, + to: AccountKeyring, +) -> Result<()> { + let from = PairSigner::new(from.pair()); + let to = to.to_account_id(); + + let _events = create_block_with_extrinsic( + client, + api.tx() + .cert() + .add_cert(to) + .create_signed(&from, ()) + .await?, + ) + .await?; + + Ok(()) +} diff --git a/end2end-tests/tests/common/mod.rs b/end2end-tests/tests/common/mod.rs index 078abd747..c3d53e9d6 100644 --- a/end2end-tests/tests/common/mod.rs +++ b/end2end-tests/tests/common/mod.rs @@ -17,10 +17,12 @@ #![allow(clippy::enum_variant_names, dead_code, unused_imports)] pub mod balances; +pub mod cert; #[subxt::subxt(runtime_metadata_path = "../resources/metadata.scale")] pub mod node_runtime {} +use anyhow::anyhow; use serde_json::Value; use sp_keyring::AccountKeyring; use std::io::prelude::*; diff --git a/end2end-tests/tests/cucumber_tests.rs b/end2end-tests/tests/cucumber_tests.rs index 09913a11e..13d88217d 100644 --- a/end2end-tests/tests/cucumber_tests.rs +++ b/end2end-tests/tests/cucumber_tests.rs @@ -28,6 +28,8 @@ use std::sync::{ Arc, }; +// ===== world ===== + #[derive(WorldInit)] pub struct DuniterWorld { ignore_errors: bool, @@ -119,6 +121,8 @@ fn parse_amount(amount: u64, unit: &str) -> (u64, bool) { } } +// ===== given ===== + #[given(regex = r"([a-zA-Z]+) ha(?:ve|s) (\d+) (ÄžD|cÄžD|UD|mUD)")] async fn who_have(world: &mut DuniterWorld, who: String, amount: u64, unit: String) -> Result<()> { // Parse inputs @@ -141,6 +145,8 @@ async fn who_have(world: &mut DuniterWorld, who: String, amount: u64, unit: Stri Ok(()) } +// ===== when ===== + #[when(regex = r"(\d+) blocks? later")] async fn n_blocks_later(world: &mut DuniterWorld, n: usize) -> Result<()> { for _ in 0..n { @@ -175,7 +181,7 @@ async fn transfer( } } -#[when(regex = r"([a-zA-Z]+) sends all (?:his|her) (?:ÄžDs?|DUs?) to ([a-zA-Z]+)")] +#[when(regex = r"([a-zA-Z]+) sends? all (?:his|her) (?:ÄžDs?|DUs?|UDs?) to ([a-zA-Z]+)")] async fn send_all_to(world: &mut DuniterWorld, from: String, to: String) -> Result<()> { // Parse inputs let from = AccountKeyring::from_str(&from).expect("unknown from"); @@ -184,6 +190,17 @@ async fn send_all_to(world: &mut DuniterWorld, from: String, to: String) -> Resu common::balances::transfer_all(world.api(), world.client(), from, to).await } +#[when(regex = r"([a-zA-Z]+) certifies ([a-zA-Z]+)")] +async fn certifies(world: &mut DuniterWorld, from: String, to: String) -> Result<()> { + // Parse inputs + let from = AccountKeyring::from_str(&from).expect("unknown from"); + let to = AccountKeyring::from_str(&to).expect("unknown to"); + + common::cert::certify(world.api(), world.client(), from, to).await +} + +// ===== then ==== + #[then(regex = r"([a-zA-Z]+) should have (\d+) (ÄžD|cÄžD)")] async fn should_have( world: &mut DuniterWorld, @@ -232,6 +249,48 @@ async fn monetary_mass_should_be(world: &mut DuniterWorld, amount: u64, cents: u Ok(()) } +#[then(regex = r"([a-zA-Z]+) should be certified by ([a-zA-Z]+)")] +async fn should_be_certified_by( + world: &mut DuniterWorld, + receiver: String, + issuer: String, +) -> Result<()> { + // Parse inputs + let receiver_account = AccountKeyring::from_str(&receiver) + .expect("unknown to") + .to_account_id(); + let issuer_account = AccountKeyring::from_str(&issuer) + .expect("unknown to") + .to_account_id(); + + let issuer_index = world + .api() + .storage() + .identity() + .identity_index_of(issuer_account, None) + .await? + .unwrap(); + let receiver_index = world + .api() + .storage() + .identity() + .identity_index_of(receiver_account, None) + .await? + .unwrap(); + + let _certification = world + .api() + .storage() + .cert() + .storage_certs_by_issuer(issuer_index, receiver_index, None) + .await? + .ok_or_else(|| anyhow::anyhow!("no certification found from {} to {}", issuer, receiver))?; + + Ok(()) +} + +// ============================================================ + #[derive(clap::Args)] struct CustomOpts { /// Keep running -- GitLab