Skip to content

Commit

Permalink
Merge pull request #67 from blockful-io/feat#18IntegratedTests
Browse files Browse the repository at this point in the history
Feat#18 integrated tests
  • Loading branch information
LeonardoVieira1630 authored Dec 24, 2024
2 parents e8e54fc + e26a3a4 commit 5b2b40a
Show file tree
Hide file tree
Showing 10 changed files with 457 additions and 103 deletions.
4 changes: 3 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ doctest = false

[dependencies]
soroban-sdk = { workspace = true }
scorer = { path = "contracts/scorer" }
scorer_factory = { path = "contracts/scorer_factory" }
deployer = { path = "contracts/deployer" }

[dev-dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
Expand Down
1 change: 0 additions & 1 deletion contracts/scorer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ testutils = []

[dependencies]
soroban-sdk = { workspace = true }
trustful-stellar-v1 = { path = "../.." }

[dev-dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
Expand Down
28 changes: 23 additions & 5 deletions contracts/scorer/src/scorer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,15 @@ impl ScorerContract {
// Ensure that the scorer creator is the sender
scorer_creator.require_auth();

// Create initial managers list with scorer_creator
let mut initial_managers = Vec::<Address>::new(&env);
initial_managers.push_back(scorer_creator.clone());

// Store initial state
env.storage().persistent().set(&DataKey::ScorerCreator, &scorer_creator);
env.storage().persistent().set(&DataKey::ScorerBadges, &scorer_badges);
env.storage().persistent().set(&DataKey::Users, &Map::<Address, bool>::new(&env));
env.storage().persistent().set(&DataKey::Managers, &Vec::<Address>::new(&env));
env.storage().persistent().set(&DataKey::Managers, &initial_managers);
env.storage().persistent().set(&DataKey::Initialized, &true);
}

Expand Down Expand Up @@ -223,6 +227,19 @@ impl ScorerContract {
pub fn get_users(env: Env) -> Map<Address, bool> {
env.storage().persistent().get::<DataKey, Map<Address, bool>>(&DataKey::Users).unwrap()
}

/// Retrieves all scorer badges from the contract's storage
///
/// # Arguments
/// * `env` - The environment object providing access to the contract's storage
///
/// # Returns
/// * `Map<u32, ScorerBadge>` - A map where:
/// - Key: Badge ID (u32)
/// - Value: ScorerBadge struct containing the badge details
pub fn get_badges(env: Env) -> Map<u32, ScorerBadge> {
env.storage().persistent().get::<DataKey, Map<u32, ScorerBadge>>(&DataKey::ScorerBadges).unwrap()
}
}

#[cfg(test)]
Expand Down Expand Up @@ -289,7 +306,7 @@ mod test {
env.storage().persistent().get::<DataKey, Vec<Address>>(&DataKey::Managers).unwrap()
});

assert_eq!(managers, Vec::from_slice(&env, &[new_manager]));
assert_eq!(managers, Vec::from_slice(&env, &[scorer_creator.clone(), new_manager]));
}

#[test]
Expand All @@ -303,7 +320,8 @@ mod test {
env.storage().persistent().get::<DataKey, Vec<Address>>(&DataKey::Managers).unwrap()
});

assert_eq!(managers, Vec::<Address>::new(&env));
// Only scorer_creator should remain
assert_eq!(managers, Vec::from_slice(&env, &[scorer_creator]));
}

#[test]
Expand Down Expand Up @@ -340,15 +358,15 @@ mod test {
env.storage().persistent().get::<DataKey, Vec<Address>>(&DataKey::Managers).unwrap()
});

assert_eq!(managers, Vec::from_slice(&env, &[manager1.clone(), manager2.clone(), manager3.clone()]));
assert_eq!(managers, Vec::from_slice(&env, &[scorer_creator.clone(), manager1.clone(), manager2.clone(), manager3.clone()]));

client.remove_manager(&scorer_creator, &manager2);

let managers_after_remove = env.as_contract(&client.address, || {
env.storage().persistent().get::<DataKey, Vec<Address>>(&DataKey::Managers).unwrap()
});

assert_eq!(managers_after_remove, Vec::from_slice(&env, &[manager1, manager3]));
assert_eq!(managers_after_remove, Vec::from_slice(&env, &[scorer_creator, manager1, manager3]));
}

#[test]
Expand Down
146 changes: 52 additions & 94 deletions contracts/scorer_factory/src/scorer_factory.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![no_std]
use soroban_sdk::{contract, contractimpl, contracttype, Map, Address, Env, BytesN, Symbol, Val, Vec, symbol_short, String};
use scorer::ScorerBadge;
// use scorer::ScorerBadge;

#[contracttype]
enum DataKey {
Expand Down Expand Up @@ -153,9 +153,59 @@ impl ScorerFactoryContract {
pub fn get_scorers(env: Env) -> Map<Address, bool> {
env.storage().persistent().get::<DataKey, Map<Address, bool>>(&DataKey::CreatedScorers).unwrap_or(Map::new(&env))
}
}

/// Adds a new manager to the contract
///
/// # Arguments
/// * `env` - The Soroban environment
/// * `caller` - The address that will authenticate the addition of the new manager
/// * `manager` - The address to be added as a manager
///
/// # Panics
/// * When the caller is not the scorer factory creator or a manager
pub fn add_manager(env: Env, caller: Address, manager: Address) {
// Require authentication from the caller
caller.require_auth();

// Verify caller is factory creator or a manager
if !Self::is_scorer_factory_creator(env.clone(), caller.clone())
&& !Self::is_manager(env.clone(), caller) {
panic!("{:?}", Error::Unauthorized);
}

let mut managers = env.storage().persistent()
.get::<DataKey, Map<Address, bool>>(&DataKey::Managers)
.unwrap_or(Map::new(&env));
managers.set(manager.clone(), true);
env.storage().persistent().set(&DataKey::Managers, &managers);
}

/// Removes a manager from the contract by setting their status to false
///
/// # Arguments
/// * `env` - The Soroban environment
/// * `caller` - The address that will authenticate the removal of the manager
/// * `manager` - The address to be removed as a manager
///
/// # Panics
/// * When the caller is not the scorer factory creator or a manager
pub fn remove_manager(env: Env, caller: Address, manager: Address) {
// Require authentication from the caller
caller.require_auth();

// Verify caller is factory creator or a manager
if !Self::is_scorer_factory_creator(env.clone(), caller.clone())
&& !Self::is_manager(env.clone(), caller) {
panic!("{:?}", Error::Unauthorized);
}

let mut managers = env.storage().persistent()
.get::<DataKey, Map<Address, bool>>(&DataKey::Managers)
.unwrap_or(Map::new(&env));
managers.set(manager.clone(), false);
env.storage().persistent().set(&DataKey::Managers, &managers);
}
}

#[cfg(test)]
mod test {
Expand Down Expand Up @@ -196,102 +246,10 @@ mod test {
assert!(scorer_factory_client.is_manager(&scorer_factory_creator));
}

#[test]
fn test_create_scorer() {
let (env, scorer_factory_creator, scorer_factory_client) = setup_contract();

let salt = BytesN::from_array(&env, &[1; 32]);
let init_fn = Symbol::new(&env, "initialize");

// Create the badge map
let mut scorer_badges = Map::new(&env);
let badge = ScorerBadge {
name: String::from_str(&env, "Test Badge"),
issuer: scorer_factory_creator.clone(),
score: 100,
};
scorer_badges.set(1, badge);
let mut init_args: Vec<Val> = Vec::new(&env);

init_args.push_back(scorer_factory_creator.clone().into_val(&env));
init_args.push_back(scorer_badges.into_val(&env));
// Create the scorer contract
let scorer_address = scorer_factory_client.create_scorer(
&scorer_factory_creator,
&salt,
&init_fn,
&init_args,
);

assert!(!scorer_address.to_string().is_empty());

}

#[test]
#[should_panic(expected = "Unauthorized")]
fn test_create_scorer_unauthorized() {
let (env, _scorer_factory_creator, scorer_factory_client) = setup_contract();

// Create an unauthorized address
let unauthorized_address = Address::generate(&env);

let salt = BytesN::from_array(&env, &[1; 32]);
let init_fn = Symbol::new(&env, "initialize");

// Create the badge map
let mut scorer_badges = Map::new(&env);
let badge = ScorerBadge {
name: String::from_str(&env, "Test Badge"),
issuer: unauthorized_address.clone(),
score: 100,
};
scorer_badges.set(1, badge);

let mut init_args: Vec<Val> = Vec::new(&env);
init_args.push_back(unauthorized_address.clone().into_val(&env));
init_args.push_back(scorer_badges.into_val(&env));

// This should panic because unauthorized_address is not a manager
scorer_factory_client.create_scorer(
&unauthorized_address,
&salt,
&init_fn,
&init_args,
);
}

#[test]
fn test_get_scorers() {
let (env, scorer_factory_creator, scorer_factory_client) = setup_contract();
let scorers = scorer_factory_client.get_scorers();
assert!(scorers.len() == 0);

let salt = BytesN::from_array(&env, &[1; 32]);
let init_fn = Symbol::new(&env, "initialize");

// Create the badge map
let mut scorer_badges = Map::new(&env);
let badge = ScorerBadge {
name: String::from_str(&env, "Test Badge"),
issuer: scorer_factory_creator.clone(),
score: 100,
};
scorer_badges.set(1, badge);
let mut init_args: Vec<Val> = Vec::new(&env);

init_args.push_back(scorer_factory_creator.clone().into_val(&env));
init_args.push_back(scorer_badges.into_val(&env));
// Create the scorer contract
let scorer_address = scorer_factory_client.create_scorer(
&scorer_factory_creator,
&salt,
&init_fn,
&init_args,
);

assert!(!scorer_address.to_string().is_empty());

let scorers = scorer_factory_client.get_scorers();
assert!(scorers.len() == 1);
}
}
Loading

0 comments on commit 5b2b40a

Please sign in to comment.