Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: use the rand crate instead of random #23

Merged
merged 2 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions fhevm-engine/Cargo.lock

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

2 changes: 1 addition & 1 deletion fhevm-engine/coprocessor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ sha3.workspace = true

[dev-dependencies]
testcontainers = "0.21"
random = "0.14.0"
rand = "0.8.5"

[build-dependencies]
tonic-build = "0.12"
57 changes: 21 additions & 36 deletions fhevm-engine/coprocessor/src/tests/operators.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
use crate::server::common::FheOperation;
use crate::server::coprocessor::fhevm_coprocessor_client::FhevmCoprocessorClient;
use crate::server::coprocessor::{
AsyncComputation, AsyncComputeRequest, DebugDecryptRequest, DebugEncryptRequest,
DebugEncryptRequestSingle,
};
use crate::server::common::FheOperation;
use crate::tests::utils::wait_until_all_ciphertexts_computed;
use crate::{
server::coprocessor::{async_computation_input::Input, AsyncComputationInput},
tests::utils::{default_api_key, setup_test_app},
};
use bigdecimal::num_bigint::BigInt;
use fhevm_engine_common::tfhe_ops::{does_fhe_operation_support_both_encrypted_operands, does_fhe_operation_support_scalar};
use fhevm_engine_common::tfhe_ops::{
does_fhe_operation_support_both_encrypted_operands, does_fhe_operation_support_scalar,
};
use fhevm_engine_common::types::{FheOperationType, SupportedFheOperations};
use random::Source;
use strum::IntoEnumIterator;
use rand::Rng;
use std::{ops::Not, str::FromStr};
use strum::IntoEnumIterator;
use tonic::metadata::MetadataValue;

struct BinaryOperatorTestCase {
Expand All @@ -37,32 +39,21 @@ struct UnaryOperatorTestCase {
}

fn supported_bits() -> &'static [i32] {
&[
8,
16,
32,
64,
128,
160,
256,
512,
1024,
2048,
]
&[8, 16, 32, 64, 128, 160, 256, 512, 1024, 2048]
}

fn supported_types() -> &'static [i32] {
&[
0, // bool
// 1, TODO: add 4 bit support
2, // 8 bit
3, // 16 bit
4, // 32 bit
5, // 64 bit
6, // 128 bit
7, // 160 bit
8, // 256 bit
9, // ebytes 64
2, // 8 bit
3, // 16 bit
4, // 32 bit
5, // 64 bit
6, // 128 bit
7, // 160 bit
8, // 256 bit
9, // ebytes 64
10, // ebytes 128
11, // ebytes 256
]
Expand All @@ -85,10 +76,7 @@ fn supported_bits_to_bit_type_in_db(inp: i32) -> i32 {
}

fn random_handle_start() -> u64 {
let time = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)
.unwrap().as_nanos();
let mut random_gen = random::default(time as u64);
random_gen.read_u64()
rand::thread_rng().gen()
}

#[tokio::test]
Expand Down Expand Up @@ -524,12 +512,7 @@ async fn test_fhe_if_then_else() -> Result<(), Box<dyn std::error::Error>> {
let left_handle = next_handle();
let right_handle = next_handle();
let is_input_bool = *input_types == fhe_bool_type;
let (left_input, right_input) =
if is_input_bool {
(0, 1)
} else {
(7, 12)
};
let (left_input, right_input) = if is_input_bool { (0, 1) } else { (7, 12) };
enc_request_payload.push(DebugEncryptRequestSingle {
handle: left_handle.clone(),
be_value: BigInt::from(left_input).to_bytes_be().1,
Expand All @@ -545,7 +528,9 @@ async fn test_fhe_if_then_else() -> Result<(), Box<dyn std::error::Error>> {
let output_handle = next_handle();
let (expected_result, input_handle) = if test_value {
(left_input, &true_handle)
} else { (right_input, &false_handle) };
} else {
(right_input, &false_handle)
};
if_then_else_outputs.push(IfThenElseOutput {
input_type: *input_types,
input_bool: test_value,
Expand Down Expand Up @@ -743,7 +728,7 @@ fn compute_expected_unary_output(inp: &BigInt, op: SupportedFheOperations) -> Bi
}
let num = BigInt::from_bytes_be(bigdecimal::num_bigint::Sign::Plus, &bytes);
num + 1
},
}
other => panic!("unsupported unary operation: {:?}", other),
}
}
Expand Down
93 changes: 59 additions & 34 deletions fhevm-engine/coprocessor/src/tests/utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::cli::Args;
use std::sync::atomic::{AtomicU16, Ordering};
use testcontainers::{core::WaitFor, runners::AsyncRunner, GenericImage, ImageExt};
use tokio::sync::watch::Receiver;

pub struct TestInstance {
// just to destroy container
Expand Down Expand Up @@ -41,28 +42,75 @@ pub fn default_tenant_id() -> i32 {
pub async fn setup_test_app() -> Result<TestInstance, Box<dyn std::error::Error>> {
if std::env::var("COPROCESSOR_TEST_LOCALHOST").is_ok() {
setup_test_app_existing_localhost().await
} else if std::env::var("COPROCESSOR_TEST_LOCAL_DB").is_ok() {
setup_test_app_existing_db().await
} else {
setup_test_app_custom_docker().await
}
}

pub async fn setup_test_app_existing_localhost() -> Result<TestInstance, Box<dyn std::error::Error>> {
const LOCAL_DB_URL: &str = "postgresql://postgres:[email protected]:5432/coprocessor";

async fn setup_test_app_existing_localhost() -> Result<TestInstance, Box<dyn std::error::Error>> {
Ok(TestInstance {
_container: None,
app_close_channel: None,
app_url: "http://127.0.0.1:50051".to_string(),
db_url: "postgresql://postgres:[email protected]:5432/coprocessor".to_string(),
db_url: LOCAL_DB_URL.to_string(),
})
}

pub async fn setup_test_app_custom_docker() -> Result<TestInstance, Box<dyn std::error::Error>> {
pub async fn setup_test_app_existing_db() -> Result<TestInstance, Box<dyn std::error::Error>> {
let app_port = get_app_port();
let (app_close_channel, rx) = tokio::sync::watch::channel(false);
start_coprocessor(rx, app_port, &LOCAL_DB_URL).await;
Ok(TestInstance {
_container: None,
app_close_channel: Some(app_close_channel),
app_url: format!("http://127.0.0.1:{app_port}"),
db_url: LOCAL_DB_URL.to_string(),
})
}

async fn start_coprocessor(rx: Receiver<bool>, app_port: u16, db_url: &str) {
let args: Args = Args {
run_bg_worker: true,
run_server: true,
generate_fhe_keys: false,
server_maximum_ciphertexts_to_schedule: 5000,
work_items_batch_size: 40,
tenant_key_cache_size: 4,
coprocessor_fhe_threads: 4,
maximum_handles_per_input: 255,
tokio_threads: 2,
pg_pool_max_connections: 2,
server_addr: format!("127.0.0.1:{app_port}"),
database_url: Some(db_url.to_string()),
maximimum_compact_inputs_upload: 10,
coprocessor_private_key: "./coprocessor.key".to_string(),
};

std::thread::spawn(move || {
crate::start_runtime(args, Some(rx));
});

// wait until app port is opened
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
}

fn get_app_port() -> u16 {
static PORT_COUNTER: AtomicU16 = AtomicU16::new(10000);

let app_port = PORT_COUNTER.fetch_add(1, Ordering::SeqCst);
// wrap around, if we ever have that many tests?
if app_port >= 50000 {
PORT_COUNTER.store(10000, Ordering::SeqCst);
}
app_port
}

async fn setup_test_app_custom_docker() -> Result<TestInstance, Box<dyn std::error::Error>> {
let app_port = get_app_port();

let container = GenericImage::new("postgres", "15.7")
.with_wait_for(WaitFor::message_on_stderr(
Expand Down Expand Up @@ -98,30 +146,7 @@ pub async fn setup_test_app_custom_docker() -> Result<TestInstance, Box<dyn std:
println!("DB prepared");

let (app_close_channel, rx) = tokio::sync::watch::channel(false);
let args: Args = Args {
run_bg_worker: true,
run_server: true,
generate_fhe_keys: false,
server_maximum_ciphertexts_to_schedule: 5000,
work_items_batch_size: 40,
tenant_key_cache_size: 4,
coprocessor_fhe_threads: 4,
maximum_handles_per_input: 255,
tokio_threads: 2,
pg_pool_max_connections: 2,
server_addr: format!("127.0.0.1:{app_port}"),
database_url: Some(db_url.clone()),
maximimum_compact_inputs_upload: 10,
coprocessor_private_key: "./coprocessor.key".to_string(),
};

std::thread::spawn(move || {
crate::start_runtime(args, Some(rx));
});

// wait until app port is opened
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;

start_coprocessor(rx, app_port, &db_url).await;
Ok(TestInstance {
_container: Some(container),
app_close_channel: Some(app_close_channel),
Expand All @@ -130,19 +155,19 @@ pub async fn setup_test_app_custom_docker() -> Result<TestInstance, Box<dyn std:
})
}

pub async fn wait_until_all_ciphertexts_computed(test_instance: &TestInstance) -> Result<(), Box<dyn std::error::Error>> {
pub async fn wait_until_all_ciphertexts_computed(
test_instance: &TestInstance,
) -> Result<(), Box<dyn std::error::Error>> {
let pool = sqlx::postgres::PgPoolOptions::new()
.max_connections(2)
.connect(test_instance.db_url())
.await?;

loop {
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
let count = sqlx::query!(
"SELECT count(*) FROM computations WHERE NOT is_completed"
)
.fetch_one(&pool)
.await?;
let count = sqlx::query!("SELECT count(*) FROM computations WHERE NOT is_completed")
.fetch_one(&pool)
.await?;
let current_count = count.count.unwrap();
if current_count == 0 {
println!("All computations completed");
Expand All @@ -153,4 +178,4 @@ pub async fn wait_until_all_ciphertexts_computed(test_instance: &TestInstance) -
}

Ok(())
}
}