chore: import upstream snapshot with attribution
CI / compile_and_lint (push) Failing after 0s
CI / docker_build (linux/amd64, -linux-amd64-duckdb, duckdb) (push) Failing after 0s
CI / docker_build (linux/arm64, -linux-arm64, minimal) (push) Failing after 2s
CI / docker_build (linux/arm64, -linux-arm64-duckdb, duckdb) (push) Failing after 1s
CI / docker_build (linux/amd64, minimal) (push) Failing after 1s
CI / test (, sqlite, sqlite::memory:) (push) Has been skipped
CI / test (mssql, mssql, mssql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (mysql, mysql, mysql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (oracle, oracle, Driver=Oracle 21 ODBC driver;Dbq=//127.0.0.1:1521/FREEPDB1;Uid=root;Pwd=Password123!) (push) Has been skipped
CI / test (postgres, odbc, Driver=PostgreSQL Unicode;Server=127.0.0.1;Port=5432;Database=sqlpage;UID=root;PWD=Password123!, true) (push) Has been skipped
CI / test (postgres, postgres, postgres://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / playwright (push) Has been skipped
CI / docker_build (linux/arm/v7, -linux-arm-v7, minimal) (push) Failing after 0s
CI / hurl_examples (push) Failing after 8s
deploy website / deploy_official_site (push) Failing after 1s
CI / hurl (${{ matrix.example }}) (push) Has been skipped
CI / docker_push (duckdb) (push) Has been cancelled
CI / docker_push (minimal) (push) Has been cancelled
CI / windows_test (push) Has been cancelled
CI / compile_and_lint (push) Failing after 0s
CI / docker_build (linux/amd64, -linux-amd64-duckdb, duckdb) (push) Failing after 0s
CI / docker_build (linux/arm64, -linux-arm64, minimal) (push) Failing after 2s
CI / docker_build (linux/arm64, -linux-arm64-duckdb, duckdb) (push) Failing after 1s
CI / docker_build (linux/amd64, minimal) (push) Failing after 1s
CI / test (, sqlite, sqlite::memory:) (push) Has been skipped
CI / test (mssql, mssql, mssql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (mysql, mysql, mysql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (oracle, oracle, Driver=Oracle 21 ODBC driver;Dbq=//127.0.0.1:1521/FREEPDB1;Uid=root;Pwd=Password123!) (push) Has been skipped
CI / test (postgres, odbc, Driver=PostgreSQL Unicode;Server=127.0.0.1;Port=5432;Database=sqlpage;UID=root;PWD=Password123!, true) (push) Has been skipped
CI / test (postgres, postgres, postgres://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / playwright (push) Has been skipped
CI / docker_build (linux/arm/v7, -linux-arm-v7, minimal) (push) Failing after 0s
CI / hurl_examples (push) Failing after 8s
deploy website / deploy_official_site (push) Failing after 1s
CI / hurl (${{ matrix.example }}) (push) Has been skipped
CI / docker_push (duckdb) (push) Has been cancelled
CI / docker_push (minimal) (push) Has been cancelled
CI / windows_test (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use actix_web::{
|
||||
App, HttpResponse, HttpServer,
|
||||
dev::{ServiceRequest, fn_service},
|
||||
http::header,
|
||||
http::header::ContentType,
|
||||
test::{self, TestRequest},
|
||||
web,
|
||||
web::Data,
|
||||
};
|
||||
use sqlpage::{
|
||||
AppState,
|
||||
app_config::{AppConfig, test_database_url},
|
||||
telemetry,
|
||||
webserver::http::{form_config, main_handler, payload_config},
|
||||
};
|
||||
use tokio::sync::oneshot;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
pub async fn get_request_to_with_data(
|
||||
path: &str,
|
||||
data: Data<AppState>,
|
||||
) -> actix_web::Result<TestRequest> {
|
||||
Ok(test::TestRequest::get()
|
||||
.uri(path)
|
||||
.insert_header(ContentType::plaintext())
|
||||
.insert_header(header::Accept::html())
|
||||
.app_data(payload_config(&data))
|
||||
.app_data(form_config(&data))
|
||||
.app_data(data))
|
||||
}
|
||||
|
||||
pub async fn get_request_to(path: &str) -> actix_web::Result<TestRequest> {
|
||||
let data = make_app_data().await;
|
||||
get_request_to_with_data(path, data).await
|
||||
}
|
||||
|
||||
pub async fn make_app_data_from_config(config: AppConfig) -> Data<AppState> {
|
||||
let state = AppState::init(&config).await.unwrap();
|
||||
Data::new(state)
|
||||
}
|
||||
|
||||
pub async fn make_app_data() -> Data<AppState> {
|
||||
init_log();
|
||||
let config = test_config();
|
||||
make_app_data_from_config(config).await
|
||||
}
|
||||
|
||||
pub async fn req_path(
|
||||
path: impl AsRef<str>,
|
||||
) -> Result<actix_web::dev::ServiceResponse, actix_web::Error> {
|
||||
let req = get_request_to(path.as_ref()).await?.to_srv_request();
|
||||
main_handler(req).await
|
||||
}
|
||||
|
||||
const REQ_TIMEOUT: Duration = Duration::from_secs(8);
|
||||
pub async fn req_path_with_app_data(
|
||||
path: impl AsRef<str>,
|
||||
app_data: Data<AppState>,
|
||||
) -> anyhow::Result<actix_web::dev::ServiceResponse> {
|
||||
req_path_with_app_data_and_accept(path, app_data, header::Accept::html()).await
|
||||
}
|
||||
|
||||
pub async fn req_path_with_app_data_json(
|
||||
path: impl AsRef<str>,
|
||||
app_data: Data<AppState>,
|
||||
) -> anyhow::Result<actix_web::dev::ServiceResponse> {
|
||||
req_path_with_app_data_and_accept(path, app_data, header::Accept::json()).await
|
||||
}
|
||||
|
||||
async fn req_path_with_app_data_and_accept(
|
||||
path: impl AsRef<str>,
|
||||
app_data: Data<AppState>,
|
||||
accept: header::Accept,
|
||||
) -> anyhow::Result<actix_web::dev::ServiceResponse> {
|
||||
let path = path.as_ref();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(path)
|
||||
.app_data(app_data)
|
||||
.insert_header(("cookie", "test_cook=123"))
|
||||
.insert_header(("authorization", "Basic dGVzdDp0ZXN0"))
|
||||
.insert_header(accept)
|
||||
.to_srv_request();
|
||||
let resp = tokio::time::timeout(REQ_TIMEOUT, main_handler(req))
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("Request to {path} timed out: {e}"))?
|
||||
.map_err(|e| {
|
||||
anyhow::anyhow!(
|
||||
"Request to {path} failed with status {}: {e:#}",
|
||||
e.as_response_error().status_code()
|
||||
)
|
||||
})?;
|
||||
Ok(resp)
|
||||
}
|
||||
|
||||
pub fn test_config() -> AppConfig {
|
||||
let db_url = test_database_url();
|
||||
serde_json::from_str::<AppConfig>(&format!(
|
||||
r#"{{
|
||||
"database_url": "{db_url}",
|
||||
"max_database_pool_connections": 1,
|
||||
"database_connection_retries": 3,
|
||||
"database_connection_acquire_timeout_seconds": 15,
|
||||
"allow_exec": true,
|
||||
"max_uploaded_file_size": 123456,
|
||||
"listen_on": "111.111.111.111:1",
|
||||
"system_root_ca_certificates" : false
|
||||
}}"#
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn init_log() {
|
||||
telemetry::init_test_logging();
|
||||
}
|
||||
|
||||
fn format_request_line_and_headers(req: &ServiceRequest) -> String {
|
||||
let mut out = format!("{} {}", req.method(), req.uri());
|
||||
let mut headers: Vec<_> = req.headers().iter().collect();
|
||||
headers.sort_by_key(|(k, _)| k.as_str());
|
||||
for (k, v) in headers {
|
||||
if k.as_str().eq_ignore_ascii_case("date") {
|
||||
continue;
|
||||
}
|
||||
out.push_str(&format!("|{k}: {}", v.to_str().unwrap_or("?")));
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
async fn format_body(req: &mut ServiceRequest) -> Vec<u8> {
|
||||
req.extract::<web::Bytes>()
|
||||
.await
|
||||
.map(|b| b.to_vec())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn build_echo_response(body: Vec<u8>, meta: String) -> HttpResponse {
|
||||
let mut resp = meta.into_bytes();
|
||||
resp.push(b'|');
|
||||
resp.extend_from_slice(&body);
|
||||
HttpResponse::Ok()
|
||||
.insert_header((header::DATE, "Mon, 24 Feb 2025 12:00:00 GMT"))
|
||||
.insert_header((header::CONTENT_TYPE, "text/plain"))
|
||||
.body(resp)
|
||||
}
|
||||
|
||||
pub fn start_echo_server(shutdown: oneshot::Receiver<()>) -> (JoinHandle<()>, u16) {
|
||||
let listener = std::net::TcpListener::bind("localhost:0").unwrap();
|
||||
let port = listener.local_addr().unwrap().port();
|
||||
let server = HttpServer::new(|| {
|
||||
App::new().default_service(fn_service(|mut req: ServiceRequest| async move {
|
||||
let meta = format_request_line_and_headers(&req);
|
||||
let body = format_body(&mut req).await;
|
||||
let resp = build_echo_response(body, meta);
|
||||
Ok(req.into_response(resp))
|
||||
}))
|
||||
})
|
||||
.workers(1)
|
||||
.listen(listener)
|
||||
.unwrap()
|
||||
.shutdown_timeout(1)
|
||||
.run();
|
||||
let handle = tokio::spawn(async move {
|
||||
tokio::select! {
|
||||
_ = server => {},
|
||||
_ = shutdown => {},
|
||||
}
|
||||
});
|
||||
(handle, port)
|
||||
}
|
||||
Reference in New Issue
Block a user