use crate::models::AccountEndpoint;
const AZURE_COSMOS_EMULATOR_HOST: &str = "AZURE_COSMOS_EMULATOR_HOST";
const EMULATOR_LOCALHOST_HOSTS: &[&str] = &["localhost", "127.0.0.1", "[::1]", "[0:0:0:0:0:0:0:1]"];
pub(crate) fn is_emulator_host(endpoint: &AccountEndpoint) -> bool {
let host = endpoint.host();
if let Ok(custom_emulator_host) = std::env::var(AZURE_COSMOS_EMULATOR_HOST) {
if !custom_emulator_host.is_empty() && host.eq_ignore_ascii_case(&custom_emulator_host) {
return true;
}
}
EMULATOR_LOCALHOST_HOSTS
.iter()
.any(|h| host.eq_ignore_ascii_case(h))
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
use std::sync::Mutex;
static ENV_MUTEX: Mutex<()> = Mutex::new(());
#[test]
fn localhost_is_emulator() {
let endpoint = AccountEndpoint::try_from("https://localhost:8081/").unwrap();
assert!(is_emulator_host(&endpoint));
}
#[test]
fn localhost_case_insensitive() {
let endpoint = AccountEndpoint::try_from("https://LOCALHOST:8081/").unwrap();
assert!(is_emulator_host(&endpoint));
let endpoint = AccountEndpoint::try_from("https://LocalHost:8081/").unwrap();
assert!(is_emulator_host(&endpoint));
}
#[test]
fn ipv4_loopback_is_emulator() {
let endpoint = AccountEndpoint::try_from("https://127.0.0.1:8081/").unwrap();
assert!(is_emulator_host(&endpoint));
}
#[test]
fn ipv6_loopback_short_is_emulator() {
let endpoint = AccountEndpoint::try_from("https://[::1]:8081/").unwrap();
assert!(is_emulator_host(&endpoint));
}
#[test]
fn ipv6_loopback_full_is_emulator() {
let endpoint = AccountEndpoint::try_from("https://[0:0:0:0:0:0:0:1]:8081/").unwrap();
assert!(is_emulator_host(&endpoint));
}
#[test]
fn production_endpoint_is_not_emulator() {
let endpoint =
AccountEndpoint::try_from("https://myaccount.documents.azure.com:443/").unwrap();
assert!(!is_emulator_host(&endpoint));
}
#[test]
fn custom_emulator_host_via_env() {
let _guard = ENV_MUTEX.lock().unwrap();
let original = env::var(AZURE_COSMOS_EMULATOR_HOST).ok();
env::set_var(AZURE_COSMOS_EMULATOR_HOST, "my-custom-emulator.local");
let custom = AccountEndpoint::try_from("https://my-custom-emulator.local:8081/").unwrap();
assert!(is_emulator_host(&custom));
let prod = AccountEndpoint::try_from("https://myaccount.documents.azure.com:443/").unwrap();
assert!(!is_emulator_host(&prod));
match original {
Some(val) => env::set_var(AZURE_COSMOS_EMULATOR_HOST, val),
None => env::remove_var(AZURE_COSMOS_EMULATOR_HOST),
}
}
#[test]
fn custom_emulator_host_case_insensitive() {
let _guard = ENV_MUTEX.lock().unwrap();
let original = env::var(AZURE_COSMOS_EMULATOR_HOST).ok();
env::set_var(AZURE_COSMOS_EMULATOR_HOST, "MY-EMULATOR.LOCAL");
let lower = AccountEndpoint::try_from("https://my-emulator.local:8081/").unwrap();
assert!(is_emulator_host(&lower));
let upper = AccountEndpoint::try_from("https://MY-EMULATOR.LOCAL:8081/").unwrap();
assert!(is_emulator_host(&upper));
match original {
Some(val) => env::set_var(AZURE_COSMOS_EMULATOR_HOST, val),
None => env::remove_var(AZURE_COSMOS_EMULATOR_HOST),
}
}
#[test]
fn empty_env_var_uses_default_hosts() {
let _guard = ENV_MUTEX.lock().unwrap();
let original = env::var(AZURE_COSMOS_EMULATOR_HOST).ok();
env::set_var(AZURE_COSMOS_EMULATOR_HOST, "");
let endpoint = AccountEndpoint::try_from("https://localhost:8081/").unwrap();
assert!(is_emulator_host(&endpoint));
match original {
Some(val) => env::set_var(AZURE_COSMOS_EMULATOR_HOST, val),
None => env::remove_var(AZURE_COSMOS_EMULATOR_HOST),
}
}
}