From 93e684b4a3c3c8dba2fd7f26f16273f0ce39552a Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Tue, 27 Aug 2024 14:53:50 +0300 Subject: [PATCH] feat(gtest): Introduce auxiliary waitlist impl to `gtest` (#4193) --- common/src/auxiliary/mod.rs | 1 + common/src/auxiliary/waitlist.rs | 84 ++++++++++++++++++++++++++++++++ gtest/src/blocks.rs | 16 +++++- gtest/src/gas_tree.rs | 2 +- gtest/src/lib.rs | 1 + gtest/src/mailbox/manager.rs | 17 ++----- gtest/src/task_pool.rs | 2 +- gtest/src/waitlist.rs | 81 ++++++++++++++++++++++++++++++ 8 files changed, 186 insertions(+), 18 deletions(-) create mode 100644 common/src/auxiliary/waitlist.rs create mode 100644 gtest/src/waitlist.rs diff --git a/common/src/auxiliary/mod.rs b/common/src/auxiliary/mod.rs index 1c2aa1fe26f..0e9c36990e8 100644 --- a/common/src/auxiliary/mod.rs +++ b/common/src/auxiliary/mod.rs @@ -23,6 +23,7 @@ pub mod gas_provider; pub mod mailbox; pub mod task_pool; +pub mod waitlist; use crate::storage::{ Counted, CountedByKey, DoubleMapStorage, GetFirstPos, GetSecondPos, IterableByKeyMap, diff --git a/common/src/auxiliary/waitlist.rs b/common/src/auxiliary/waitlist.rs new file mode 100644 index 00000000000..81c746d11fd --- /dev/null +++ b/common/src/auxiliary/waitlist.rs @@ -0,0 +1,84 @@ +// This file is part of Gear. + +// Copyright (C) 2021-2024 Gear Technologies Inc. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program 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 General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Auxiliary implementation of the waitlist. + +use super::{AuxiliaryDoubleStorageWrap, BlockNumber, DoubleBTreeMap}; +use crate::storage::{Interval, WaitlistError, WaitlistImpl, WaitlistKeyGen}; +use core::cell::RefCell; +use gear_core::{ + ids::{MessageId, ProgramId}, + message::StoredDispatch, +}; + +/// Waitlist implementation that can be used in a native, non-wasm runtimes. +pub type AuxiliaryWaitlist = WaitlistImpl< + WaitlistStorageWrap, + WaitlistedMessage, + BlockNumber, + WaitlistErrorImpl, + WaitlistErrorImpl, + WaitListCallbacks, + WaitlistKeyGen, +>; +/// Type represents message stored in the waitlist. +pub type WaitlistedMessage = StoredDispatch; + +std::thread_local! { + // Definition of the waitlist (`StorageDoubleMap`) global storage, accessed by the `Waitlist` trait implementor. + pub(crate) static WAITLIST_STORAGE: RefCell)>> = const { RefCell::new(DoubleBTreeMap::new()) }; +} + +/// `Waitlist` double storage map manager. +pub struct WaitlistStorageWrap; + +impl AuxiliaryDoubleStorageWrap for WaitlistStorageWrap { + type Key1 = ProgramId; + type Key2 = MessageId; + type Value = (WaitlistedMessage, Interval); + + fn with_storage(f: F) -> R + where + F: FnOnce(&DoubleBTreeMap) -> R, + { + WAITLIST_STORAGE.with_borrow(f) + } + + fn with_storage_mut(f: F) -> R + where + F: FnOnce(&mut DoubleBTreeMap) -> R, + { + WAITLIST_STORAGE.with_borrow_mut(f) + } +} + +/// An implementor of the error returned from calling `Waitlist` trait functions +pub enum WaitlistErrorImpl { + DuplicateKey, + ElementNotFound, +} + +impl WaitlistError for WaitlistErrorImpl { + fn duplicate_key() -> Self { + Self::DuplicateKey + } + + fn element_not_found() -> Self { + Self::ElementNotFound + } +} diff --git a/gtest/src/blocks.rs b/gtest/src/blocks.rs index 1e4b593e792..dce699bec87 100644 --- a/gtest/src/blocks.rs +++ b/gtest/src/blocks.rs @@ -18,15 +18,15 @@ //! Block timestamp and height management. +use crate::BLOCK_DURATION_IN_MSECS; use core_processor::configs::BlockInfo; +use gear_common::{auxiliary::BlockNumber, storage::GetCallback}; use std::{ cell::RefCell, rc::Rc, time::{SystemTime, UNIX_EPOCH}, }; -use crate::BLOCK_DURATION_IN_MSECS; - type BlockInfoStorageInner = Rc>>; thread_local! { @@ -115,6 +115,18 @@ fn now() -> u64 { .as_millis() as u64 } +/// Block number getter. +/// +/// Used to get block number for auxiliary complex storage managers, +/// like auxiliary maibox, waitlist and etc. +pub(crate) struct GetBlockNumberImpl; + +impl GetCallback for GetBlockNumberImpl { + fn call() -> BlockNumber { + BlocksManager::new().get().height + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/gtest/src/gas_tree.rs b/gtest/src/gas_tree.rs index a362170424c..422ba87f4d1 100644 --- a/gtest/src/gas_tree.rs +++ b/gtest/src/gas_tree.rs @@ -36,7 +36,7 @@ pub type OriginNodeDataOf = ( type GasTree = ::GasTree; /// Gas tree manager which operates under the hood over -/// [`gear_common::AuxiliaryGasProvider`]. +/// [`gear_common::auxiliary::gas_provider::AuxiliaryGasProvider`]. /// /// Manager is needed mainly to adapt arguments of the gas tree methods to the /// crate. diff --git a/gtest/src/lib.rs b/gtest/src/lib.rs index dec27bb58b7..3fdbdbaf188 100644 --- a/gtest/src/lib.rs +++ b/gtest/src/lib.rs @@ -504,6 +504,7 @@ mod manager; mod program; mod system; mod task_pool; +mod waitlist; pub use crate::log::{BlockRunResult, CoreLog, Log}; pub use codec; diff --git a/gtest/src/mailbox/manager.rs b/gtest/src/mailbox/manager.rs index 32582adf4d9..b0791569fbe 100644 --- a/gtest/src/mailbox/manager.rs +++ b/gtest/src/mailbox/manager.rs @@ -18,15 +18,15 @@ //! Mailbox manager. -use crate::blocks::BlocksManager; +use crate::blocks::GetBlockNumberImpl; use gear_common::{ auxiliary::{mailbox::*, BlockNumber}, - storage::{GetCallback, Interval, IterableByKeyMap, Mailbox, MailboxCallbacks}, + storage::{Interval, IterableByKeyMap, Mailbox, MailboxCallbacks}, }; use gear_core::ids::{MessageId, ProgramId}; /// Mailbox manager which operates under the hood over -/// [`gear_common::AuxiliaryMailbox`]. +/// [`gear_common::auxiliary::mailbox::AuxiliaryMailbox`]. #[derive(Debug, Default)] pub(crate) struct MailboxManager; @@ -80,14 +80,3 @@ impl MailboxCallbacks for MailboxCallbacksImpl { type OnInsert = (); type OnRemove = (); } - -/// Block number getter. -/// -/// Used to get block number to insert message into mailbox. -pub(crate) struct GetBlockNumberImpl; - -impl GetCallback for GetBlockNumberImpl { - fn call() -> BlockNumber { - BlocksManager::new().get().height - } -} diff --git a/gtest/src/task_pool.rs b/gtest/src/task_pool.rs index f61cb6cd6d7..edf51c89405 100644 --- a/gtest/src/task_pool.rs +++ b/gtest/src/task_pool.rs @@ -29,7 +29,7 @@ use gear_common::{ }; /// Task pool manager which operates under the hood over -/// [`gear_common::AuxiliaryTaskpool`]. +/// [`gear_common::auxiliary::task_pool::AuxiliaryTaskpool`]. /// /// Manager is needed mainly to adapt arguments of the task pool methods to the /// crate. diff --git a/gtest/src/waitlist.rs b/gtest/src/waitlist.rs new file mode 100644 index 00000000000..3145ea064d3 --- /dev/null +++ b/gtest/src/waitlist.rs @@ -0,0 +1,81 @@ +// This file is part of Gear. + +// Copyright (C) 2024 Gear Technologies Inc. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program 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 General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Waitlist manager. + +#![allow(unused)] + +use crate::blocks::GetBlockNumberImpl; +use gear_common::{ + auxiliary::{waitlist::*, BlockNumber}, + storage::{Interval, IterableByKeyMap, Waitlist, WaitlistCallbacks}, +}; +use gear_core::ids::{MessageId, ProgramId}; + +/// Waitlist manager which operates under the hood over +/// [`gear_common::auxiliary::waitlist::AuxiliaryWaitlist`]. +#[derive(Debug, Default)] +pub(crate) struct WaitlistManager; + +impl WaitlistManager { + /// Check if message with `message_id` to a program with `program_id` is in + /// the waitlist. + pub(crate) fn contains(program_id: ProgramId, message_id: MessageId) -> bool { + as Waitlist>::contains(&program_id, &message_id) + } + + /// Insert message into waitlist. + pub(crate) fn insert( + &self, + message: WaitlistedMessage, + expected: BlockNumber, + ) -> Result<(), WaitlistErrorImpl> { + as Waitlist>::insert(message, expected) + } + + /// Remove message from the waitlist. + pub(crate) fn remove( + &self, + program_id: ProgramId, + message_id: MessageId, + ) -> Result<(WaitlistedMessage, Interval), WaitlistErrorImpl> { + as Waitlist>::remove(program_id, message_id) + } + + /// Fully reset waitlist. + /// + /// # Note: + /// Must be called by `WaitlistManager` owner to reset waitlist + /// when the owner is dropped. + pub(crate) fn reset(&self) { + as Waitlist>::clear(); + } +} + +/// Waitlist callbacks implementor. +pub(crate) struct WaitlistCallbacksImpl; + +impl WaitlistCallbacks for WaitlistCallbacksImpl { + type Value = WaitlistedMessage; + type BlockNumber = BlockNumber; + + type GetBlockNumber = GetBlockNumberImpl; + + type OnInsert = (); + type OnRemove = (); +}