1use std::collections::HashMap;
19use std::env;
20use std::sync::LazyLock;
21
22use opendal_core::Operator;
23use opendal_core::Result;
24use opendal_core::layers::CapabilityOverrideLayer;
25use opendal_layer_logging::LoggingLayer;
26use opendal_layer_retry::RetryLayer;
27use opendal_layer_timeout::TimeoutLayer;
28use sha2::Digest;
29use sha2::Sha256;
30
31const OPENDAL_TEST_CAPABILITY_OVERRIDES: &str = "OPENDAL_TEST_CAPABILITY_OVERRIDES";
32
33pub(crate) fn sha256_digest(data: impl AsRef<[u8]>) -> String {
34 use std::fmt::Write;
35
36 let digest = Sha256::digest(data);
37 let mut output = String::with_capacity(digest.len() * 2);
38 for byte in digest {
39 write!(&mut output, "{byte:02x}").expect("writing to String must succeed");
40 }
41 output
42}
43
44pub static TEST_RUNTIME: LazyLock<tokio::runtime::Runtime> = LazyLock::new(|| {
46 tokio::runtime::Builder::new_multi_thread()
47 .enable_all()
48 .build()
49 .unwrap()
50});
51
52pub fn init_test_service() -> Result<Option<Operator>> {
58 let _ = dotenvy::dotenv();
59
60 let scheme = if let Ok(v) = env::var("OPENDAL_TEST") {
61 v
62 } else {
63 return Ok(None);
64 };
65
66 let prefix = {
67 let scheme_key = scheme.replace('-', "_");
68 format!("opendal_{scheme_key}_")
69 };
70
71 let mut cfg = env::vars()
72 .filter_map(|(k, v)| {
73 k.to_lowercase()
74 .strip_prefix(&prefix)
75 .map(|k| (k.to_string(), v))
76 })
77 .collect::<HashMap<String, String>>();
78
79 let disable_random_root = env::var("OPENDAL_DISABLE_RANDOM_ROOT").unwrap_or_default() == "true";
81 if !disable_random_root {
82 let root = format!(
83 "{}{}/",
84 cfg.get("root").cloned().unwrap_or_else(|| "/".to_string()),
85 uuid::Uuid::new_v4()
86 );
87 cfg.insert("root".to_string(), root);
88 }
89
90 let scheme = scheme.replace('_', "-");
92 let mut op = Operator::via_iter(scheme, cfg).expect("must succeed");
93
94 if let Ok(overrides) = env::var(OPENDAL_TEST_CAPABILITY_OVERRIDES) {
95 op = op.layer(CapabilityOverrideLayer::from_overrides(&overrides)?);
96 }
97
98 let op = op
99 .layer(LoggingLayer::default())
100 .layer(TimeoutLayer::new())
101 .layer(RetryLayer::new().with_max_times(4));
102
103 Ok(Some(op))
104}