start adding tests that need docker for mysql management
This commit is contained in:
parent
31c611f4ff
commit
5da334fcb7
@ -12,6 +12,7 @@ deadlock_detection = ["parking_lot/deadlock_detection"]
|
|||||||
mimalloc = ["dep:mimalloc"]
|
mimalloc = ["dep:mimalloc"]
|
||||||
tokio-console = ["dep:tokio-console", "dep:console-subscriber"]
|
tokio-console = ["dep:tokio-console", "dep:console-subscriber"]
|
||||||
rdkafka-src = ["rdkafka/cmake-build", "rdkafka/libz", "rdkafka/ssl-vendored", "rdkafka/zstd-pkg-config"]
|
rdkafka-src = ["rdkafka/cmake-build", "rdkafka/libz", "rdkafka/ssl-vendored", "rdkafka/zstd-pkg-config"]
|
||||||
|
tests-needing-docker = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
deferred-rate-limiter = { path = "../deferred-rate-limiter" }
|
deferred-rate-limiter = { path = "../deferred-rate-limiter" }
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use anyhow::Context;
|
||||||
use derive_more::From;
|
use derive_more::From;
|
||||||
use migration::sea_orm::{self, ConnectionTrait, Database};
|
use migration::sea_orm::{self, ConnectionTrait, Database};
|
||||||
use migration::sea_query::table::ColumnDef;
|
use migration::sea_query::table::ColumnDef;
|
||||||
@ -31,24 +32,28 @@ pub async fn get_db(
|
|||||||
|
|
||||||
let mut db_opt = sea_orm::ConnectOptions::new(db_url);
|
let mut db_opt = sea_orm::ConnectOptions::new(db_url);
|
||||||
|
|
||||||
// TODO: load all these options from the config file. i think mysql default max is 100
|
// TODO: load all these options from the config file. i think docker mysql default max is 100
|
||||||
// TODO: sqlx logging only in debug. way too verbose for production
|
// TODO: sqlx info logging is way too verbose for production.
|
||||||
db_opt
|
db_opt
|
||||||
.connect_timeout(Duration::from_secs(30))
|
.acquire_timeout(Duration::from_secs(5))
|
||||||
|
.connect_timeout(Duration::from_secs(5))
|
||||||
.min_connections(min_connections)
|
.min_connections(min_connections)
|
||||||
.max_connections(max_connections)
|
.max_connections(max_connections)
|
||||||
.sqlx_logging(false);
|
.sqlx_logging_level(tracing::log::LevelFilter::Warn)
|
||||||
// .sqlx_logging_level(log::LevelFilter::Info);
|
.sqlx_logging(true);
|
||||||
|
|
||||||
Database::connect(db_opt).await
|
Database::connect(db_opt).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn drop_migration_lock(db_conn: &DatabaseConnection) -> Result<(), DbErr> {
|
pub async fn drop_migration_lock(db_conn: &DatabaseConnection) -> anyhow::Result<()> {
|
||||||
let db_backend = db_conn.get_database_backend();
|
let db_backend = db_conn.get_database_backend();
|
||||||
|
|
||||||
let drop_lock_statment = db_backend.build(Table::drop().table(Alias::new("migration_lock")));
|
let drop_lock_statment = db_backend.build(Table::drop().table(Alias::new("migration_lock")));
|
||||||
|
|
||||||
db_conn.execute(drop_lock_statment).await?;
|
db_conn
|
||||||
|
.execute(drop_lock_statment)
|
||||||
|
.await
|
||||||
|
.context("dropping lock")?;
|
||||||
|
|
||||||
debug!("migration lock unlocked");
|
debug!("migration lock unlocked");
|
||||||
|
|
||||||
@ -59,7 +64,7 @@ pub async fn drop_migration_lock(db_conn: &DatabaseConnection) -> Result<(), DbE
|
|||||||
pub async fn migrate_db(
|
pub async fn migrate_db(
|
||||||
db_conn: &DatabaseConnection,
|
db_conn: &DatabaseConnection,
|
||||||
override_existing_lock: bool,
|
override_existing_lock: bool,
|
||||||
) -> Result<(), DbErr> {
|
) -> anyhow::Result<()> {
|
||||||
let db_backend = db_conn.get_database_backend();
|
let db_backend = db_conn.get_database_backend();
|
||||||
|
|
||||||
// TODO: put the timestamp and hostname into this as columns?
|
// TODO: put the timestamp and hostname into this as columns?
|
||||||
@ -75,6 +80,8 @@ pub async fn migrate_db(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!("waiting for migration lock...");
|
||||||
|
|
||||||
// there are migrations to apply
|
// there are migrations to apply
|
||||||
// acquire a lock
|
// acquire a lock
|
||||||
if let Err(err) = db_conn.execute(create_lock_statment.clone()).await {
|
if let Err(err) = db_conn.execute(create_lock_statment.clone()).await {
|
||||||
@ -96,13 +103,15 @@ pub async fn migrate_db(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!("migrating...");
|
||||||
|
|
||||||
let migration_result = Migrator::up(db_conn, None).await;
|
let migration_result = Migrator::up(db_conn, None).await;
|
||||||
|
|
||||||
// drop the distributed lock
|
// drop the distributed lock
|
||||||
drop_migration_lock(db_conn).await?;
|
drop_migration_lock(db_conn).await?;
|
||||||
|
|
||||||
// return if migrations erred
|
// return if migrations erred
|
||||||
migration_result
|
migration_result.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Connect to the database and run migrations
|
/// Connect to the database and run migrations
|
||||||
@ -110,11 +119,13 @@ pub async fn get_migrated_db(
|
|||||||
db_url: String,
|
db_url: String,
|
||||||
min_connections: u32,
|
min_connections: u32,
|
||||||
max_connections: u32,
|
max_connections: u32,
|
||||||
) -> Result<DatabaseConnection, DbErr> {
|
) -> anyhow::Result<DatabaseConnection> {
|
||||||
// TODO: this seems to fail silently
|
// TODO: this seems to fail silently
|
||||||
let db_conn = get_db(db_url, min_connections, max_connections).await?;
|
let db_conn = get_db(db_url, min_connections, max_connections)
|
||||||
|
.await
|
||||||
|
.context("getting db")?;
|
||||||
|
|
||||||
migrate_db(&db_conn, false).await?;
|
migrate_db(&db_conn, false).await.context("migrating db")?;
|
||||||
|
|
||||||
Ok(db_conn)
|
Ok(db_conn)
|
||||||
}
|
}
|
||||||
|
@ -1565,7 +1565,7 @@ mod tests {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
dbg!(&x);
|
info!(?x);
|
||||||
|
|
||||||
assert!(matches!(x, OpenRequestResult::NotReady));
|
assert!(matches!(x, OpenRequestResult::NotReady));
|
||||||
|
|
||||||
|
@ -148,23 +148,23 @@ impl RpcAccountingSubCommand {
|
|||||||
.signed_duration_since(stats.first_period_datetime)
|
.signed_duration_since(stats.first_period_datetime)
|
||||||
.num_seconds()
|
.num_seconds()
|
||||||
.into();
|
.into();
|
||||||
dbg!(query_seconds);
|
info!(%query_seconds);
|
||||||
|
|
||||||
let avg_request_per_second = (stats.total_frontend_requests / query_seconds).round_dp(2);
|
let avg_request_per_second = (stats.total_frontend_requests / query_seconds).round_dp(2);
|
||||||
dbg!(avg_request_per_second);
|
info!(%avg_request_per_second);
|
||||||
|
|
||||||
let cache_hit_rate = (stats.total_cache_hits / stats.total_frontend_requests
|
let cache_hit_rate = (stats.total_cache_hits / stats.total_frontend_requests
|
||||||
* Decimal::from(100))
|
* Decimal::from(100))
|
||||||
.round_dp(2);
|
.round_dp(2);
|
||||||
dbg!(cache_hit_rate);
|
info!(%cache_hit_rate);
|
||||||
|
|
||||||
let avg_response_millis =
|
let avg_response_millis =
|
||||||
(stats.total_response_millis / stats.total_frontend_requests).round_dp(3);
|
(stats.total_response_millis / stats.total_frontend_requests).round_dp(3);
|
||||||
dbg!(avg_response_millis);
|
info!(%avg_response_millis);
|
||||||
|
|
||||||
let avg_response_bytes =
|
let avg_response_bytes =
|
||||||
(stats.total_response_bytes / stats.total_frontend_requests).round();
|
(stats.total_response_bytes / stats.total_frontend_requests).round();
|
||||||
dbg!(avg_response_bytes);
|
info!(%avg_response_bytes);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use ethers::{
|
use ethers::{
|
||||||
prelude::{Http, Provider},
|
prelude::{
|
||||||
|
rand::{self, distributions::Alphanumeric, Rng},
|
||||||
|
Http, Provider,
|
||||||
|
},
|
||||||
signers::LocalWallet,
|
signers::LocalWallet,
|
||||||
types::Address,
|
types::Address,
|
||||||
utils::{Anvil, AnvilInstance},
|
utils::{Anvil, AnvilInstance},
|
||||||
@ -8,21 +11,30 @@ use hashbrown::HashMap;
|
|||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
|
process::Command as SyncCommand,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::atomic::{AtomicU16, Ordering},
|
sync::atomic::{AtomicU16, Ordering},
|
||||||
};
|
};
|
||||||
use std::{sync::Arc, time::Duration};
|
use std::{sync::Arc, time::Duration};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
|
net::TcpStream,
|
||||||
|
process::Command as AsyncCommand,
|
||||||
sync::broadcast::{self, error::SendError},
|
sync::broadcast::{self, error::SendError},
|
||||||
task::JoinHandle,
|
task::JoinHandle,
|
||||||
time::{sleep, Instant},
|
time::{sleep, Instant},
|
||||||
};
|
};
|
||||||
use tracing::info;
|
use tracing::{info, trace};
|
||||||
use web3_proxy::{
|
use web3_proxy::{
|
||||||
config::{AppConfig, TopConfig, Web3RpcConfig},
|
config::{AppConfig, TopConfig, Web3RpcConfig},
|
||||||
|
relational_db::get_migrated_db,
|
||||||
sub_commands::ProxydSubCommand,
|
sub_commands::ProxydSubCommand,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub struct DbData {
|
||||||
|
container_name: String,
|
||||||
|
url: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct TestApp {
|
pub struct TestApp {
|
||||||
/// anvil shuts down when this guard is dropped.
|
/// anvil shuts down when this guard is dropped.
|
||||||
pub anvil: AnvilInstance,
|
pub anvil: AnvilInstance,
|
||||||
@ -30,8 +42,11 @@ pub struct TestApp {
|
|||||||
/// connection to anvil.
|
/// connection to anvil.
|
||||||
pub anvil_provider: Provider<Http>,
|
pub anvil_provider: Provider<Http>,
|
||||||
|
|
||||||
|
/// keep track of the database so it can be stopped on drop
|
||||||
|
pub db: Option<DbData>,
|
||||||
|
|
||||||
/// spawn handle for the proxy.
|
/// spawn handle for the proxy.
|
||||||
pub handle: Mutex<Option<JoinHandle<anyhow::Result<()>>>>,
|
pub proxy_handle: Mutex<Option<JoinHandle<anyhow::Result<()>>>>,
|
||||||
|
|
||||||
/// connection to the proxy that is connected to anil.
|
/// connection to the proxy that is connected to anil.
|
||||||
pub proxy_provider: Provider<Http>,
|
pub proxy_provider: Provider<Http>,
|
||||||
@ -41,7 +56,7 @@ pub struct TestApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TestApp {
|
impl TestApp {
|
||||||
pub async fn spawn() -> Self {
|
pub async fn spawn(setup_db: bool) -> Self {
|
||||||
let num_workers = 2;
|
let num_workers = 2;
|
||||||
|
|
||||||
// TODO: move basic setup into a test fixture
|
// TODO: move basic setup into a test fixture
|
||||||
@ -58,14 +73,146 @@ impl TestApp {
|
|||||||
|
|
||||||
let anvil_provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
|
let anvil_provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
|
||||||
|
|
||||||
|
let db = if setup_db {
|
||||||
|
// sqlite doesn't seem to work. our migrations are written for mysql
|
||||||
|
// so lets use docker to start mysql
|
||||||
|
let password: String = rand::thread_rng()
|
||||||
|
.sample_iter(&Alphanumeric)
|
||||||
|
.take(32)
|
||||||
|
.map(char::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let random: String = rand::thread_rng()
|
||||||
|
.sample_iter(&Alphanumeric)
|
||||||
|
.take(8)
|
||||||
|
.map(char::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let db_container_name = format!("web3-proxy-test-{}", random);
|
||||||
|
|
||||||
|
info!(%db_container_name);
|
||||||
|
|
||||||
|
// create the db_data as soon as the url is known
|
||||||
|
// when this is dropped, the db will be stopped
|
||||||
|
let mut db_data = DbData {
|
||||||
|
container_name: db_container_name.clone(),
|
||||||
|
url: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = AsyncCommand::new("docker")
|
||||||
|
.args([
|
||||||
|
"run",
|
||||||
|
"--name",
|
||||||
|
&db_container_name,
|
||||||
|
"--rm",
|
||||||
|
"-d",
|
||||||
|
"-e",
|
||||||
|
&format!("MYSQL_ROOT_PASSWORD={}", password),
|
||||||
|
"-e",
|
||||||
|
"MYSQL_DATABASE=web3_proxy_test",
|
||||||
|
"-p",
|
||||||
|
"0:3306",
|
||||||
|
"mysql",
|
||||||
|
])
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
.expect("failed to start db");
|
||||||
|
|
||||||
|
// give the db a second to start
|
||||||
|
// TODO: wait until docker says it is healthy
|
||||||
|
sleep(Duration::from_secs(1)).await;
|
||||||
|
|
||||||
|
// TODO: why is this always empty?!
|
||||||
|
let docker_inspect_output = AsyncCommand::new("docker")
|
||||||
|
.args(["inspect", &db_container_name])
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let docker_inspect_json = String::from_utf8(docker_inspect_output.stdout).unwrap();
|
||||||
|
|
||||||
|
trace!(%docker_inspect_json);
|
||||||
|
|
||||||
|
let docker_inspect_json: serde_json::Value =
|
||||||
|
serde_json::from_str(&docker_inspect_json).unwrap();
|
||||||
|
|
||||||
|
let mysql_ports = docker_inspect_json
|
||||||
|
.get(0)
|
||||||
|
.unwrap()
|
||||||
|
.get("NetworkSettings")
|
||||||
|
.unwrap()
|
||||||
|
.get("Ports")
|
||||||
|
.unwrap()
|
||||||
|
.get("3306/tcp")
|
||||||
|
.unwrap()
|
||||||
|
.get(0)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
trace!(?mysql_ports);
|
||||||
|
|
||||||
|
let mysql_port: u64 = mysql_ports
|
||||||
|
.get("HostPort")
|
||||||
|
.expect("unable to determine mysql port")
|
||||||
|
.as_str()
|
||||||
|
.unwrap()
|
||||||
|
.parse()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mysql_ip = mysql_ports
|
||||||
|
.get("HostIp")
|
||||||
|
.and_then(|x| x.as_str())
|
||||||
|
.expect("unable to determine mysql ip");
|
||||||
|
// let mysql_ip = "localhost";
|
||||||
|
// let mysql_ip = "127.0.0.1";
|
||||||
|
|
||||||
|
let db_url = format!(
|
||||||
|
"mysql://root:{}@{}:{}/web3_proxy_test",
|
||||||
|
password, mysql_ip, mysql_port
|
||||||
|
);
|
||||||
|
|
||||||
|
info!(%db_url, "waiting for start");
|
||||||
|
|
||||||
|
db_data.url = Some(db_url.clone());
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
let max_wait = Duration::from_secs(30);
|
||||||
|
loop {
|
||||||
|
if start.elapsed() > max_wait {
|
||||||
|
panic!("db took too long to start");
|
||||||
|
}
|
||||||
|
|
||||||
|
if TcpStream::connect(format!("{}:{}", mysql_ip, mysql_port))
|
||||||
|
.await
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
// not open wait. sleep and then try again
|
||||||
|
sleep(Duration::from_secs(1)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!(%db_url, "db is ready for connections");
|
||||||
|
|
||||||
|
// try to migrate
|
||||||
|
let _ = get_migrated_db(db_url, 1, 1)
|
||||||
|
.await
|
||||||
|
.expect("failed migration");
|
||||||
|
|
||||||
|
Some(db_data)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let db_url = db.as_ref().and_then(|x| x.url.clone());
|
||||||
|
|
||||||
// make a test TopConfig
|
// make a test TopConfig
|
||||||
// TODO: test influx
|
// TODO: test influx
|
||||||
// TODO: test redis
|
// TODO: test redis
|
||||||
let top_config = TopConfig {
|
let top_config = TopConfig {
|
||||||
app: AppConfig {
|
app: AppConfig {
|
||||||
chain_id: 31337,
|
chain_id: 31337,
|
||||||
// TODO: [make sqlite work](<https://www.sea-ql.org/SeaORM/docs/write-test/sqlite/>)
|
db_url,
|
||||||
// db_url: Some("sqlite::memory:".into()),
|
|
||||||
default_user_max_requests_per_period: Some(6_000_000),
|
default_user_max_requests_per_period: Some(6_000_000),
|
||||||
deposit_factory_contract: Address::from_str(
|
deposit_factory_contract: Address::from_str(
|
||||||
"4e3BC2054788De923A04936C6ADdB99A05B0Ea36",
|
"4e3BC2054788De923A04936C6ADdB99A05B0Ea36",
|
||||||
@ -111,7 +258,8 @@ impl TestApp {
|
|||||||
let mut frontend_port = frontend_port_arc.load(Ordering::Relaxed);
|
let mut frontend_port = frontend_port_arc.load(Ordering::Relaxed);
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
while frontend_port == 0 {
|
while frontend_port == 0 {
|
||||||
if start.elapsed() > Duration::from_secs(1) {
|
// we have to give it some time because it might have to do migrations
|
||||||
|
if start.elapsed() > Duration::from_secs(10) {
|
||||||
panic!("took too long to start!");
|
panic!("took too long to start!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +274,8 @@ impl TestApp {
|
|||||||
Self {
|
Self {
|
||||||
anvil,
|
anvil,
|
||||||
anvil_provider,
|
anvil_provider,
|
||||||
handle: Mutex::new(Some(handle)),
|
db,
|
||||||
|
proxy_handle: Mutex::new(Some(handle)),
|
||||||
proxy_provider,
|
proxy_provider,
|
||||||
shutdown_sender,
|
shutdown_sender,
|
||||||
}
|
}
|
||||||
@ -136,18 +285,20 @@ impl TestApp {
|
|||||||
self.shutdown_sender.send(())
|
self.shutdown_sender.send(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub async fn wait(&self) {
|
pub async fn wait(&self) {
|
||||||
// TODO: lock+take feels weird, but it works
|
|
||||||
let handle = self.handle.lock().take();
|
|
||||||
|
|
||||||
if let Some(handle) = handle {
|
|
||||||
let _ = self.stop();
|
let _ = self.stop();
|
||||||
|
|
||||||
|
// TODO: lock+take feels weird, but it works
|
||||||
|
let handle = self.proxy_handle.lock().take();
|
||||||
|
|
||||||
|
if let Some(handle) = handle {
|
||||||
info!("waiting for the app to stop...");
|
info!("waiting for the app to stop...");
|
||||||
handle.await.unwrap().unwrap();
|
handle.await.unwrap().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn wallet(&self, id: usize) -> LocalWallet {
|
pub fn wallet(&self, id: usize) -> LocalWallet {
|
||||||
self.anvil.keys()[id].clone().into()
|
self.anvil.keys()[id].clone().into()
|
||||||
}
|
}
|
||||||
@ -160,3 +311,14 @@ impl Drop for TestApp {
|
|||||||
// TODO: do we care about waiting for it to stop? it will slow our tests down so we probably only care about waiting in some tests
|
// TODO: do we care about waiting for it to stop? it will slow our tests down so we probably only care about waiting in some tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for DbData {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// TODO: this doesn't seem to run
|
||||||
|
info!(%self.container_name, "killing db");
|
||||||
|
|
||||||
|
let _ = SyncCommand::new("docker")
|
||||||
|
.args(["kill", "-s", "9", &self.container_name])
|
||||||
|
.output();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,26 +2,29 @@ mod common;
|
|||||||
|
|
||||||
use crate::common::TestApp;
|
use crate::common::TestApp;
|
||||||
|
|
||||||
#[ignore]
|
#[cfg_attr(not(feature = "tests-needing-docker"), ignore)]
|
||||||
|
#[ignore = "under construction"]
|
||||||
#[test_log::test(tokio::test)]
|
#[test_log::test(tokio::test)]
|
||||||
async fn test_admin_imitate_user() {
|
async fn test_admin_imitate_user() {
|
||||||
let x = TestApp::spawn().await;
|
let x = TestApp::spawn(true).await;
|
||||||
|
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore]
|
#[cfg_attr(not(feature = "tests-needing-docker"), ignore)]
|
||||||
|
#[ignore = "under construction"]
|
||||||
#[test_log::test(tokio::test)]
|
#[test_log::test(tokio::test)]
|
||||||
async fn test_admin_grant_credits() {
|
async fn test_admin_grant_credits() {
|
||||||
let x = TestApp::spawn().await;
|
let x = TestApp::spawn(true).await;
|
||||||
|
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore]
|
#[cfg_attr(not(feature = "tests-needing-docker"), ignore)]
|
||||||
|
#[ignore = "under construction"]
|
||||||
#[test_log::test(tokio::test)]
|
#[test_log::test(tokio::test)]
|
||||||
async fn test_admin_change_user_tier() {
|
async fn test_admin_change_user_tier() {
|
||||||
let x = TestApp::spawn().await;
|
let x = TestApp::spawn(true).await;
|
||||||
|
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,16 @@ use tokio::{
|
|||||||
};
|
};
|
||||||
use web3_proxy::rpcs::blockchain::ArcBlock;
|
use web3_proxy::rpcs::blockchain::ArcBlock;
|
||||||
|
|
||||||
|
#[cfg_attr(not(feature = "tests-needing-docker"), ignore)]
|
||||||
|
#[ignore = "under construction"]
|
||||||
|
#[test_log::test(tokio::test)]
|
||||||
|
async fn it_migrates_the_db() {
|
||||||
|
TestApp::spawn(true).await;
|
||||||
|
}
|
||||||
|
|
||||||
#[test_log::test(tokio::test)]
|
#[test_log::test(tokio::test)]
|
||||||
async fn it_starts_and_stops() {
|
async fn it_starts_and_stops() {
|
||||||
let x = TestApp::spawn().await;
|
let x = TestApp::spawn(false).await;
|
||||||
|
|
||||||
let anvil_provider = &x.anvil_provider;
|
let anvil_provider = &x.anvil_provider;
|
||||||
let proxy_provider = &x.proxy_provider;
|
let proxy_provider = &x.proxy_provider;
|
||||||
|
@ -1,21 +1,36 @@
|
|||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
use crate::common::TestApp;
|
use crate::common::TestApp;
|
||||||
|
use ethers::signers::Signer;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
#[ignore]
|
/// TODO: 191 and the other message formats in another test
|
||||||
|
#[cfg_attr(not(feature = "tests-needing-docker"), ignore)]
|
||||||
#[test_log::test(tokio::test)]
|
#[test_log::test(tokio::test)]
|
||||||
async fn test_log_in_and_out() {
|
async fn test_log_in_and_out() {
|
||||||
let x = TestApp::spawn().await;
|
let x = TestApp::spawn(true).await;
|
||||||
|
|
||||||
let w = x.wallet(0);
|
let w = x.wallet(0);
|
||||||
|
|
||||||
|
let login_url = format!("{}user/login/{:?}", x.proxy_provider.url(), w.address());
|
||||||
|
let login_response = reqwest::get(login_url).await.unwrap();
|
||||||
|
|
||||||
|
info!(?login_response);
|
||||||
|
|
||||||
|
// TODO: sign the message and POST it
|
||||||
|
|
||||||
|
// TODO: get bearer token out of response
|
||||||
|
|
||||||
|
// TODO: log out
|
||||||
|
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ignore]
|
#[cfg_attr(not(feature = "tests-needing-docker"), ignore)]
|
||||||
|
#[ignore = "under construction"]
|
||||||
#[test_log::test(tokio::test)]
|
#[test_log::test(tokio::test)]
|
||||||
async fn test_referral_bonus() {
|
async fn test_referral_bonus() {
|
||||||
let x = TestApp::spawn().await;
|
let x = TestApp::spawn(true).await;
|
||||||
|
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user