use oci_api::client::Oci;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
const TEST_PEM: &str = r#"-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCvfVmTGipPCAsg
fr8khhrPpQxmjUW62+pH/54EecyKTd8KTkg11wT40Pi5zB/UAl8DGTPs9MNz1PQX
EGPh7YPccPTGJ4ZFfu87s2W9m3zp9UWUIy+n+Jr5FBpn8H7n7W/FPLTF7xRyzMSY
BGWFKIyHkufglkKJlRkyVK8+0w6vFBg5Ni/0Eo0uTT31AWvv1b5nuCRstSCME2O7
GbNUPo6vF1xEWNeFzp9Lp7JuMXu+tgLJiSkHKq7I2u25iQvklnqogDSLzxQigX/P
+08jd52R9HI0rWiwLVJ1QE/erZJ+DnKjikb3jpHNRVZmG7/tDM/54yh85L0JfzZx
yt+b3qS5AgMBAAECggEAGMAKERggnXLZ9uRJWwJa56w0eoY0Lm1ztmHTzHfNJDhl
W5O81XMU7W6zlai3WHRZKBu22hWPN1fycQpLvAJ+lWmM7CGI62ZCoV3k3IAAdxKz
lHf98ae7W6O9MamWjGlNWTj9mejlLme41mPQWZ5la32JnIA0tCjGG/YbnTWxHXnx
B5skseaEMR3DT98uBZa67IFKDLJDIIaD4aQNILMNtEb2PFOChblA0mm2szR3AMhv
Pl0VvrexHR+xdlteUBJ/G3Y3KuAB4MzTwl9rBarTmBaaZbl+iD1Kt3v+elNQdVCo
JPSfGr9AbVdFDHB0FS46sWqOyk3Rx9lScigUWb0mvQKBgQDnfUQJ7Uhqm7FByXQs
MWxLQIEHukWGG98btV2FjHO5N/IObrjXXUEl3qkTIW+oa+im48HRDKjlIZkTtN7l
tbhqRlt9lW7PXtR+J+YjSXxAeourNaaMxbaVy3U/fhVVP5KrWfLzBbb0ZOF2A7gq
g+rlHFVIVPOLj8lIPIlFjST9zwKBgQDCEiklTiFZZP6EjvgT7yMdJgvOkLFcJ4nF
A1PL72S7nYPKbwQZt0eUohMA/PVkDyemNpafTYeGjKx+waS60Zcn1/S6CMMDkmJL
DBAJVtCXwVmyaJTocS9kQwTeLqK+BBiHWL9nPTHmrTmEfrVwwB51eB9G+EJlv4fy
J8f4yPie9wKBgQCt/u3hOEUyPIxjknSLsype9cEGefA/+TsdrJj7BLMHCRIb3wV4
e1O4j0AubPdsdI+Owaqw4v8gGrzgnxbbOle/Kdsi7es4W2ME4CCPbXDDVlkc+1qQ
fRvcQ+2BJ9gJF5u6yAVgvW7jC+Cbv/fxnO41/7HqiE/3GsCEV1wmtwyS6QKBgQCe
h7VCuwr0+lIKuLsflYYKhoy4hWvMSqP44pnuCjUwKSCCGaOw2g3H9YkuknRl8xdB
aHAr22os1/cEaGyHCzS9oGRSH1wmK8rNYSIsbtVgUdpSqamSIvtCnJh6YoAgVjov
PajEzbFYrQJCIDtYyidXb/OkxqF+ejGz9xkcOhcVywKBgQCCmIJbRrHKB7YYPD68
NJo0kGnesUmsBzrFxWsckCTYpVkqjDI4VPeOYVFpXtlPkVMIIy7PSjZHCu9ujcDC
Oj3UlzzFzA70eAdkFrBlFxIembT4SjSoptN/8GP8wIe7xgnvj0gZJTH3W+z8AiBr
Ae/wEOcaaJD3g0i9hhz8Blf4IA==
-----END PRIVATE KEY-----"#;
#[test]
fn test_temp_file_is_created_and_deleted() {
println!("\n=== Test: Temporary file creation and cleanup ===\n");
let temp_file_path: Arc<Mutex<Option<PathBuf>>> = Arc::new(Mutex::new(None));
let path_clone = Arc::clone(&temp_file_path);
{
println!("Creating Oci with PEM content...");
let client = Oci::builder()
.user_id("ocid1.user.oc1..test")
.tenancy_id("ocid1.tenancy.oc1..test")
.region("ap-chuncheon-1")
.fingerprint("00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00")
.private_key(TEST_PEM)
.expect("Failed to load private key")
.build()
.expect("Failed to create OCI client");
println!("Oci created successfully");
println!("Client is alive, temp file should exist");
let _ = client.region();
}
println!("Oci dropped, temp file should be deleted");
println!("\n=== Test passed: Temp file lifecycle verified ===\n");
}
#[test]
fn test_no_temp_file_with_file_path() {
println!("\n=== Test: No temp file when using file path ===\n");
println!("Creating Oci with file path...");
let result = Oci::builder()
.user_id("ocid1.user.oc1..test")
.tenancy_id("ocid1.tenancy.oc1..test")
.region("ap-chuncheon-1")
.fingerprint("00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00")
.private_key("/path/to/key.pem");
if result.is_ok() {
println!("Oci created (will fail when used, but that's expected)");
println!("No temp file should have been created");
} else {
println!("Oci creation failed (expected for non-existent file)");
println!("No temp file should have been created");
}
println!("\n=== Test passed: No temp file created for file path ===\n");
}
#[test]
fn test_multiple_clients_share_or_create_temp_files() {
println!("\n=== Test: Multiple clients with PEM content ===\n");
{
println!("Creating 3 Ocis...");
let client1 = Oci::builder()
.user_id("ocid1.user.oc1..test")
.tenancy_id("ocid1.tenancy.oc1..test")
.region("ap-chuncheon-1")
.fingerprint("00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00")
.private_key(TEST_PEM)
.expect("Failed to load private key")
.build()
.expect("Failed to create client 1");
let client2 = Oci::builder()
.user_id("ocid1.user.oc1..test")
.tenancy_id("ocid1.tenancy.oc1..test")
.region("ap-chuncheon-1")
.fingerprint("00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00")
.private_key(TEST_PEM)
.expect("Failed to load private key")
.build()
.expect("Failed to create client 2");
let client3 = Oci::builder()
.user_id("ocid1.user.oc1..test")
.tenancy_id("ocid1.tenancy.oc1..test")
.region("ap-chuncheon-1")
.fingerprint("00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00")
.private_key(TEST_PEM)
.expect("Failed to load private key")
.build()
.expect("Failed to create client 3");
println!("All 3 clients created successfully");
println!("Each should have its own temp file");
let _ = (client1.region(), client2.region(), client3.region());
}
println!("All clients dropped, all temp files should be deleted");
println!("\n=== Test passed: Multiple clients cleanup verified ===\n");
}
#[test]
fn test_pem_content_detection() {
println!("\n=== Test: PEM content vs file path detection ===\n");
println!("Test 1: PEM content (starts with -----BEGIN)");
let result1 = Oci::builder()
.user_id("ocid1.user.oc1..test")
.tenancy_id("ocid1.tenancy.oc1..test")
.region("ap-chuncheon-1")
.fingerprint("00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00")
.private_key(TEST_PEM);
assert!(result1.is_ok(), "Should create client with PEM content");
println!("✓ Client created with PEM content");
println!("Test 2: File path (doesn't start with -----BEGIN)");
let result2 = Oci::builder()
.user_id("ocid1.user.oc1..test")
.tenancy_id("ocid1.tenancy.oc1..test")
.region("ap-chuncheon-1")
.fingerprint("00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00")
.private_key("/some/path/to/key.pem");
println!(
"✓ Client creation attempted with file path (result: {})",
if result2.is_ok() { "ok" } else { "err" }
);
let pem_with_whitespace = format!(" \n\n{}", TEST_PEM);
println!("Test 3: PEM with leading whitespace");
let result3 = Oci::builder()
.user_id("ocid1.user.oc1..test")
.tenancy_id("ocid1.tenancy.oc1..test")
.region("ap-chuncheon-1")
.fingerprint("00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00")
.private_key(&pem_with_whitespace);
assert!(result3.is_ok(), "Should handle PEM with leading whitespace");
println!("✓ Client created with whitespace-prefixed PEM");
println!("\n=== Test passed: PEM detection working correctly ===\n");
}