mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 08:18:18 +00:00
fix: handle Windows paths in pre-commit tests (#2974)
Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
@@ -82,17 +82,22 @@ impl TryFrom<&str> for Endpoint {
|
||||
#[cfg(not(windows))]
|
||||
let path = Path::new(&path).absolutize()?;
|
||||
|
||||
// On windows having a preceding SlashSeparator will cause problems, if the
|
||||
// command line already has C:/<export-folder/ in it. Final resulting
|
||||
// path on windows might become C:/C:/ this will cause problems
|
||||
// of starting rustfs server properly in distributed mode on windows.
|
||||
// As a special case make sure to trim the separator.
|
||||
#[cfg(windows)]
|
||||
let path = Path::new(&path[1..]).absolutize()?;
|
||||
let path = if has_leading_slash_windows_drive(&path) {
|
||||
// Url::path() exposes file-like Windows paths as `/C:/...`.
|
||||
// Strip only that synthetic leading slash; plain URL paths
|
||||
// such as `/export1` must stay URL paths, not become
|
||||
// relative paths under the current drive.
|
||||
Path::new(&path[1..]).absolutize()?.to_string_lossy().into_owned()
|
||||
} else {
|
||||
path
|
||||
};
|
||||
#[cfg(windows)]
|
||||
let path = Path::new(&path);
|
||||
|
||||
debug!("endpoint try_from: path={}", path.display());
|
||||
|
||||
if path.parent().is_none() || Path::new("").eq(&path) {
|
||||
if path.parent().is_none() || path.as_os_str().is_empty() {
|
||||
return Err(Error::other("empty or root path is not supported in URL endpoint"));
|
||||
}
|
||||
|
||||
@@ -217,6 +222,12 @@ impl Endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn has_leading_slash_windows_drive(path: &str) -> bool {
|
||||
let bytes = path.as_bytes();
|
||||
bytes.len() >= 4 && bytes[0] == b'/' && bytes[1].is_ascii_alphabetic() && bytes[2] == b':' && bytes[3] == b'/'
|
||||
}
|
||||
|
||||
/// parse a file path into a URL.
|
||||
fn url_parse_from_file_path(value: &str) -> Result<Url> {
|
||||
// Only check if the arg is an ip address and ask for scheme since its absent.
|
||||
@@ -242,6 +253,14 @@ fn url_parse_from_file_path(value: &str) -> Result<Url> {
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
fn expected_file_path(path: &str) -> String {
|
||||
Path::new(path).absolutize().unwrap().to_string_lossy().replace('\\', "/")
|
||||
}
|
||||
|
||||
fn expected_file_url(path: &str) -> Url {
|
||||
url_parse_from_file_path(path).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_endpoint() {
|
||||
#[derive(Default)]
|
||||
@@ -255,7 +274,7 @@ mod test {
|
||||
let u2 = Url::parse("https://example.org/path").unwrap();
|
||||
let u4 = Url::parse("http://192.168.253.200/path").unwrap();
|
||||
let u6 = Url::parse("http://server:/path").unwrap();
|
||||
let root_slash_foo = Url::from_file_path("/foo").unwrap();
|
||||
let root_slash_foo = expected_file_url("/foo");
|
||||
|
||||
let test_cases = [
|
||||
TestCase {
|
||||
@@ -416,7 +435,7 @@ mod test {
|
||||
// Test file path display
|
||||
let file_endpoint = Endpoint::try_from("/tmp/data").unwrap();
|
||||
let display_str = format!("{file_endpoint}");
|
||||
assert_eq!(display_str, "/tmp/data");
|
||||
assert_eq!(display_str, expected_file_path("/tmp/data"));
|
||||
|
||||
// Test URL display
|
||||
let url_endpoint = Endpoint::try_from("http://example.com:9000/path").unwrap();
|
||||
@@ -479,12 +498,25 @@ mod test {
|
||||
#[test]
|
||||
fn test_endpoint_get_file_path() {
|
||||
let file_endpoint = Endpoint::try_from("/tmp/data").unwrap();
|
||||
assert_eq!(file_endpoint.get_file_path(), "/tmp/data");
|
||||
assert_eq!(file_endpoint.get_file_path(), expected_file_path("/tmp/data"));
|
||||
|
||||
let url_endpoint = Endpoint::try_from("http://example.com:9000/path/to/data").unwrap();
|
||||
assert_eq!(url_endpoint.get_file_path(), "/path/to/data");
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn test_windows_url_drive_path_requires_separator_after_colon() {
|
||||
let drive_path_endpoint = Endpoint::try_from("http://host/C:/data").unwrap();
|
||||
assert_eq!(drive_path_endpoint.get_type(), EndpointType::Url);
|
||||
assert!(has_leading_slash_windows_drive(Url::parse("http://host/C:/data").unwrap().path()));
|
||||
|
||||
let url_path_endpoint = Endpoint::try_from("http://host/C:foo").unwrap();
|
||||
assert_eq!(url_path_endpoint.get_type(), EndpointType::Url);
|
||||
assert!(!has_leading_slash_windows_drive(Url::parse("http://host/C:foo").unwrap().path()));
|
||||
assert_eq!(url_path_endpoint.get_file_path(), "/C:foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_endpoint_clone_and_equality() {
|
||||
let endpoint1 = Endpoint::try_from("/tmp/data").unwrap();
|
||||
@@ -503,7 +535,7 @@ mod test {
|
||||
// Test with complex paths
|
||||
let complex_path = "/var/lib/rustfs/data/bucket1";
|
||||
let endpoint = Endpoint::try_from(complex_path).unwrap();
|
||||
assert_eq!(endpoint.get_file_path(), complex_path);
|
||||
assert_eq!(endpoint.get_file_path(), expected_file_path(complex_path));
|
||||
assert!(endpoint.is_local);
|
||||
assert_eq!(endpoint.get_type(), EndpointType::Path);
|
||||
}
|
||||
@@ -512,7 +544,7 @@ mod test {
|
||||
fn test_endpoint_with_spaces_in_path() {
|
||||
let path_with_spaces = "/Users/test/Library/Application Support/rustfs/data";
|
||||
let endpoint = Endpoint::try_from(path_with_spaces).unwrap();
|
||||
assert_eq!(endpoint.get_file_path(), path_with_spaces);
|
||||
assert_eq!(endpoint.get_file_path(), expected_file_path(path_with_spaces));
|
||||
assert!(endpoint.is_local);
|
||||
assert_eq!(endpoint.get_type(), EndpointType::Path);
|
||||
}
|
||||
@@ -532,7 +564,7 @@ mod test {
|
||||
// Verify that get_file_path() decodes the percent-encoded path correctly
|
||||
assert_eq!(
|
||||
endpoint.get_file_path(),
|
||||
"/Users/test/Library/Application Support/rustfs/data",
|
||||
expected_file_path("/Users/test/Library/Application Support/rustfs/data"),
|
||||
"get_file_path() should decode percent-encoded spaces"
|
||||
);
|
||||
}
|
||||
@@ -544,7 +576,7 @@ mod test {
|
||||
let endpoint = Endpoint::try_from(path_with_special).unwrap();
|
||||
|
||||
// get_file_path() should return the original path with decoded characters
|
||||
assert_eq!(endpoint.get_file_path(), path_with_special);
|
||||
assert_eq!(endpoint.get_file_path(), expected_file_path(path_with_special));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -545,7 +545,7 @@ mod tests {
|
||||
|
||||
// Create two different files
|
||||
tokio::fs::write(&file1_path, b"content1").await.unwrap();
|
||||
tokio::fs::write(&file2_path, b"content2").await.unwrap();
|
||||
tokio::fs::write(&file2_path, b"different content").await.unwrap();
|
||||
|
||||
// Get metadata
|
||||
let metadata1 = tokio::fs::metadata(&file1_path).await.unwrap();
|
||||
|
||||
@@ -2153,9 +2153,6 @@ impl DiskAPI for LocalDisk {
|
||||
#[allow(unsafe_code)]
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
async fn read_file_zero_copy(&self, volume: &str, path: &str, offset: usize, length: usize) -> Result<Bytes> {
|
||||
use std::time::Instant;
|
||||
|
||||
let start = Instant::now();
|
||||
let volume_dir = self.get_bucket_path(volume)?;
|
||||
if !skip_access_checks(volume) {
|
||||
access(&volume_dir)
|
||||
@@ -2188,6 +2185,9 @@ impl DiskAPI for LocalDisk {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use memmap2::MmapOptions;
|
||||
use std::time::Instant;
|
||||
|
||||
let start = Instant::now();
|
||||
let file_path_clone = file_path.clone();
|
||||
|
||||
let should_reclaim_after_read = should_reclaim_file_cache_after_read(length);
|
||||
@@ -2272,8 +2272,7 @@ impl DiskAPI for LocalDisk {
|
||||
f.seek(SeekFrom::Start(offset as u64)).await?;
|
||||
}
|
||||
|
||||
let mut buffer = Vec::with_capacity(length);
|
||||
buffer.resize(length, 0);
|
||||
let mut buffer = vec![0; length];
|
||||
f.read_exact(&mut buffer).await?;
|
||||
|
||||
Ok(Bytes::from(buffer))
|
||||
@@ -3497,10 +3496,10 @@ mod test {
|
||||
let disk_info = disk.disk_info(&disk_info_opts).await.unwrap();
|
||||
|
||||
// Basic checks on disk info
|
||||
// Note: On macOS and some other Unix systems, fs_type may be empty
|
||||
// Note: On macOS, Windows, and some other systems, fs_type may be empty
|
||||
// because statvfs does not provide filesystem type information.
|
||||
// This is a platform limitation, not a bug.
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(not(any(target_os = "macos", windows)))]
|
||||
assert!(!disk_info.fs_type.is_empty(), "fs_type should not be empty on this platform");
|
||||
assert!(disk_info.total > 0);
|
||||
assert!(disk_info.free <= disk_info.total);
|
||||
|
||||
@@ -789,7 +789,6 @@ mod tests {
|
||||
use super::*;
|
||||
use endpoint::Endpoint;
|
||||
use local::LocalDisk;
|
||||
use std::path::PathBuf;
|
||||
use tokio::fs;
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -1094,7 +1093,7 @@ mod tests {
|
||||
assert!(disk.is_ok());
|
||||
|
||||
let disk = disk.unwrap();
|
||||
assert_eq!(disk.path(), PathBuf::from(test_dir).canonicalize().unwrap());
|
||||
assert_eq!(disk.path(), rustfs_utils::canonicalize(test_dir).unwrap());
|
||||
assert!(disk.is_local());
|
||||
// Note: is_online() might return false for local disks without proper initialization
|
||||
// This is expected behavior for test environments
|
||||
|
||||
@@ -749,6 +749,7 @@ fn validate_local_cross_device_mounts(local_paths: &[String]) -> Result<()> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use path_absolutize::Absolutize;
|
||||
use rustfs_utils::must_get_local_ips;
|
||||
|
||||
use super::*;
|
||||
@@ -1452,9 +1453,10 @@ mod test {
|
||||
}
|
||||
|
||||
fn must_file_path(s: impl AsRef<Path>) -> url::Url {
|
||||
let url = url::Url::from_file_path(s.as_ref());
|
||||
let path = s.as_ref().absolutize().expect("absolute test path");
|
||||
let url = url::Url::from_file_path(&path);
|
||||
|
||||
assert!(url.is_ok(), "failed to convert path to URL: {}", s.as_ref().display());
|
||||
assert!(url.is_ok(), "failed to convert path to URL: {}", path.display());
|
||||
|
||||
url.unwrap()
|
||||
}
|
||||
|
||||
@@ -872,10 +872,7 @@ mod tests {
|
||||
let result = call_peer_with_timeout(
|
||||
Duration::from_millis(5),
|
||||
"peer-3",
|
||||
|| async {
|
||||
tokio::time::sleep(Duration::from_millis(25)).await;
|
||||
Ok::<_, Error>(build_props("slow"))
|
||||
},
|
||||
std::future::pending::<Result<ServerProperties>>,
|
||||
|| build_props("fallback"),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -287,7 +287,7 @@ mod tests {
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
// Non-Linux should return UnsupportedPlatform
|
||||
let file = std::fs::File::open("/dev/null").unwrap();
|
||||
let file = std::fs::File::open(std::env::current_exe().unwrap()).unwrap();
|
||||
assert!(matches!(DirectIoReader::new(file, 0, 512), Err(DirectIoError::UnsupportedPlatform)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,6 +219,15 @@ pub fn detect_storage_media(storage_detection_enabled: bool, storage_media_overr
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
||||
{
|
||||
if let Ok(media) = detect_platform_storage_media()
|
||||
&& media != StorageMedia::Unknown
|
||||
{
|
||||
return media;
|
||||
}
|
||||
}
|
||||
|
||||
StorageMedia::Unknown
|
||||
}
|
||||
|
||||
|
||||
@@ -648,6 +648,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::capacity_manager::{DataSource, HybridStrategyConfig, create_isolated_manager};
|
||||
use rustfs_common::capacity_scope::{CapacityScope, CapacityScopeDisk};
|
||||
#[cfg(unix)]
|
||||
use rustfs_config::ENV_CAPACITY_FOLLOW_SYMLINKS;
|
||||
use serial_test::serial;
|
||||
|
||||
@@ -671,6 +672,7 @@ mod tests {
|
||||
let file_path = temp_dir.path().join("test.txt");
|
||||
let mut file = File::create(&file_path).unwrap();
|
||||
file.write_all(b"Hello, World!").unwrap();
|
||||
drop(file);
|
||||
|
||||
let size = get_dir_size_async(temp_dir.path()).await.unwrap();
|
||||
assert_eq!(size.used_bytes, 13);
|
||||
@@ -709,10 +711,12 @@ mod tests {
|
||||
let file1 = temp_dir.path().join("file1.txt");
|
||||
let mut f1 = File::create(&file1).unwrap();
|
||||
f1.write_all(b"content1").unwrap();
|
||||
drop(f1);
|
||||
|
||||
let file2 = subdir.join("file2.txt");
|
||||
let mut f2 = File::create(&file2).unwrap();
|
||||
f2.write_all(b"content2").unwrap();
|
||||
drop(f2);
|
||||
|
||||
let size = get_dir_size_async(temp_dir.path()).await.unwrap();
|
||||
assert_eq!(size.used_bytes, 16);
|
||||
@@ -736,6 +740,7 @@ mod tests {
|
||||
let file_path = temp_dir.path().join("test.txt");
|
||||
let mut file = File::create(&file_path).unwrap();
|
||||
file.write_all(b"Hello, World!").unwrap();
|
||||
drop(file);
|
||||
|
||||
let disks = vec![
|
||||
CapacityDiskRef {
|
||||
|
||||
@@ -504,7 +504,7 @@ impl LogCleaner {
|
||||
if let Some(err) = last_err {
|
||||
return Err(err);
|
||||
}
|
||||
return Ok(());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
#![cfg(test)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
//! Storage-backend double for protocol driver unit tests.
|
||||
//!
|
||||
|
||||
@@ -28,6 +28,7 @@ use super::constants::limits::{
|
||||
READ_CACHE_TOTAL_MEM_MIN, READ_CACHE_WINDOW_DEFAULT, READ_CACHE_WINDOW_MAX, READ_CACHE_WINDOW_MIN, S3_MAX_PART_SIZE,
|
||||
S3_MIN_PART_SIZE,
|
||||
};
|
||||
#[cfg(unix)]
|
||||
use russh::keys::PublicKeyBase64;
|
||||
use std::net::SocketAddr;
|
||||
#[cfg(unix)]
|
||||
@@ -38,6 +39,7 @@ use thiserror::Error;
|
||||
/// Upper bound on file size accepted as a candidate host key (1 MiB).
|
||||
/// Guards against accidentally reading huge non-key files in the host
|
||||
/// key directory. Real keys are well under 10 KiB.
|
||||
#[cfg(unix)]
|
||||
const MAX_HOST_KEY_FILE_SIZE: u64 = 1024 * 1024;
|
||||
|
||||
/// PEM pre-encapsulation boundary marker prefix per RFC 7468 section 3.
|
||||
@@ -45,6 +47,7 @@ const MAX_HOST_KEY_FILE_SIZE: u64 = 1024 * 1024;
|
||||
/// space, the label, and five more hyphens. Used to distinguish a file
|
||||
/// that looks like a private key but failed to decode (passphrase, corrupt)
|
||||
/// from a file that is genuinely something else (a .pub key, a README).
|
||||
#[cfg(unix)]
|
||||
const PEM_BEGIN_MARKER: &str = "-----BEGIN";
|
||||
|
||||
/// Errors that can occur during SFTP server initialization.
|
||||
@@ -457,6 +460,7 @@ impl SftpConfig {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
use tempfile::TempDir;
|
||||
|
||||
@@ -464,17 +468,21 @@ mod tests {
|
||||
// label / five-hyphen) are composed at runtime by build_pem_block
|
||||
// so the source file emits no contiguous private-key marker that
|
||||
// secret scanners would flag. Throwaway test-vector keys.
|
||||
#[cfg(unix)]
|
||||
const PEM_BOUNDARY_DASHES: &str = "-----";
|
||||
#[cfg(unix)]
|
||||
const PEM_OPENSSH_LABEL: &str = "OPENSSH PRIVATE KEY";
|
||||
|
||||
/// Wrap a base64 body in the OpenSSH-format PEM boundary markers.
|
||||
/// The boundary string is composed at runtime from PEM_BOUNDARY_DASHES
|
||||
/// and PEM_OPENSSH_LABEL so the source file does not contain the full
|
||||
/// marker as a contiguous literal.
|
||||
#[cfg(unix)]
|
||||
fn build_pem_block(body: &str) -> String {
|
||||
format!("{d}BEGIN {l}{d}\n{body}\n{d}END {l}{d}\n", d = PEM_BOUNDARY_DASHES, l = PEM_OPENSSH_LABEL,)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn test_ed25519_pem() -> String {
|
||||
// Throwaway Ed25519 private key, no passphrase.
|
||||
build_pem_block(
|
||||
@@ -486,6 +494,7 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn test_ecdsa_pem() -> String {
|
||||
// ECDSA P-256 fixture key for the algorithm-preference sort
|
||||
// test. Not passphrase-protected.
|
||||
@@ -516,6 +525,7 @@ mod tests {
|
||||
}
|
||||
|
||||
/// Write a file at the given path with the given content and mode.
|
||||
#[cfg(unix)]
|
||||
fn write_file_with_mode(path: &Path, content: &str, mode: u32) {
|
||||
let mut opts = std::fs::OpenOptions::new();
|
||||
opts.write(true).create(true).truncate(true).mode(mode);
|
||||
@@ -599,6 +609,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn load_host_keys_fails_when_dir_missing() {
|
||||
let path = PathBuf::from("/this/path/does/not/exist/sftp-host-keys");
|
||||
let err = SftpConfig::load_host_keys(&path).await.expect_err("missing dir must error");
|
||||
@@ -606,6 +617,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn load_host_keys_fails_when_dir_empty() {
|
||||
let dir = TempDir::new().expect("tempdir");
|
||||
let err = SftpConfig::load_host_keys(dir.path())
|
||||
@@ -615,6 +627,17 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(not(unix))]
|
||||
async fn load_host_keys_rejects_non_unix_platform() {
|
||||
let dir = TempDir::new().expect("tempdir");
|
||||
let err = SftpConfig::load_host_keys(dir.path())
|
||||
.await
|
||||
.expect_err("non-Unix platforms must be rejected");
|
||||
assert!(matches!(err, SftpInitError::UnsupportedPlatform { .. }));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn load_host_keys_rejects_insecure_permissions() {
|
||||
let dir = TempDir::new().expect("tempdir");
|
||||
let key_path = dir.path().join("ssh_host_ed25519_key");
|
||||
@@ -632,6 +655,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn load_host_keys_loads_one_valid_ed25519_key() {
|
||||
let dir = TempDir::new().expect("tempdir");
|
||||
let key_path = dir.path().join("ssh_host_ed25519_key");
|
||||
@@ -642,6 +666,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn load_host_keys_skips_non_key_files() {
|
||||
let dir = TempDir::new().expect("tempdir");
|
||||
// Real key plus an unrelated file.
|
||||
@@ -654,6 +679,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn load_host_keys_handles_empty_file() {
|
||||
let dir = TempDir::new().expect("tempdir");
|
||||
write_file_with_mode(&dir.path().join("empty"), "", 0o600);
|
||||
@@ -665,6 +691,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn load_host_keys_skips_passphrase_protected_key_with_warn() {
|
||||
// Build content that looks like a private key but cannot be decoded
|
||||
// (we pass None as the passphrase). Exercises the load_host_keys
|
||||
@@ -682,6 +709,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn load_host_keys_sorts_ed25519_before_ecdsa() {
|
||||
let dir = TempDir::new().expect("tempdir");
|
||||
// Write ECDSA first to confirm sort ordering rather than insertion order.
|
||||
|
||||
@@ -605,6 +605,10 @@ mod tests {
|
||||
};
|
||||
use rustfs_ecstore::config::KVS;
|
||||
|
||||
fn absolute_test_path(path: &str) -> String {
|
||||
std::env::temp_dir().join(path).to_string_lossy().into_owned()
|
||||
}
|
||||
|
||||
fn amqp_base_config() -> KVS {
|
||||
let mut config = KVS::new();
|
||||
config.insert(AMQP_URL.to_string(), "amqp://127.0.0.1:5672/%2f".to_string());
|
||||
@@ -787,8 +791,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn build_mysql_args_applies_defaults() {
|
||||
let args = build_mysql_args(&mysql_base_config(), "/custom/queue", TargetType::NotifyEvent).expect("valid mysql args");
|
||||
assert_eq!(args.queue_dir, "/custom/queue");
|
||||
let queue_dir = absolute_test_path("custom-queue");
|
||||
let args = build_mysql_args(&mysql_base_config(), &queue_dir, TargetType::NotifyEvent).expect("valid mysql args");
|
||||
assert_eq!(args.queue_dir, queue_dir);
|
||||
assert_eq!(args.queue_limit, 100000);
|
||||
assert_eq!(args.max_open_connections, 2);
|
||||
}
|
||||
@@ -846,7 +851,7 @@ mod tests {
|
||||
let err = validate_mysql_config(&config, "").expect_err("relative tls_ca should fail");
|
||||
assert!(err.to_string().contains("tls_ca must be an absolute path"));
|
||||
|
||||
config.insert(MYSQL_TLS_CA.to_string(), "/etc/ssl/mysql/ca.pem".to_string());
|
||||
config.insert(MYSQL_TLS_CA.to_string(), absolute_test_path("mysql-ca.pem"));
|
||||
config.insert(MYSQL_TLS_CLIENT_CERT.to_string(), "client.pem".to_string());
|
||||
config.insert(MYSQL_TLS_CLIENT_KEY.to_string(), "client.key".to_string());
|
||||
|
||||
@@ -857,14 +862,17 @@ mod tests {
|
||||
#[test]
|
||||
fn build_mysql_args_accepts_absolute_tls_paths() {
|
||||
let mut config = mysql_base_config();
|
||||
config.insert(MYSQL_TLS_CA.to_string(), "/etc/ssl/mysql/ca.pem".to_string());
|
||||
config.insert(MYSQL_TLS_CLIENT_CERT.to_string(), "/etc/ssl/mysql/client.pem".to_string());
|
||||
config.insert(MYSQL_TLS_CLIENT_KEY.to_string(), "/etc/ssl/mysql/client.key".to_string());
|
||||
let tls_ca = absolute_test_path("mysql-ca.pem");
|
||||
let tls_client_cert = absolute_test_path("mysql-client.pem");
|
||||
let tls_client_key = absolute_test_path("mysql-client.key");
|
||||
config.insert(MYSQL_TLS_CA.to_string(), tls_ca.clone());
|
||||
config.insert(MYSQL_TLS_CLIENT_CERT.to_string(), tls_client_cert.clone());
|
||||
config.insert(MYSQL_TLS_CLIENT_KEY.to_string(), tls_client_key.clone());
|
||||
|
||||
let args = build_mysql_args(&config, "", TargetType::NotifyEvent).expect("absolute mysql TLS paths should pass");
|
||||
assert_eq!(args.tls_ca, "/etc/ssl/mysql/ca.pem");
|
||||
assert_eq!(args.tls_client_cert, "/etc/ssl/mysql/client.pem");
|
||||
assert_eq!(args.tls_client_key, "/etc/ssl/mysql/client.key");
|
||||
assert_eq!(args.tls_ca, tls_ca);
|
||||
assert_eq!(args.tls_client_cert, tls_client_cert);
|
||||
assert_eq!(args.tls_client_key, tls_client_key);
|
||||
}
|
||||
|
||||
fn redis_base_config() -> KVS {
|
||||
|
||||
@@ -832,6 +832,10 @@ where
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn absolute_test_path(path: &str) -> String {
|
||||
std::env::temp_dir().join(path).to_string_lossy().into_owned()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_dsn_format() {
|
||||
let dsn = MySqlDsn::parse("rustfs:secret123@tcp(mysql.example.com:3306)/rustfs_events").expect("valid DSN");
|
||||
@@ -1189,10 +1193,10 @@ mod tests {
|
||||
dsn_string: "rustfs:password@tcp(127.0.0.1:3306)/db".to_string(),
|
||||
table: "events".to_string(),
|
||||
format: "access".to_string(),
|
||||
tls_ca: "/etc/ssl/mysql/ca.pem".to_string(),
|
||||
tls_client_cert: "/etc/ssl/mysql/client.pem".to_string(),
|
||||
tls_client_key: "/etc/ssl/mysql/client.key".to_string(),
|
||||
queue_dir: "/tmp".to_string(),
|
||||
tls_ca: absolute_test_path("mysql-ca.pem"),
|
||||
tls_client_cert: absolute_test_path("mysql-client.pem"),
|
||||
tls_client_key: absolute_test_path("mysql-client.key"),
|
||||
queue_dir: absolute_test_path("mysql-queue"),
|
||||
queue_limit: 100,
|
||||
max_open_connections: 2,
|
||||
target_type: TargetType::NotifyEvent,
|
||||
|
||||
@@ -730,6 +730,10 @@ mod tests {
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
fn absolute_test_path(path: &str) -> String {
|
||||
std::env::temp_dir().join(path).to_string_lossy().into_owned()
|
||||
}
|
||||
|
||||
fn base_args() -> RedisArgs {
|
||||
RedisArgs {
|
||||
enable: true,
|
||||
@@ -782,7 +786,7 @@ mod tests {
|
||||
url: Url::parse("rediss://127.0.0.1:6379").unwrap(),
|
||||
tls: RedisTlsConfig {
|
||||
policy: Some(RedisTlsPolicy::CustomCa),
|
||||
ca_path: "/tmp/ca.pem".to_string(),
|
||||
ca_path: absolute_test_path("redis-ca.pem"),
|
||||
..RedisTlsConfig::default()
|
||||
},
|
||||
..base_args()
|
||||
|
||||
Reference in New Issue
Block a user