100 lines
2.9 KiB
Rust
100 lines
2.9 KiB
Rust
use crate::common::docker::DOCKER_EXPOSED_PORT;
|
|
use crate::common::expected::Expected;
|
|
use http::{header, HeaderMap, StatusCode};
|
|
use reqwest::Client;
|
|
use serde_json::Value as JsonValue;
|
|
use std::time::{Duration, SystemTime};
|
|
use tokio::time::sleep;
|
|
use tracing::{debug, error, warn};
|
|
|
|
// A very basic Rest client.
|
|
// The goal is to have a client that can connect to any version of SurrealDB.
|
|
// Using the REST API / sql endpoint
|
|
pub struct RestClient {
|
|
client: Client,
|
|
url: String,
|
|
user: String,
|
|
pass: String,
|
|
}
|
|
|
|
impl RestClient {
|
|
pub fn new(ns: &str, db: &str, user: &str, pass: &str) -> Self {
|
|
let mut headers = HeaderMap::new();
|
|
headers.insert("NS", ns.parse().unwrap());
|
|
headers.insert("DB", db.parse().unwrap());
|
|
headers.insert(header::ACCEPT, "application/json".parse().unwrap());
|
|
let client = Client::builder()
|
|
.connect_timeout(Duration::from_millis(10))
|
|
.default_headers(headers)
|
|
.build()
|
|
.expect("Client::builder()...build()");
|
|
Self {
|
|
client,
|
|
url: format!("http://127.0.0.1:{DOCKER_EXPOSED_PORT}/sql"),
|
|
user: user.to_string(),
|
|
pass: pass.to_string(),
|
|
}
|
|
}
|
|
|
|
pub async fn wait_for_connection(self, time_out: &Duration) -> Option<Self> {
|
|
sleep(Duration::from_secs(2)).await;
|
|
let start = SystemTime::now();
|
|
while start.elapsed().unwrap().le(time_out) {
|
|
sleep(Duration::from_secs(2)).await;
|
|
if let Some(r) = self.query("INFO FOR ROOT").await {
|
|
if r.status() == StatusCode::OK {
|
|
return Some(self);
|
|
}
|
|
}
|
|
warn!("DB not yet responding");
|
|
sleep(Duration::from_secs(2)).await;
|
|
}
|
|
None
|
|
}
|
|
|
|
pub async fn query(&self, q: &str) -> Option<reqwest::Response> {
|
|
match self
|
|
.client
|
|
.post(&self.url)
|
|
.basic_auth(&self.user, Some(&self.pass))
|
|
.body(q.to_string())
|
|
.send()
|
|
.await
|
|
{
|
|
Ok(r) => Some(r),
|
|
Err(e) => {
|
|
error!("{e}");
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn checked_query(&self, q: &str, expected: &Expected) {
|
|
let r = self.query(q).await.unwrap_or_else(|| panic!("No response for {q}"));
|
|
assert_eq!(
|
|
r.status(),
|
|
StatusCode::OK,
|
|
"Wrong response for {q} -> {}",
|
|
r.text().await.expect(q)
|
|
);
|
|
// Convert the result to JSON
|
|
let j: JsonValue = r.json().await.expect(q);
|
|
debug!("{q} => {j:#}");
|
|
// The result should be an array
|
|
let results_with_status = j.as_array().expect(q);
|
|
assert_eq!(results_with_status.len(), 1, "Wrong number of results on query {q}");
|
|
let result_with_status = &results_with_status[0];
|
|
// Check the status
|
|
let status =
|
|
result_with_status.get("status").unwrap_or_else(|| panic!("No status on query: {q}"));
|
|
assert_eq!(status.as_str(), Some("OK"), "Wrong status for {q} => {status:#}");
|
|
// Extract the results
|
|
let results =
|
|
result_with_status.get("result").unwrap_or_else(|| panic!("No result for query: {q}"));
|
|
if !matches!(expected, Expected::Any) {
|
|
// Check the results
|
|
let results = results.as_array().expect(q);
|
|
expected.check_results(q, results);
|
|
}
|
|
}
|
|
}
|