Skip to content

Commit

Permalink
feat(gtest): Introduce auxiliary waitlist impl to gtest (#4193)
Browse files Browse the repository at this point in the history
  • Loading branch information
techraed authored Aug 27, 2024
1 parent 09977f4 commit 93e684b
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 18 deletions.
1 change: 1 addition & 0 deletions common/src/auxiliary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
84 changes: 84 additions & 0 deletions common/src/auxiliary/waitlist.rs
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

//! 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<WaitListCallbacks> = 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<DoubleBTreeMap<ProgramId, MessageId, (WaitlistedMessage, Interval<BlockNumber>)>> = 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<BlockNumber>);

fn with_storage<F, R>(f: F) -> R
where
F: FnOnce(&DoubleBTreeMap<Self::Key1, Self::Key2, Self::Value>) -> R,
{
WAITLIST_STORAGE.with_borrow(f)
}

fn with_storage_mut<F, R>(f: F) -> R
where
F: FnOnce(&mut DoubleBTreeMap<Self::Key1, Self::Key2, Self::Value>) -> 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
}
}
16 changes: 14 additions & 2 deletions gtest/src/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<RefCell<Option<BlockInfo>>>;

thread_local! {
Expand Down Expand Up @@ -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<BlockNumber> for GetBlockNumberImpl {
fn call() -> BlockNumber {
BlocksManager::new().get().height
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion gtest/src/gas_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub type OriginNodeDataOf = (
type GasTree = <AuxiliaryGasProvider as Provider>::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.
Expand Down
1 change: 1 addition & 0 deletions gtest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
17 changes: 3 additions & 14 deletions gtest/src/mailbox/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -80,14 +80,3 @@ impl MailboxCallbacks<MailboxErrorImpl> 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<BlockNumber> for GetBlockNumberImpl {
fn call() -> BlockNumber {
BlocksManager::new().get().height
}
}
2 changes: 1 addition & 1 deletion gtest/src/task_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
81 changes: 81 additions & 0 deletions gtest/src/waitlist.rs
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

//! 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 {
<AuxiliaryWaitlist<WaitlistCallbacksImpl> as Waitlist>::contains(&program_id, &message_id)
}

/// Insert message into waitlist.
pub(crate) fn insert(
&self,
message: WaitlistedMessage,
expected: BlockNumber,
) -> Result<(), WaitlistErrorImpl> {
<AuxiliaryWaitlist<WaitlistCallbacksImpl> as Waitlist>::insert(message, expected)
}

/// Remove message from the waitlist.
pub(crate) fn remove(
&self,
program_id: ProgramId,
message_id: MessageId,
) -> Result<(WaitlistedMessage, Interval<BlockNumber>), WaitlistErrorImpl> {
<AuxiliaryWaitlist<WaitlistCallbacksImpl> 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) {
<AuxiliaryWaitlist<WaitlistCallbacksImpl> 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 = ();
}

0 comments on commit 93e684b

Please sign in to comment.