chuniio-yubideck/vendor/shared_memory/tests/posix_semantics.rs
2023-12-24 03:43:42 +07:00

91 lines
3.5 KiB
Rust

use shared_memory::ShmemConf;
use std::sync::mpsc::channel;
use std::thread;
#[test]
fn persistence() {
let os_id = {
let mut shmem = ShmemConf::new().size(4096).create().unwrap();
shmem.set_owner(false);
String::from(shmem.get_os_id())
};
let mut shmem = ShmemConf::new().os_id(os_id).open().unwrap();
shmem.set_owner(true);
}
#[test]
fn posix_behavior() {
let (tx_a, rx_a) = channel();
let (tx_b, rx_b) = channel();
let (tx_c, rx_c) = channel();
let thread_a = thread::Builder::new()
.name(String::from("A"))
.spawn(move || {
let os_id = {
let shmem = ShmemConf::new().size(4096).create().unwrap();
let os_id = String::from(shmem.get_os_id());
// Creating two `Shmem`s with the same `os_id` should fail
assert!(ShmemConf::new().size(4096).os_id(&os_id).create().is_err());
tx_b.send(os_id.clone()).unwrap();
tx_c.send(os_id.clone()).unwrap();
// Wait for threads B and C to confirm they have created their instances.
rx_a.recv().unwrap();
rx_a.recv().unwrap();
// Tell thread B to drop its instance.
tx_b.send(String::new()).unwrap();
os_id
// Owned shmem drops here after a second owned instance has been
// dropped in thread B.
};
// Should not be able to reopen shared memory after an owned instance
// has been dropped in thread B.
assert!(ShmemConf::new().size(4096).os_id(os_id).open().is_err());
// Tell thread C to drop the unowned instance.
tx_c.send(String::new()).unwrap();
})
.unwrap();
let thread_b = thread::Builder::new()
.name(String::from("B"))
.spawn({
let tx_a = tx_a.clone();
move || {
let existing_os_id = rx_b.recv().unwrap();
// Creating two `Shmem`s with the same `os_id` should fail
assert!(ShmemConf::new()
.size(4096)
.os_id(&existing_os_id)
.create()
.is_err());
{
// Should be able to open the existing shared memory
let mut shmem = ShmemConf::new().os_id(&existing_os_id).open().unwrap();
shmem.set_owner(true);
tx_a.send(String::new()).unwrap();
rx_b.recv().unwrap();
// When the owning shmem is dropped here, we
// 1. should be able to still drop the original shared memory in thread A.
// 2. should not be able to reopen it with the same name in thread A, even
// if an instance is kept alive in thread C.
}
}
})
.unwrap();
let thread_c = thread::Builder::new()
.name(String::from("C"))
.spawn(move || {
// This thread keeps a shared memory instance alive until it's told to
// drop it.
let existing_os_id = rx_c.recv().unwrap();
let _shmem = ShmemConf::new().os_id(&existing_os_id).open().unwrap();
// Indicate to thread A that the instance has been created.
tx_a.send(String::new()).unwrap();
// Shut down signal.
rx_c.recv().unwrap();
})
.unwrap();
thread_a.join().unwrap();
thread_b.join().unwrap();
thread_c.join().unwrap();
}