use cucumber::{writer, World, WriterExt};
use std::fs::{create_dir_all, read_to_string, File, OpenOptions};
use std::process;
mod access;
mod common;
mod crypto;
mod presence;
mod publish;
mod subscribe;
use common::PubNubWorld;
async fn init_server(script: String) -> Result<String, Box<dyn std::error::Error>> {
let url = format!("http://localhost:8090/init?__contract__script__={}", script);
let client = reqwest::Client::new();
let body = client.get(url).send().await?.text().await?;
Ok(body)
}
fn get_feature_set(tags: &[String]) -> String {
tags.iter()
.filter(|tag| tag.starts_with("featureSet"))
.map(|tag| tag.split('=').last().unwrap().to_string())
.collect::<String>()
}
fn feature_allows_beta(feature: &str) -> bool {
let features: Vec<&str> = vec![
"access",
"publish",
"eventEngine",
"presenceEventEngine",
"cryptoModule",
];
features.contains(&feature)
}
fn feature_allows_skipped(feature: &str) -> bool {
let features: Vec<&str> = vec![];
features.contains(&feature)
}
fn feature_allows_contract_less(feature: &str) -> bool {
let features: Vec<&str> = vec!["access", "cryptoModule"];
features.contains(&feature)
}
fn is_ignored_feature_set_tag(feature: &str, tags: &[String]) -> bool {
let supported_features = [
"access",
"publish",
"eventEngine",
"presenceEventEngine",
"cryptoModule",
];
let mut ignored_tags = vec!["na=rust"];
if !feature_allows_beta(feature) {
ignored_tags.push("beta");
}
if !feature_allows_skipped(feature) {
ignored_tags.push("skip");
}
ignored_tags
.iter()
.any(|tag| tags.contains(&tag.to_string()))
|| !supported_features.contains(&feature)
}
fn is_ignored_scenario_tag(feature: &str, tags: &[String]) -> bool {
let tested_contract = "";
tags.contains(&"na=rust".to_string())
|| !feature_allows_beta(feature) && tags.iter().any(|tag| tag.starts_with("beta"))
|| !feature_allows_skipped(feature) && tags.iter().any(|tag| tag.starts_with("skip"))
|| (!feature_allows_contract_less(feature) || !tested_contract.is_empty())
&& !tags.iter().any(|tag| {
if !tested_contract.is_empty() {
tag == format!("contract={tested_contract}").as_str()
} else {
tag.starts_with("contract=")
}
})
}
pub fn scenario_name(world: &mut PubNubWorld) -> String {
world.scenario.as_ref().unwrap().name.clone()
}
pub fn clear_log_file() {
create_dir_all("tests/logs").expect("Unable to create required directories for logs");
if let Ok(_) = std::fs::metadata("tests/logs/log.txt") {
OpenOptions::new()
.read(true)
.write(true)
.truncate(true)
.open("tests/logs/log.txt")
.expect("Unable to open log file.")
.set_len(0)
.expect("Can't truncate log file");
}
}
fn logger_target() -> env_logger::Target {
create_dir_all("tests/logs").expect("Unable to create required directories for logs");
env_logger::Target::Pipe(Box::new(
OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open("tests/logs/log.txt")
.expect("Unable to open log file"),
))
}
#[tokio::main]
async fn main() {
env_logger::builder()
.target(logger_target())
.try_init()
.unwrap();
let _ = std::fs::create_dir_all("tests/reports");
let file: File = File::create("tests/reports/report-required.xml").unwrap();
PubNubWorld::cucumber()
.max_concurrent_scenarios(1) .before(|_feature, _rule, scenario, world| {
world.scenario = Some(scenario.clone());
futures::FutureExt::boxed(async move {
if scenario.tags.iter().any(|t| t.starts_with("contract=")) {
let tag = scenario
.tags
.iter()
.find(|&t| t.starts_with("contract="))
.unwrap();
let splitted_values: Vec<&str> = tag.split('=').collect();
if !splitted_values[1].is_empty() {
let script_name = splitted_values[1];
init_server(script_name.to_string()).await.unwrap();
}
}
})
})
.after(|_feature, _, _rule, _scenario, world| {
futures::FutureExt::boxed(async move { world.unwrap().reset().await })
})
.with_writer(
writer::Basic::stdout()
.summarized()
.tee(writer::JUnit::new(file, 0))
.normalized(),
)
.fail_on_skipped()
.filter_run("tests/features", move |feature, _, scenario| {
let current_feature = get_feature_set(&feature.tags);
!(is_ignored_feature_set_tag(¤t_feature, &feature.tags)
|| is_ignored_scenario_tag(¤t_feature, &scenario.tags))
})
.await;
let report =
read_to_string("tests/reports/report-required.xml").expect("Unable to load reports");
if report.contains('✘') {
process::exit(1)
}
}