Skip to content

Commit

Permalink
Update env version in SDK. (#1062)
Browse files Browse the repository at this point in the history
### What

Update env version in SDK.

Also add more tests to cover instance-related fixes.

### Why

Improving test utils.

### Known limitations

N/A
  • Loading branch information
dmkozh authored Aug 22, 2023
1 parent d8bd392 commit 9d4fe53
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 35 deletions.
44 changes: 21 additions & 23 deletions soroban-sdk/src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
};

use super::{
env::internal::{Env as _, EnvBase as _, MapObject},
env::internal::{Env as _, EnvBase as _, MapObject, U32Val},
ConversionError, Env, IntoVal, TryFromVal, TryIntoVal, Val, Vec,
};

Expand Down Expand Up @@ -508,15 +508,15 @@ where
#[derive(Clone)]
pub struct MapTryIter<K, V> {
map: Map<K, V>,
pos: u32,
len: u32,
begin: u32,
end: u32,
}

impl<K, V> MapTryIter<K, V> {
fn new(map: Map<K, V>) -> Self {
Self {
pos: 0,
len: map.len(),
begin: 0,
end: map.len(),
map,
}
}
Expand All @@ -531,16 +531,15 @@ where

fn next(&mut self) -> Option<Self::Item> {
let env = self.map.env();
if self.pos == self.len {
if self.begin >= self.end {
return None;
}
let key = env
.map_key_by_pos(self.map.to_object(), self.pos.into())
.unwrap_infallible();
let value = env
.map_val_by_pos(self.map.to_object(), self.pos.into())
.unwrap_infallible();
self.pos += 1;
let map_obj = self.map.to_object();
let index_val: U32Val = self.begin.into();
let key = env.map_key_by_pos(map_obj, index_val).unwrap_infallible();
let value = env.map_val_by_pos(map_obj, index_val).unwrap_infallible();
self.begin += 1;

Some(Ok((
match K::try_from_val(env, &key) {
Ok(k) => k,
Expand All @@ -554,7 +553,7 @@ where
}

fn size_hint(&self) -> (usize, Option<usize>) {
let len = (self.len - self.pos) as usize;
let len = (self.end - self.begin) as usize;
(len, Some(len))
}

Expand All @@ -568,16 +567,15 @@ where
{
fn next_back(&mut self) -> Option<Self::Item> {
let env = self.map.env();
if self.pos == self.len {
if self.begin >= self.end {
return None;
}
self.len -= 1;
let key = env
.map_key_by_pos(self.map.to_object(), self.len.into())
.unwrap_infallible();
let value = env
.map_val_by_pos(self.map.to_object(), self.len.into())
.unwrap_infallible();
self.end -= 1;
let map_obj = self.map.to_object();
let index_val: U32Val = self.end.into();
let key = env.map_key_by_pos(map_obj, index_val).unwrap_infallible();
let value = env.map_val_by_pos(map_obj, index_val).unwrap_infallible();

Some(Ok((
match K::try_from_val(env, &key) {
Ok(k) => k,
Expand Down Expand Up @@ -606,7 +604,7 @@ where
V: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
fn len(&self) -> usize {
(self.len - self.pos) as usize
(self.end - self.begin) as usize
}
}

Expand Down
8 changes: 2 additions & 6 deletions soroban-sdk/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,14 +363,10 @@ impl Instance {
self.storage.remove(key, StorageType::Instance)
}

pub fn bump(&self, _min_ledgers_to_live: u32) {
// This is required because register_contract
// doesn't create an instance. This guard can be
// removed once that is fixed.
#[cfg(not(any(test, feature = "testutils")))]
pub fn bump(&self, min_ledgers_to_live: u32) {
internal::Env::bump_current_contract_instance_and_code(
&self.storage.env,
_min_ledgers_to_live.into(),
min_ledgers_to_live.into(),
)
.unwrap_infallible();
}
Expand Down
94 changes: 88 additions & 6 deletions soroban-sdk/src/tests/contract_store.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,50 @@
use crate::{self as soroban_sdk};
use soroban_sdk::{contract, contractimpl, Env};
use soroban_sdk::{contract, contractimpl, contracttype, Env};

#[contracttype]
enum DataKey {
Key(i32),
}

#[contract]
pub struct Contract;

#[contractimpl]
impl Contract {
pub fn store(env: Env, k: i32, v: i32) {
env.storage().persistent().set(&k, &v)
pub fn get_persistent(env: Env, k: i32) -> Option<i32> {
env.storage().persistent().get(&DataKey::Key(k))
}

pub fn set_persistent(env: Env, k: i32, v: i32) {
env.storage().persistent().set(&DataKey::Key(k), &v);
}

pub fn get_temporary(env: Env, k: i32) -> Option<i32> {
env.storage().temporary().get(&DataKey::Key(k))
}

pub fn set_temporary(env: Env, k: i32, v: i32) {
env.storage().temporary().set(&DataKey::Key(k), &v);
}

pub fn get_instance(env: Env, k: i32) -> Option<i32> {
env.storage().instance().get(&DataKey::Key(k))
}

pub fn set_instance(env: Env, k: i32, v: i32) {
env.storage().instance().set(&DataKey::Key(k), &v);
}

pub fn bump_persistent(env: Env, k: i32) {
env.storage().persistent().bump(&DataKey::Key(k), 100);
}

pub fn bump_temporary(env: Env, k: i32) {
env.storage().temporary().bump(&DataKey::Key(k), 100);
}

pub fn bump_instance(env: Env) {
env.storage().instance().bump(100);
}
}

Expand All @@ -17,10 +54,55 @@ fn test_storage() {
let contract_id = e.register_contract(None, Contract);
let client = ContractClient::new(&e, &contract_id);

client.store(&2, &4);
// Smoke test instance bump before putting any data into it.
client.bump_instance();

assert!(client.get_persistent(&11).is_none());
assert!(client.get_temporary(&11).is_none());
assert!(client.get_instance(&11).is_none());

// Setup the the storage with some values.
e.as_contract(&contract_id, || {
e.storage().persistent().set(&DataKey::Key(11), &1111_i32);
e.storage().temporary().set(&DataKey::Key(11), &2222_i32);
e.storage().instance().set(&DataKey::Key(11), &3333_i32);
});
assert_eq!(client.get_persistent(&11), Some(1111));
assert_eq!(client.get_temporary(&11), Some(2222));
assert_eq!(client.get_instance(&11), Some(3333));

client.set_persistent(&22, &111);
assert_eq!(client.get_persistent(&22), Some(111));
assert_eq!(
e.as_contract(&contract_id, || e.storage().persistent().get::<_, i32>(&2)),
Some(4)
e.as_contract(&contract_id, || e
.storage()
.persistent()
.get(&DataKey::Key(22))),
Some(111_i32)
);

client.set_temporary(&22, &222);
assert_eq!(client.get_temporary(&22), Some(222));
assert_eq!(
e.as_contract(&contract_id, || e
.storage()
.temporary()
.get(&DataKey::Key(22))),
Some(222_i32)
);

client.set_instance(&22, &333);
assert_eq!(client.get_instance(&22), Some(333));
assert_eq!(
e.as_contract(&contract_id, || e
.storage()
.instance()
.get(&DataKey::Key(22))),
Some(333_i32)
);

// Smoke test temp/persistent bumps. This can be enhanced when we provided
// expiration ledger getter for tests.
client.bump_persistent(&11);
client.bump_temporary(&11);
}

0 comments on commit 9d4fe53

Please sign in to comment.