use essential_builder::{build_block_fifo, Config};
use essential_builder_db as builder_db;
use essential_node::{self as node, test_utils as util};
use essential_node_types::{register_contract_solution, BigBang};
use essential_types::solution::SolutionSet;
use std::sync::Arc;
use std::time::Duration;
async fn test_builder_conn_pool() -> builder_db::ConnectionPool {
let config = builder_db::pool::Config {
conn_limit: 4,
source: builder_db::pool::Source::Memory(uuid::Uuid::new_v4().into()),
};
let conn_pool = builder_db::ConnectionPool::new(&config).unwrap();
conn_pool.create_tables().await.unwrap();
conn_pool
}
async fn test_node_conn_pool() -> node::db::ConnectionPool {
let node_conf = node::db::pool::Config {
conn_limit: 4,
source: node::db::pool::Source::Memory(uuid::Uuid::new_v4().into()),
};
let db = node::db::ConnectionPool::with_tables(&node_conf).unwrap();
let bb = BigBang::default();
node::ensure_big_bang_block(&db, &bb).await.unwrap();
db
}
#[tokio::test]
async fn build_block_all_solution_sets_succeed() {
let builder_config = Config::default();
let builder_conn_pool = test_builder_conn_pool().await;
let node_conn_pool = test_node_conn_pool().await;
let blocks = util::test_blocks_with_contracts(1, 101);
let solution_sets = blocks
.into_iter()
.flat_map(|block| block.solution_sets)
.map(Arc::new)
.collect::<Vec<_>>();
for solution_set in &solution_sets {
let submission_timestamp = Duration::from_secs(0);
builder_conn_pool
.insert_solution_set_submission(solution_set.clone(), submission_timestamp)
.await
.unwrap();
}
let (_, summary) = build_block_fifo(&builder_conn_pool, &node_conn_pool, &builder_config)
.await
.unwrap();
assert_eq!(summary.succeeded.len(), solution_sets.len() + 1);
assert_eq!(summary.failed.len(), 0);
let remaining_solution_sets = builder_conn_pool
.list_solution_sets(Duration::ZERO..Duration::from_secs(i64::MAX as _), i64::MAX)
.await
.unwrap();
assert!(remaining_solution_sets.is_empty());
}
#[tokio::test]
async fn build_block_all_solution_sets_fail() {
let builder_config = Config::default();
let builder_conn_pool = test_builder_conn_pool().await;
let node_conn_pool = test_node_conn_pool().await;
let (blocks, _contracts, _programs) = util::test_blocks(100);
let solution_sets = blocks
.into_iter()
.flat_map(|block| block.solution_sets)
.map(Arc::new)
.collect::<Vec<_>>();
for solution_set in &solution_sets {
let timestamp = Duration::from_secs(0); builder_conn_pool
.insert_solution_set_submission(solution_set.clone(), timestamp)
.await
.unwrap();
}
let (_, summary) = build_block_fifo(&builder_conn_pool, &node_conn_pool, &builder_config)
.await
.unwrap();
assert_eq!(summary.failed.len(), solution_sets.len());
assert_eq!(summary.succeeded.len(), 1);
for (ca, solution_set_ix, _invalid_solution_set) in summary.failed {
let failures = builder_conn_pool
.latest_solution_set_failures(ca.clone(), 1)
.await
.unwrap();
assert_eq!(failures.len(), 1);
assert_eq!(failures[0].attempt_solution_set_ix, solution_set_ix);
}
let remaining_solution_sets = builder_conn_pool
.list_solution_sets(Duration::ZERO..Duration::from_secs(i64::MAX as _), i64::MAX)
.await
.unwrap();
assert!(remaining_solution_sets.is_empty());
}
#[tokio::test]
async fn build_block_no_solution_sets() {
let builder_config = Config::default();
let builder_conn_pool = test_builder_conn_pool().await;
let node_conn_pool = test_node_conn_pool().await;
let (_, summary) = build_block_fifo(&builder_conn_pool, &node_conn_pool, &builder_config)
.await
.unwrap();
assert_eq!(summary.succeeded.len(), 1);
assert_eq!(summary.failed.len(), 0);
}
#[tokio::test]
async fn build_block_mixed_solution_sets() {
let builder_config = Config::default();
let builder_conn_pool = test_builder_conn_pool().await;
let node_conn_pool = test_node_conn_pool().await;
let registry = BigBang::default().contract_registry;
let (blocks, contracts, _programs) = util::test_blocks(10);
let solution_sets = blocks
.into_iter()
.enumerate()
.flat_map(|(i, mut block)| {
let ix = 2;
if i == ix {
let sol = register_contract_solution(registry.clone(), &contracts[ix]).unwrap();
let solution_set = SolutionSet {
solutions: vec![sol],
};
block.solution_sets.insert(0, solution_set);
}
block.solution_sets
})
.map(Arc::new)
.collect::<Vec<_>>();
for solution_set in &solution_sets {
let timestamp = Duration::from_secs(0); builder_conn_pool
.insert_solution_set_submission(solution_set.clone(), timestamp)
.await
.unwrap();
}
let (_, summary) = build_block_fifo(&builder_conn_pool, &node_conn_pool, &builder_config)
.await
.unwrap();
assert!(!summary.succeeded.is_empty());
assert!(!summary.failed.is_empty());
for (ca, solution_set_ix, _invalid_solution_set) in summary.failed {
let failures = builder_conn_pool
.latest_solution_set_failures(ca, 1)
.await
.unwrap();
assert_eq!(failures.len(), 1);
assert_eq!(failures[0].attempt_solution_set_ix, solution_set_ix);
}
let remaining_solution_sets = builder_conn_pool
.list_solution_sets(Duration::ZERO..Duration::from_secs(i64::MAX as _), i64::MAX)
.await
.unwrap();
assert!(remaining_solution_sets.is_empty());
}