dynamic port choice
also: better error messages in tests
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
<div class="text-muted">
|
||||
<p>We are sorry, but an error occurred while generating this page. You should contact the site's
|
||||
administrator.</p>
|
||||
<pre class="mt-2"><code>{{description}}</code></pre>
|
||||
<pre class="mt-2"><code class="sqlpage-error-description">{{description}}</code></pre>
|
||||
{{#if backtrace}}
|
||||
<details class="mt-2">
|
||||
<summary>Backtrace</summary>
|
||||
|
||||
+7
-4
@@ -137,7 +137,9 @@ fn build_echo_response(body: Vec<u8>, meta: String) -> HttpResponse {
|
||||
.body(resp)
|
||||
}
|
||||
|
||||
pub fn start_echo_server(shutdown: oneshot::Receiver<()>) -> JoinHandle<()> {
|
||||
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);
|
||||
@@ -146,14 +148,15 @@ pub fn start_echo_server(shutdown: oneshot::Receiver<()>) -> JoinHandle<()> {
|
||||
Ok(req.into_response(resp))
|
||||
}))
|
||||
})
|
||||
.bind("localhost:62802")
|
||||
.listen(listener)
|
||||
.unwrap()
|
||||
.shutdown_timeout(1)
|
||||
.run();
|
||||
tokio::spawn(async move {
|
||||
let handle = tokio::spawn(async move {
|
||||
tokio::select! {
|
||||
_ = server => {},
|
||||
_ = shutdown => {},
|
||||
}
|
||||
})
|
||||
});
|
||||
(handle, port)
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,10 +1,11 @@
|
||||
set url = 'http://localhost:' || $echo_port || '/post';
|
||||
set res = sqlpage.fetch(json_object(
|
||||
'method', 'POST',
|
||||
'url', 'http://localhost:62802/post',
|
||||
'url', $url,
|
||||
'headers', json_object('x-custom', '1'),
|
||||
'body', json_array('hello', 'world')
|
||||
));
|
||||
set expected = 'POST /post|accept-encoding: br, gzip, deflate, zstd|content-length: 17|content-type: application/json|host: localhost:62802|user-agent: sqlpage|x-custom: 1|["hello","world"]';
|
||||
set expected = 'POST /post|accept-encoding: br, gzip, deflate, zstd|content-length: 17|content-type: application/json|host: localhost:' || $echo_port || '|user-agent: sqlpage|x-custom: 1|["hello","world"]';
|
||||
select 'text' as component,
|
||||
case $res
|
||||
when $expected then 'It works !'
|
||||
@@ -1,15 +1,12 @@
|
||||
set res = sqlpage.fetch('{
|
||||
"method": "POST",
|
||||
"url": "http://localhost:62802/post",
|
||||
"headers": {"x-custom": "1"},
|
||||
"body": {"hello": "world"}
|
||||
}');
|
||||
set expected = 'POST /post|accept-encoding: br, gzip, deflate, zstd|content-length: 18|content-type: application/json|host: localhost:62802|user-agent: sqlpage|x-custom: 1|{"hello": "world"}';
|
||||
set url = 'http://localhost:' || $echo_port || '/post';
|
||||
set fetch_request = '{"method": "POST", "url": "' || $url || '", "headers": {"x-custom": "1"}, "body": {"hello": "world"}}';
|
||||
set res = sqlpage.fetch($fetch_request);
|
||||
set expected = 'POST /post|accept-encoding: br, gzip, deflate, zstd|content-length: 18|content-type: application/json|host: localhost:' || $echo_port || '|user-agent: sqlpage|x-custom: 1|{"hello": "world"}';
|
||||
select 'text' as component,
|
||||
case $res
|
||||
when $expected then 'It works !'
|
||||
else 'It failed ! Expected:
|
||||
' || $expected || '
|
||||
' || COALESCE($expected, 'null') || '
|
||||
Got:
|
||||
' || $res
|
||||
' || COALESCE($res, 'null')
|
||||
end as contents;
|
||||
@@ -1,4 +1,5 @@
|
||||
set res = sqlpage.fetch('http://localhost:62802/hello_world')
|
||||
set url = 'http://localhost:' || $echo_port || '/hello_world';
|
||||
set res = sqlpage.fetch($url);
|
||||
select 'text' as component,
|
||||
case
|
||||
when $res LIKE 'GET /hello_world%' then 'It works !'
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
set res = sqlpage.fetch_with_meta('{
|
||||
set url = 'http://localhost:' || $echo_port || '/hello_world';
|
||||
set fetch_req = '{
|
||||
"method": "PUT",
|
||||
"url": "http://localhost:62802/hello_world",
|
||||
"url": "' || $url || '",
|
||||
"headers": {
|
||||
"user-agent": "myself"
|
||||
}
|
||||
}');
|
||||
}';
|
||||
set res = sqlpage.fetch_with_meta($fetch_req);
|
||||
|
||||
select 'text' as component,
|
||||
case
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
set actual = sqlpage.link('', sqlpage.variables('get'));
|
||||
set expected = '?x=1';
|
||||
SELECT
|
||||
'text' AS component,
|
||||
CASE sqlpage.link('', sqlpage.variables('get'))
|
||||
WHEN '?x=1' THEN
|
||||
CASE $actual
|
||||
WHEN $expected THEN
|
||||
'It works !'
|
||||
ELSE
|
||||
'Expected "?x=1"'
|
||||
'Expected ' || COALESCE($expected, 'null') || ' but got ' || COALESCE($actual, 'null')
|
||||
END AS contents
|
||||
;
|
||||
@@ -12,13 +12,13 @@ async fn run_all_sql_test_files() {
|
||||
// Create a shutdown channel for the echo server
|
||||
let (shutdown_tx, shutdown_rx) = oneshot::channel();
|
||||
// Start echo server once for all tests
|
||||
let echo_handle = crate::common::start_echo_server(shutdown_rx);
|
||||
let (echo_handle, port) = crate::common::start_echo_server(shutdown_rx);
|
||||
|
||||
// Wait for echo server to be ready
|
||||
wait_for_echo_server().await;
|
||||
wait_for_echo_server(port).await;
|
||||
|
||||
for test_file in test_files {
|
||||
let test_result = run_sql_test(&test_file, &app_data, &echo_handle).await;
|
||||
let test_result = run_sql_test(&test_file, &app_data, &echo_handle, port).await;
|
||||
assert_test_result(test_result, &test_file);
|
||||
}
|
||||
|
||||
@@ -31,13 +31,13 @@ async fn run_all_sql_test_files() {
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_echo_server() {
|
||||
async fn wait_for_echo_server(port: u16) {
|
||||
let client = awc::Client::default();
|
||||
let start = std::time::Instant::now();
|
||||
let timeout = Duration::from_secs(5);
|
||||
|
||||
while start.elapsed() < timeout {
|
||||
match client.get("http://localhost:62802/").send().await {
|
||||
match client.get(format!("http://localhost:{port}/")).send().await {
|
||||
Ok(_) => return,
|
||||
Err(_) => {
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
@@ -64,13 +64,20 @@ fn get_sql_test_files() -> Vec<std::path::PathBuf> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
use std::fmt::Write;
|
||||
|
||||
async fn run_sql_test(
|
||||
test_file: &std::path::Path,
|
||||
app_data: &actix_web::web::Data<AppState>,
|
||||
_echo_handle: &JoinHandle<()>,
|
||||
port: u16,
|
||||
) -> anyhow::Result<String> {
|
||||
let test_file_path = test_file.to_string_lossy().replace('\\', "/");
|
||||
let req_str = format!("/{test_file_path}?x=1");
|
||||
let mut query_params = "x=1".to_string();
|
||||
if test_file_path.contains("fetch") {
|
||||
write!(query_params, "&echo_port={port}").unwrap();
|
||||
}
|
||||
let req_str = format!("/{test_file_path}?{query_params}");
|
||||
|
||||
let resp = tokio::time::timeout(
|
||||
Duration::from_secs(5),
|
||||
@@ -114,11 +121,23 @@ fn assert_html_response(body: &str, test_file: &std::path::Path) {
|
||||
}
|
||||
|
||||
fn assert_it_works_tests(body: &str, lowercase_body: &str, test_file: &std::path::Path) {
|
||||
if body.contains("<code class=\"sqlpage-error-description\">") {
|
||||
let error_desc = body
|
||||
.split("<code class=\"sqlpage-error-description\">")
|
||||
.nth(1)
|
||||
.and_then(|s| s.split("</code>").next())
|
||||
.unwrap_or("Unknown error");
|
||||
panic!(
|
||||
"\n\n❌ TEST FAILED: {} ❌\n\nFull Response:\n{}\n\nError Description: {}\n",
|
||||
test_file.display(),
|
||||
error_desc,
|
||||
body
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
body.contains("It works !"),
|
||||
"{}\n{}\nexpected to contain: It works !",
|
||||
test_file.display(),
|
||||
body
|
||||
"{body}\n❌ Error in file {test_file:?} ❌\n",
|
||||
);
|
||||
assert!(
|
||||
!lowercase_body.contains("error"),
|
||||
|
||||
Reference in New Issue
Block a user