use std::fs;
use std::path::{Path, PathBuf};
use orion_variate::EnvDict;
use wp_knowledge::facade as kdb;
use wp_model_core::model::DataField;
fn uniq_tmp_dir() -> PathBuf {
use rand::{Rng, rng};
use std::time::{SystemTime, UNIX_EPOCH};
let ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
let rnd: u64 = rng().next_u64();
std::env::current_dir()
.unwrap()
.join(format!(".tmp_udf_{}_{}", ts, rnd))
}
#[ignore = "ci error"]
#[test]
fn load_zone_with_udf_and_query() {
let root = uniq_tmp_dir();
let models = root.join("models").join("knowledge");
let zone_dir = models.join("zone");
fs::create_dir_all(&zone_dir).unwrap();
let knowdb = r#"
version = 2
[csv]
has_header = false
[[tables]]
name = "zone"
columns.by_index = [0,1,2]
[tables.expected_rows]
min = 1
"#;
fs::write(models.join("knowdb.toml"), knowdb).unwrap();
let create_sql = r#"
CREATE TABLE IF NOT EXISTS {table} (
id INTEGER PRIMARY KEY,
ip_start_int INTEGER NOT NULL,
ip_end_int INTEGER NOT NULL,
zone TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_{table}_start ON {table}(ip_start_int);
CREATE INDEX IF NOT EXISTS idx_{table}_end ON {table}(ip_end_int);
"#;
fs::write(zone_dir.join("create.sql"), create_sql).unwrap();
let insert_sql = "INSERT INTO {table} (ip_start_int, ip_end_int, zone) VALUES (ip4_int(?1), ip4_int(?2), trim_quotes(?3));\n";
fs::write(zone_dir.join("insert.sql"), insert_sql).unwrap();
let data = "10.0.10.1, 10.0.90.255, \"work_zone\"\n10.0.100.1, 10.0.200.255, 'core_zone' \n";
fs::write(zone_dir.join("data.csv"), data).unwrap();
let conf_path = models.join("knowdb.toml");
let auth_uri = format!(
"file:{}/.run/authority.sqlite?mode=rwc&uri=true",
root.display()
);
let _ = kdb::init_thread_cloned_from_knowdb(
Path::new(&root),
&conf_path,
&auth_uri,
&EnvDict::default(),
);
let rows = kdb::query_fields(
"SELECT zone FROM zone WHERE ip4_between(:ip, ip_start_int, ip_end_int)=1 LIMIT 1",
&[DataField::from_chars(
":ip".to_string(),
"10.0.10.5".to_string(),
)],
)
.expect("query zone by ip");
assert_eq!(rows.len(), 1);
assert_eq!(rows[0].to_string(), "chars(work_zone)");
let rows = kdb::query_fields(
"SELECT cidr4_contains(:ip, '10.0.0.0/8') AS ok",
&[DataField::from_chars(
":ip".to_string(),
"10.1.2.3".to_string(),
)],
)
.expect("query cidr contains");
assert_eq!(rows[0].to_string(), "digit(1)");
let _ = std::fs::remove_dir_all(&root);
}
#[test]
fn load_zone_with_int_compare_query() {
let root = uniq_tmp_dir();
let models = root.join("models").join("knowledge");
let zone_dir = models.join("zone");
fs::create_dir_all(&zone_dir).unwrap();
let knowdb = r#"
version = 2
[csv]
has_header = false
[[tables]]
name = "zone"
columns.by_index = [0,1,2]
[tables.expected_rows]
min = 1
"#;
fs::write(models.join("knowdb.toml"), knowdb).unwrap();
let create_sql = r#"
CREATE TABLE IF NOT EXISTS {table} (
id INTEGER PRIMARY KEY,
ip_start_int INTEGER NOT NULL,
ip_end_int INTEGER NOT NULL,
zone TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_{table}_start ON {table}(ip_start_int);
CREATE INDEX IF NOT EXISTS idx_{table}_end ON {table}(ip_end_int);
"#;
fs::write(zone_dir.join("create.sql"), create_sql).unwrap();
let insert_sql = "INSERT INTO {table} (ip_start_int, ip_end_int, zone) VALUES (ip4_int(?1), ip4_int(?2), trim_quotes(?3));\n";
fs::write(zone_dir.join("insert.sql"), insert_sql).unwrap();
let data = "10.0.10.1, 10.0.90.255, \"work_zone\"\n10.0.100.1, 10.0.200.255, 'core_zone' \n";
fs::write(zone_dir.join("data.csv"), data).unwrap();
let conf_path = models.join("knowdb.toml");
let auth_uri = format!(
"file:{}/.run/authority.sqlite?mode=rwc&uri=true",
root.display()
);
let _ = kdb::init_thread_cloned_from_knowdb(
Path::new(&root),
&conf_path,
&auth_uri,
&EnvDict::default(),
);
let rows = kdb::query_fields(
"SELECT zone FROM zone WHERE ip_start_int <= ip4_int(:ip) AND ip_end_int >= ip4_int(:ip) LIMIT 1",
&[DataField::from_chars(":ip".to_string(), "10.0.10.5".to_string())],
)
.expect("query zone by ip (int compare)");
assert_eq!(rows.len(), 1);
assert_eq!(rows[0].to_string(), "chars(work_zone)");
let _ = std::fs::remove_dir_all(&root);
}