Skip to content

Commit

Permalink
refactor entire test utilities, setup generalized testing framework
Browse files Browse the repository at this point in the history
  • Loading branch information
Zacholme7 committed Dec 11, 2024
1 parent 1652528 commit e99b7ef
Show file tree
Hide file tree
Showing 8 changed files with 587 additions and 383 deletions.
4 changes: 2 additions & 2 deletions anchor/database/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::sync::LazyLock;
use std::time::Duration;

mod cluster_operations;
pub mod error;
mod error;
mod operator_operations;
mod share_operations;
mod state;
Expand All @@ -24,7 +24,7 @@ const POOL_SIZE: u32 = 1;
const CONNECTION_TIMEOUT: Duration = Duration::from_secs(5);

#[derive(Debug, Clone, Default)]
pub struct NetworkState {
struct NetworkState {
/// The ID of our own operator. This is determined via events when the operator is
/// registered with the network. Therefore, this may not be available right away if the client
/// is running but has not bee registered with the network contract yet.
Expand Down
5 changes: 0 additions & 5 deletions anchor/database/src/operator_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ impl NetworkDatabase {
Ok(())
}

/// Set the id of our own operator
pub fn set_own_id(&mut self, id: OperatorId) {
self.state.id = Some(id);
}

// Helper to encode the RsaPublicKey to PEM
fn encode_pubkey(pubkey: &Rsa<Public>) -> String {
// this should never fail as the key has already been validated upon construction
Expand Down
6 changes: 5 additions & 1 deletion anchor/database/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ impl NetworkState {
let mut cluster_members: HashMap<ClusterId, HashSet<OperatorId>> =
HashMap::with_capacity(num_clusters);

println!("{:#?}", clusters);
// Populate state stores from cluster data
clusters.iter().for_each(|cluster| {
let cluster_id = cluster.cluster_id;
Expand Down Expand Up @@ -125,4 +124,9 @@ impl NetworkDatabase {
pub fn member_of_cluster(&self, id: &ClusterId) -> bool {
self.state.clusters.contains(id)
}

/// Set the id of our own operator
pub fn set_own_id(&mut self, id: OperatorId) {
self.state.id = Some(id);
}
}
104 changes: 16 additions & 88 deletions anchor/database/src/tests/cluster_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,101 +7,29 @@ mod cluster_database_tests {
#[test]
// Test inserting a cluster into the database
fn test_insert_retrieve_cluster() {
// Create a temporary database
let dir = tempdir().unwrap();
let file = dir.path().join("db.sqlite");
let mut db = NetworkDatabase::new(&file, Some(OperatorId(1))).unwrap();

// First insert the operators that will be part of the cluster
for i in 0..4 {
let operator = dummy_operator(i);
assert!(db.insert_operator(&operator).is_ok());
}

// Insert a dummy cluster
let cluster = dummy_cluster(4);
assert!(db.insert_cluster(cluster.clone()).is_ok());

debug_print_db(&db);
println!("{:#?}", db.state);

// Verify cluster is in memory
assert!(db.member_of_cluster(&cluster.cluster_id));
assert_eq!(
db.state.cluster_members[&cluster.cluster_id].len(),
cluster.cluster_members.len()
);

// Verify cluster is in the underlying database
let cluster_row = get_cluster_from_db(&db, cluster.cluster_id);
assert!(cluster_row.is_some());
let (db_cluster_id, db_faulty, db_liquidated) = cluster_row.unwrap();
assert_eq!(db_cluster_id, *cluster.cluster_id as i64);
assert_eq!(db_faulty, cluster.faulty as i64);
assert_eq!(db_liquidated, cluster.liquidated);

// Verify cluster members are in the underlying database
for member in &cluster.cluster_members {
let member_row = get_cluster_member_from_db(&db, member.cluster_id, member.operator_id);
assert!(member_row.is_some());
let (db_cluster_id, db_operator_id) = member_row.unwrap();
assert_eq!(db_cluster_id, *member.cluster_id as i64);
assert_eq!(db_operator_id, *member.operator_id as i64);
}

// Verify that the shares are in the database
let all_shares = get_shares_from_db(&db, cluster.cluster_id);
assert!(!all_shares.is_empty());

// Verify that the validator is in the database
let validator_pubkey_str = cluster.validator_metadata.validator_pubkey.to_string();
assert!(get_validator_from_db(&db, &validator_pubkey_str).is_some());
let fixture = TestFixture::new(Some(1));
assertions::assert_cluster_exists_fully(&fixture.db, &fixture.cluster);
}

#[test]
/// Try inserting a cluster that does not already have registers operators in the database
// Try inserting a cluster that does not already have registers operators in the database
fn test_insert_cluster_without_operators() {
// Create a temporary database
let dir = tempdir().unwrap();
let file = dir.path().join("db.sqlite");
let mut db = NetworkDatabase::new(&file, None).unwrap();

// Try to insert a cluster without first inserting its operators
let cluster = dummy_cluster(4);

// This should fail because the operators don't exist in the database
assert!(db.insert_cluster(cluster).is_err());
let mut fixture = TestFixture::new_empty();
let cluster = generators::cluster::random(3);
fixture
.db
.insert_cluster(cluster)
.expect_err("Insertion should fail");
}

#[test]
// Test deleting a cluster and make sure that it is properly cleaned up
fn test_delete_cluster() {
// Create a temporary database
let dir = tempdir().unwrap();
let file = dir.path().join("db.sqlite");
let mut db = NetworkDatabase::new(&file, Some(OperatorId(1))).unwrap();

// populate the db with operators and cluster
let cluster = db_with_cluster(&mut db);

// Delete the cluster and then confirm it is gone from memory and dbb
assert!(db.delete_cluster(cluster.cluster_id).is_ok());

let cluster_row = get_cluster_from_db(&db, cluster.cluster_id);
assert!(!db.member_of_cluster(&cluster.cluster_id));
assert!(cluster_row.is_none());

// Make sure all the members are gone
for member in &cluster.cluster_members {
let member_row = get_cluster_member_from_db(&db, member.cluster_id, member.operator_id);
assert!(member_row.is_none());
}

// Make sure all the shares are gone
let all_shares = get_shares_from_db(&db, cluster.cluster_id);
assert!(all_shares.is_empty());

// Make sure the validator this cluster represented is gone
let validator_pubkey_str = cluster.validator_metadata.validator_pubkey.to_string();
assert!(get_validator_from_db(&db, &validator_pubkey_str).is_none());
let mut fixture = TestFixture::new(Some(1));
fixture
.db
.delete_cluster(fixture.cluster.cluster_id)
.expect("Failed to delete cluster");
assertions::assert_cluster_exists_not_fully(&fixture.db, &fixture.cluster);
}
}
114 changes: 62 additions & 52 deletions anchor/database/src/tests/operator_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,78 +5,88 @@ mod operator_database_tests {
use super::*;

#[test]
// Test inserting into the database and then confirming that it is both in
// memory and in the underlying database
// Test to make sure we can insert new operators into the database and they are present in the
// state stores
fn test_insert_retrieve_operator() {
// Create a temporary database
let dir = tempdir().unwrap();
let file = dir.path().join("db.sqlite");
let mut db = NetworkDatabase::new(&file, None).unwrap();
// Create a new text fixture with empty db
let mut fixture = TestFixture::new_empty();

// Insert dummy operator data into the database
let operator = dummy_operator(1);
assert!(db.insert_operator(&operator).is_ok());
// Generate a new operator and insert it
let operator = generators::operator::with_id(1);
fixture
.db
.insert_operator(&operator)
.expect("Failed to insert operator");

// Fetch operator from in memory store and confirm values
let fetched_operator = db.get_operator(&operator.id);
if let Some(op) = fetched_operator {
assert_eq!(op.id, operator.id);
// Confirm that it exists both in the db and the state store
assertions::assert_operator_exists_fully(&fixture.db, &operator);
}

assert_eq!(
op.rsa_pubkey.public_key_to_pem().unwrap(),
operator.rsa_pubkey.public_key_to_pem().unwrap()
);
assert_eq!(op.owner, operator.owner);
} else {
panic!("Expected to find operator in memory");
}
#[test]
// Ensure that we cannot insert a duplicate operator into the database
fn test_duplicate_insert() {
// Create a new test fixture with empty db
let mut fixture = TestFixture::new_empty();

// Generate a new operator and insert it
let operator = generators::operator::with_id(1);
fixture
.db
.insert_operator(&operator)
.expect("Failed to insert operator");

// Check to make sure the operator is also in the underlying db
let db_operator = get_operator_from_db(&db, operator.id);
if let Some(op) = db_operator {
assert_eq!(
op.rsa_pubkey.public_key_to_pem().unwrap(),
operator.rsa_pubkey.public_key_to_pem().unwrap()
);
assert_eq!(op.id, operator.id);
assert_eq!(op.owner, operator.owner);
} else {
panic!("Expected to find operator in database");
// Try to insert it again, this should fail
let success = fixture.db.insert_operator(&operator);
if success.is_ok() {
panic!("Expected an error when inserting an operator that is already present");
}
}

#[test]
// Test deleting an operator and confirming it is gone from the db and in memory
fn test_insert_delete_operator() {
// Create a temporary database
let dir = tempdir().unwrap();
let file = dir.path().join("db.sqlite");
let mut db = NetworkDatabase::new(&file, None).unwrap();
// Create new test fixture with empty db
let mut fixture = TestFixture::new_empty();

// Insert dummy operator data into the database
let operator = dummy_operator(1);
let _ = db.insert_operator(&operator);
// Generate a new operator and insert it
let operator = generators::operator::with_id(1);
fixture
.db
.insert_operator(&operator)
.expect("Failed to insert operator");

// Now, delete the operator
assert!(db.delete_operator(operator.id).is_ok());
fixture
.db
.delete_operator(operator.id)
.expect("Failed to delete operator");

// Confirm that is it removed from in memory
assert!(db.get_operator(&operator.id).is_none());

// Also confirm that it is removed from the database
assert!(get_operator_from_db(&db, operator.id).is_none());
// Confirm that it is gone
assertions::assert_operator_not_exists_fully(&fixture.db, operator.id);
}

#[test]
// insert multiple operators
// Test inserting multiple operators
fn test_insert_multiple_operators() {
let dir = tempdir().unwrap();
let file = dir.path().join("db.sqlite");
let mut db = NetworkDatabase::new(&file, None).unwrap();
// Create new test fixture with empty db
let mut fixture = TestFixture::new_empty();

// Generate and insert operators
let operators: Vec<Operator> = (0..4).map(generators::operator::with_id).collect();
for operator in &operators {
fixture
.db
.insert_operator(operator)
.expect("Failed to insert operator");
}

for id in 0..4 {
let operator = dummy_operator(id);
assert!(db.insert_operator(&operator).is_ok());
// Delete them all and confirm deletion
for operator in operators {
fixture
.db
.delete_operator(operator.id)
.expect("Failed to delete operator");
assertions::assert_operator_not_exists_fully(&fixture.db, operator.id);
}
}
}
42 changes: 25 additions & 17 deletions anchor/database/src/tests/state_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,34 @@ mod state_database_tests {
use super::*;

#[test]
fn test_state_after_restart() {
// Create a temporary database
let dir = tempdir().unwrap();
let file = dir.path().join("db.sqlite");
let mut db = NetworkDatabase::new(&file, Some(OperatorId(1))).unwrap();
// Make sure all of the previously inserted operators are present after restart
fn test_operator_store() {
// Create new test fixture with populated DB
let mut fixture = TestFixture::new(Some(1));

// Insert the operators and a cluster we are a part of
for i in 0..4 {
let operator = dummy_operator(i);
assert!(db.insert_operator(&operator).is_ok());
// drop the database and then recreate it
drop(fixture.db);
fixture.db = NetworkDatabase::new(&fixture.path, Some(OperatorId(1)))
.expect("Failed to create database");

// confirm that all of the operators exist were
for operator in fixture.operators {
assertions::assert_operator_exists_fully(&fixture.db, &operator);
}
// Insert a dummy cluster
let cluster = dummy_cluster(4);
assert!(db.insert_cluster(cluster.clone()).is_ok());
println!("{:#?}", db.state);
}

#[test]
fn test_cluster_after_restart() {
// Create new test fixture with populated DB
let mut fixture = TestFixture::new(Some(1));
let cluster = fixture.cluster;

// drop db and recreate it, stores should be built since db already exists
drop(db);
// drop the database and then recreate it
drop(fixture.db);
fixture.db = NetworkDatabase::new(&fixture.path, Some(OperatorId(1)))
.expect("Failed to create database");

let db = NetworkDatabase::new(&file, Some(OperatorId(1))).unwrap();
println!("{:#?}", db.state);
// Confirm all cluster related data is still correct
assertions::assert_cluster_exists_fully(&fixture.db, &cluster);
}
}
Loading

0 comments on commit e99b7ef

Please sign in to comment.