91 lines
3.5 KiB
Rust
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();
|
||
|
}
|