#[cfg(any(feature = "csv_ds", feature = "gpkg_ds", feature = "pg_ds"))]
pub mod country;
#[cfg(any(feature = "csv_ds", feature = "gpkg_ds", feature = "pg_ds"))]
mod place;
#[cfg(any(feature = "csv_ds", feature = "gpkg_ds", feature = "pg_ds"))]
mod river;
#[cfg(feature = "pg_ds")]
pub(crate) use {country::CountryPG, place::PlacePG, river::RiverPG};
#[cfg(feature = "csv_ds")]
pub(crate) use {
country::{CountryCSV, countries},
place::{PlaceCSV, places},
river::RiverCSV,
};
#[cfg(feature = "gpkg_ds")]
pub(crate) use {
country::{CountryGPkg, countries_gpkg},
place::PlaceGPkg,
river::RiverGPkg,
};
use futures::TryStreamExt;
use ogc_cql2::{
Context, Evaluator, ExEvaluator, Expression, IterableDS, MyError, Outcome, Resource,
StreamableDS,
};
use rand::{
RngExt,
distr::{
Alphanumeric,
uniform::{UniformChar, UniformSampler},
},
};
use std::error::Error;
#[cfg(feature = "gpkg_ds")]
const GPKG_URL: &str = "sqlite:tests/samples/data/ne110m4cql2.gpkg";
#[cfg(feature = "pg_ds")]
const PG_DB_NAME: &str = "cql2";
#[allow(dead_code)]
pub(crate) fn harness<T: IterableDS<Err = MyError>>(
ds: T,
predicates: &[(&str, u32)],
) -> Result<(), Box<dyn Error>>
where
Resource: TryFrom<<T as IterableDS>::Item>,
{
let mut evaluators = vec![];
let mut expected = vec![];
let mut actual = vec![];
let shared_ctx = Context::try_with_crs("epsg:4326")?.freeze();
for (input, success_count) in predicates {
let mut evaluator = ExEvaluator::new(shared_ctx.clone());
let expr = Expression::try_from_text(input)?;
evaluator.setup(expr)?;
evaluators.push(evaluator);
expected.push(success_count);
actual.push(0);
}
for x in ds.iter()? {
let feature = x?;
let resource = Resource::try_from(feature)
.map_err(|_| MyError::Runtime("Failed converting iterable item to Resource".into()))?;
for (p_ndx, evaluator) in evaluators.iter().enumerate() {
let res = evaluator
.evaluate(&resource)
.expect(&format!("Failed evaluating resource"));
if matches!(res, Outcome::T) {
actual[p_ndx] += 1;
}
}
}
let mut failures = 0;
for (ndx, count) in actual.iter().enumerate() {
let n = expected[ndx];
if count != n {
tracing::error!("Failed predicate #{ndx} - actual/expected: {count} / {n}");
failures += 1;
}
}
assert_eq!(failures, 0);
Ok(())
}
#[allow(dead_code)]
pub(crate) async fn harness_gpkg<T: StreamableDS<Err = MyError>>(
ds: T,
predicates: &[(&str, u32)],
) -> Result<(), Box<dyn Error>> {
let mut evaluators = vec![];
let mut expected = vec![];
let mut actual = vec![];
let shared_ctx = Context::try_with_crs("epsg:4326")?.freeze();
for (input, success_count) in predicates {
let mut evaluator = ExEvaluator::new(shared_ctx.clone());
let expr = Expression::try_from_text(input)?;
evaluator.setup(expr)?;
evaluators.push(evaluator);
expected.push(success_count);
actual.push(0);
}
let mut stream = ds.stream().await?;
while let Some(resource) = stream.try_next().await? {
for (p_ndx, evaluator) in evaluators.iter().enumerate() {
let res = evaluator
.evaluate(&resource)
.expect(&format!("Failed evaluating resource"));
if matches!(res, Outcome::T) {
actual[p_ndx] += 1;
}
}
}
let mut failures = 0;
for (ndx, count) in actual.iter().enumerate() {
let n = expected[ndx];
if count != n {
tracing::error!("Failed predicate #{ndx} - actual/expected: {count} / {n}");
failures += 1;
}
}
assert_eq!(failures, 0);
Ok(())
}
#[allow(dead_code)]
pub(crate) async fn harness_sql<T: StreamableDS<Err = MyError>>(
ds: T,
predicates: &[(&str, u32)],
) -> Result<(), Box<dyn Error>> {
for (ndx, (filter, expected)) in predicates.iter().enumerate() {
let exp = Expression::try_from_text(&filter)?;
let mut actual = 0;
let mut stream = ds.fetch_where(&exp).await?;
while let Some(_) = stream.try_next().await? {
actual += 1;
}
assert_eq!(actual, *expected, "Failed predicate #{ndx}");
}
Ok(())
}
pub(crate) fn random_ascii_word() -> String {
let mut rng = rand::rng();
let size: usize = rng.random_range(5..15);
(0..size)
.map(|_| rng.sample(Alphanumeric) as char)
.collect()
}
pub(crate) fn random_unicode_word() -> String {
let mut rng = rand::rng();
let dist = UniformChar::new_inclusive('\u{0041}', '\u{10FFFF}')
.expect("Failed setting up uniform distribution");
let size: usize = rng.random_range(5..15);
(0..size).map(|_| dist.sample(&mut rng)).collect()
}