#![cfg(not(target_arch = "wasm32"))]
use bytes::Bytes;
use surrealmx::Database;
#[test]
fn getm_returns_values_in_order() {
let db = Database::new();
let mut tx = db.transaction(true);
tx.set("key1", "value1").unwrap();
tx.set("key2", "value2").unwrap();
tx.set("key3", "value3").unwrap();
tx.commit().unwrap();
let tx = db.transaction(false);
let keys = vec!["key1", "key2", "key3"];
let results = tx.getm(keys).unwrap();
assert_eq!(results.len(), 3);
assert_eq!(results[0], Some(Bytes::from("value1")));
assert_eq!(results[1], Some(Bytes::from("value2")));
assert_eq!(results[2], Some(Bytes::from("value3")));
}
#[test]
fn getm_handles_missing_keys() {
let db = Database::new();
let mut tx = db.transaction(true);
tx.set("key1", "value1").unwrap();
tx.set("key3", "value3").unwrap();
tx.commit().unwrap();
let tx = db.transaction(false);
let keys = vec!["key1", "key2", "key3", "key4"];
let results = tx.getm(keys).unwrap();
assert_eq!(results.len(), 4);
assert_eq!(results[0], Some(Bytes::from("value1")));
assert_eq!(results[1], None, "Missing key2 should be None");
assert_eq!(results[2], Some(Bytes::from("value3")));
assert_eq!(results[3], None, "Missing key4 should be None");
}
#[test]
fn getm_handles_all_missing_keys() {
let db = Database::new();
let tx = db.transaction(false);
let keys = vec!["missing1", "missing2", "missing3"];
let results = tx.getm(keys).unwrap();
assert_eq!(results.len(), 3);
assert!(results.iter().all(|r| r.is_none()), "All results should be None");
}
#[test]
fn getm_with_empty_keys() {
let db = Database::new();
let tx = db.transaction(false);
let keys: Vec<&str> = vec![];
let results = tx.getm(keys).unwrap();
assert!(results.is_empty(), "Empty keys should return empty results");
}
#[test]
fn getm_with_duplicate_keys() {
let db = Database::new();
let mut tx = db.transaction(true);
tx.set("key", "value").unwrap();
tx.commit().unwrap();
let tx = db.transaction(false);
let keys = vec!["key", "key", "key"];
let results = tx.getm(keys).unwrap();
assert_eq!(results.len(), 3);
assert!(results.iter().all(|r| *r == Some(Bytes::from("value"))));
}
#[test]
fn getm_sees_uncommitted_writes() {
let db = Database::new();
let mut tx = db.transaction(true);
tx.set("key1", "uncommitted1").unwrap();
tx.set("key2", "uncommitted2").unwrap();
let keys = vec!["key1", "key2"];
let results = tx.getm(keys).unwrap();
assert_eq!(results[0], Some(Bytes::from("uncommitted1")));
assert_eq!(results[1], Some(Bytes::from("uncommitted2")));
tx.cancel().unwrap();
}
#[test]
fn getm_with_deleted_keys() {
let db = Database::new();
let mut tx = db.transaction(true);
tx.set("key1", "value1").unwrap();
tx.set("key2", "value2").unwrap();
tx.commit().unwrap();
let mut tx = db.transaction(true);
tx.del("key1").unwrap();
let keys = vec!["key1", "key2"];
let results = tx.getm(keys).unwrap();
assert_eq!(results[0], None, "Deleted key should be None");
assert_eq!(results[1], Some(Bytes::from("value2")));
tx.commit().unwrap();
}
#[test]
fn getm_large_batch() {
let db = Database::new();
let count = 1000;
let mut tx = db.transaction(true);
for i in 0..count {
tx.set(format!("key_{:04}", i), format!("value_{}", i)).unwrap();
}
tx.commit().unwrap();
let tx = db.transaction(false);
let keys: Vec<String> = (0..count).map(|i| format!("key_{:04}", i)).collect();
let results = tx.getm(keys).unwrap();
assert_eq!(results.len(), count);
for (i, result) in results.iter().enumerate() {
assert_eq!(*result, Some(Bytes::from(format!("value_{}", i))));
}
}
#[test]
fn getm_tracks_reads_for_ssi() {
let db = Database::new();
let mut tx = db.transaction(true);
tx.set("key1", "value1").unwrap();
tx.commit().unwrap();
let mut tx1 = db.transaction(true).with_serializable_snapshot_isolation();
let keys = vec!["key1", "key2"];
let _ = tx1.getm(keys).unwrap();
let mut tx2 = db.transaction(true).with_serializable_snapshot_isolation();
tx2.set("key1", "modified").unwrap();
assert!(tx2.commit().is_ok());
tx1.set("other", "value").unwrap();
assert!(tx1.commit().is_err(), "tx1 should fail due to SSI read conflict");
}
#[test]
fn getm_with_binary_keys() {
let db = Database::new();
let key1: Vec<u8> = vec![0x00, 0x01, 0x02];
let key2: Vec<u8> = vec![0xFF, 0xFE, 0xFD];
let mut tx = db.transaction(true);
tx.set(key1.clone(), "binary1").unwrap();
tx.set(key2.clone(), "binary2").unwrap();
tx.commit().unwrap();
let tx = db.transaction(false);
let keys = vec![key1, key2];
let results = tx.getm(keys).unwrap();
assert_eq!(results[0], Some(Bytes::from("binary1")));
assert_eq!(results[1], Some(Bytes::from("binary2")));
}
#[test]
fn getm_concurrent_with_writes() {
let db = Database::new();
let mut tx = db.transaction(true);
tx.set("key1", "v1").unwrap();
tx.set("key2", "v1").unwrap();
tx.commit().unwrap();
let read_tx = db.transaction(false);
let mut write_tx = db.transaction(true);
write_tx.set("key1", "v2").unwrap();
write_tx.set("key2", "v2").unwrap();
write_tx.commit().unwrap();
let keys = vec!["key1", "key2"];
let results = read_tx.getm(keys).unwrap();
assert_eq!(results[0], Some(Bytes::from("v1")));
assert_eq!(results[1], Some(Bytes::from("v1")));
}