// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Unlicense use anyhow::Result; use detee_shared::app_proto::brain_app_cli_server::BrainAppCliServer; use detee_shared::app_proto::brain_app_daemon_server::BrainAppDaemonServer; use detee_shared::general_proto::brain_general_cli_server::BrainGeneralCliServer; use detee_shared::vm_proto::brain_vm_cli_server::BrainVmCliServer; use detee_shared::vm_proto::brain_vm_daemon_server::BrainVmDaemonServer; use dotenv::dotenv; use hyper_util::rt::TokioIo; use std::sync::Arc; use surreal_brain::grpc::app::{AppCliServer, AppDaemonServer}; use surreal_brain::grpc::general::GeneralCliServer; use surreal_brain::grpc::vm::{VmCliServer, VmDaemonServer}; use surrealdb::engine::remote::ws::Client; use surrealdb::Surreal; use tokio::io::DuplexStream; use tokio::sync::OnceCell; use tonic::transport::{Channel, Endpoint, Uri}; use tower::service_fn; pub static DB_STATE: OnceCell> = OnceCell::const_new(); pub async fn prepare_test_db() -> Result> { dotenv().ok(); let db_url = std::env::var("DB_URL").expect("DB_URL not set in .env"); let db_user = std::env::var("DB_USER").expect("DB_USER not set in .env"); let db_pass = std::env::var("DB_PASS").expect("DB_PASS not set in .env"); let db_ns = "test_brain"; let db_name = "test_brain_db"; let db = surreal_brain::db::db_connection(&db_url, &db_user, &db_pass, db_ns, db_name).await?; DB_STATE .get_or_init(|| async { db.query(format!("REMOVE DATABASE {db_name}")).await?; // enable this for single isolated tests without mock data // surreal_brain::db::migration0_tables(&db).await?; surreal_brain::db::migration0_mock_data(&db).await?; surreal_brain::db::migration1_patch(&db).await?; Ok::<(), anyhow::Error>(()) }) .await; Ok(db) } pub async fn run_service_for_stream_server() -> DuplexStream { dotenv().ok(); let (client, server) = tokio::io::duplex(1024); let db_url = std::env::var("DB_URL").expect("DB_URL not set in .env"); let db_user = std::env::var("DB_USER").expect("DB_USER not set in .env"); let db_pass = std::env::var("DB_PASS").expect("DB_PASS not set in .env"); let db_ns = "test_brain"; let db_name = "test_brain_db"; tokio::spawn(async move { let db = surreal_brain::db::db_connection(&db_url, &db_user, &db_pass, db_ns, db_name).await?; let db_arc = Arc::new(db); tonic::transport::Server::builder() .add_service(BrainGeneralCliServer::new(GeneralCliServer::new(db_arc.clone()))) .add_service(BrainVmCliServer::new(VmCliServer::new(db_arc.clone()))) .add_service(BrainVmDaemonServer::new(VmDaemonServer::new(db_arc.clone()))) .add_service(BrainAppCliServer::new(AppCliServer::new(db_arc.clone()))) .add_service(BrainAppDaemonServer::new(AppDaemonServer::new(db_arc.clone()))) .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server))) .await?; Ok::<(), anyhow::Error>(()) }); client } pub async fn connect_stream_client_channel(c_stream: DuplexStream) -> Result { let mut client = Some(c_stream); Ok(Endpoint::from_static("http://127.0.0.1:0") .connect_with_connector(service_fn(move |_: Uri| { let client = client.take().unwrap(); async move { Ok::, std::io::Error>(TokioIo::new(client)) } })) .await?) } pub async fn run_service_for_stream() -> Result { let client = run_service_for_stream_server().await; connect_stream_client_channel(client).await }