Skip to content

Commit

Permalink
Merge pull request #90 from elast0ny/feature/add_tests
Browse files Browse the repository at this point in the history
Feature/add tests
  • Loading branch information
elast0ny committed Mar 1, 2022
2 parents 1f3b6a1 + 8dfa117 commit f845530
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 29 deletions.
9 changes: 7 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,16 @@ jobs:
uses: actions-rs/[email protected]
with:
command: build
args: --all

- name: Tests
uses: actions-rs/[email protected]
with:
command: test

- name: Examples
uses: actions-rs/[email protected]
env:
RUST_LOG: "trace"
with:
command: run
args: --all-features --example mutex -- 2
args: --all-features --example mutex -- 15
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "shared_memory"
description = "A user friendly crate that allows you to share memory between processes"
version = "0.12.3"
version = "0.12.4"
authors = ["ElasT0ny <[email protected]>"]
license = "MIT OR Apache-2.0"
edition = "2018"
Expand Down Expand Up @@ -35,7 +35,7 @@ nix = "0.23"
libc = "0.2"

[target.'cfg(windows)'.dependencies]
win-sys = "0.2"
win-sys = "0.3"

[dev-dependencies]
raw_sync = "0.1"
Expand Down
9 changes: 4 additions & 5 deletions examples/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,14 @@ fn increment_value(shmem_flink: &str, thread_num: usize) {

let mut raw_ptr = shmem.as_ptr();
let is_init: &mut AtomicU8;
let mutex: Box<dyn LockImpl>;

unsafe {
is_init = &mut *(raw_ptr as *mut u8 as *mut AtomicU8);
raw_ptr = raw_ptr.add(8);
};

// Initialize or wait for initialized mutex
if shmem.is_owner() {
let mutex = if shmem.is_owner() {
is_init.store(0, Ordering::Relaxed);
// Initialize the mutex
let (lock, _bytes_used) = unsafe {
Expand All @@ -77,7 +76,7 @@ fn increment_value(shmem_flink: &str, thread_num: usize) {
.unwrap()
};
is_init.store(1, Ordering::Relaxed);
mutex = lock;
lock
} else {
// wait until mutex is initialized
while is_init.load(Ordering::Relaxed) != 1 {}
Expand All @@ -89,8 +88,8 @@ fn increment_value(shmem_flink: &str, thread_num: usize) {
)
.unwrap()
};
mutex = lock;
}
lock
};

// Loop until mutex data reaches 10
loop {
Expand Down
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub struct ShmemConf {
overwrite_flink: bool,
flink_path: Option<PathBuf>,
size: usize,
ext: os_impl::ShmemConfExt,
}
impl Drop for ShmemConf {
fn drop(&mut self) {
Expand Down Expand Up @@ -184,6 +185,7 @@ impl ShmemConf {
let mut retry = 0;
loop {
let unique_id = if let Some(ref unique_id) = self.os_id {
retry = 5;
unique_id.as_str()
} else {
let flink_path = self.flink_path.as_ref().unwrap();
Expand All @@ -202,7 +204,7 @@ impl ShmemConf {
flink_uid.as_str()
};

match os_impl::open_mapping(unique_id, self.size) {
match os_impl::open_mapping(unique_id, self.size, &self.ext) {
Ok(m) => {
self.size = m.map_size;
self.owner = false;
Expand Down
9 changes: 8 additions & 1 deletion src/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use nix::unistd::{close, ftruncate};

use crate::ShmemError;

#[derive(Clone, Default)]
pub struct ShmemConfExt;

pub struct MapData {
//On linux, you must shm_unlink() the object created for the mapping. It wont disappear automatically.
owner: bool,
Expand Down Expand Up @@ -145,7 +148,11 @@ pub fn create_mapping(unique_id: &str, map_size: usize) -> Result<MapData, Shmem
}

/// Opens an existing mapping specified by its uid
pub fn open_mapping(unique_id: &str, _map_size: usize) -> Result<MapData, ShmemError> {
pub fn open_mapping(
unique_id: &str,
_map_size: usize,
_ext: &ShmemConfExt,
) -> Result<MapData, ShmemError> {
//Open shared memory
debug!("Openning persistent mapping at {}", unique_id);
let shmem_fd = match shm_open(
Expand Down
58 changes: 40 additions & 18 deletions src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,24 @@ use std::io::ErrorKind;
use std::os::windows::{fs::OpenOptionsExt, io::AsRawHandle};
use std::path::PathBuf;

use crate::log::*;
use crate::{log::*, ShmemConf};
use win_sys::*;

use crate::ShmemError;

#[derive(Clone, Default)]
pub struct ShmemConfExt {
allow_raw: bool,
}

impl ShmemConf {
/// If set to true, enables openning raw shared memory that is not managed by this crate
pub fn allow_raw(mut self, allow: bool) -> Self {
self.ext.allow_raw = allow;
self
}
}

pub struct MapData {
owner: bool,

Expand Down Expand Up @@ -118,7 +131,12 @@ fn get_tmp_dir() -> Result<PathBuf, ShmemError> {
}
}

fn new_map(unique_id: &str, map_size: usize, create: bool) -> Result<MapData, ShmemError> {
fn new_map(
unique_id: &str,
mut map_size: usize,
create: bool,
allow_raw: bool,
) -> Result<MapData, ShmemError> {
// Create file to back the shared memory
let mut file_path = get_tmp_dir()?;
file_path.push(unique_id.trim_start_matches('/'));
Expand Down Expand Up @@ -188,6 +206,8 @@ fn new_map(unique_id: &str, map_size: usize, create: bool) -> Result<MapData, Sh
Err(e) => {
if create {
return Err(ShmemError::MapCreateFailed(e.raw_os_error().unwrap() as _));
} else if !allow_raw {
return Err(ShmemError::MapOpenFailed(ERROR_FILE_NOT_FOUND.0));
}

// This may be a mapping that isnt managed by this crate
Expand Down Expand Up @@ -216,7 +236,7 @@ fn new_map(unique_id: &str, map_size: usize, create: bool) -> Result<MapData, Sh
(FILE_MAP_READ | FILE_MAP_WRITE).0,
);
let map_ptr = match MapViewOfFile(map_h.as_handle(), FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0) {
Ok(v) => v as _,
Ok(v) => v,
Err(e) => {
return Err(if create {
ShmemError::MapCreateFailed(e.win32_error().unwrap().0)
Expand All @@ -227,33 +247,35 @@ fn new_map(unique_id: &str, map_size: usize, create: bool) -> Result<MapData, Sh
};
trace!("\t{:p}", map_ptr);

let mut new_map = MapData {
owner: create,
file_map: map_h,
persistent_file,
unique_id: unique_id.to_string(),
map_size: 0,
view: map_ptr,
};

if !create {
//Get the real size of the openned mapping
let mut info = MEMORY_BASIC_INFORMATION::default();
if let Err(e) = VirtualQuery(new_map.view.as_mut_ptr() as _, &mut info) {
if let Err(e) = VirtualQuery(map_ptr.as_mut_ptr(), &mut info) {
return Err(ShmemError::UnknownOsError(e.win32_error().unwrap().0));
}
new_map.map_size = info.RegionSize;
map_size = info.RegionSize;
}

Ok(new_map)
Ok(MapData {
owner: create,
file_map: map_h,
persistent_file,
unique_id: unique_id.to_string(),
map_size,
view: map_ptr,
})
}

//Creates a mapping specified by the uid and size
pub fn create_mapping(unique_id: &str, map_size: usize) -> Result<MapData, ShmemError> {
new_map(unique_id, map_size, true)
new_map(unique_id, map_size, true, false)
}

//Opens an existing mapping specified by its uid
pub fn open_mapping(unique_id: &str, map_size: usize) -> Result<MapData, ShmemError> {
new_map(unique_id, map_size, false)
pub fn open_mapping(
unique_id: &str,
map_size: usize,
ext: &ShmemConfExt,
) -> Result<MapData, ShmemError> {
new_map(unique_id, map_size, false, ext.allow_raw)
}
117 changes: 117 additions & 0 deletions tests/general.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use std::path::Path;

use shared_memory::ShmemConf;

#[test]
fn create_new() {
let mut s = ShmemConf::new().size(4090).create().unwrap();

assert!(s.is_owner());
assert!(!s.get_os_id().is_empty());
assert!(s.len() >= 4090);
assert!(!s.as_ptr().is_null());
unsafe {
assert_eq!(s.as_slice().len(), s.len());
assert_eq!(s.as_slice_mut().len(), s.len());
}
}

#[test]
fn create_with_flink() {
let flink = Path::new("create_new1");

let mut s = ShmemConf::new().flink(flink).size(4090).create().unwrap();

assert!(s.is_owner());
assert!(!s.get_os_id().is_empty());
assert!(flink.is_file());
assert!(s.len() >= 4090);
assert!(!s.as_ptr().is_null());
unsafe {
assert_eq!(s.as_slice().len(), s.len());
assert_eq!(s.as_slice_mut().len(), s.len());
}

drop(s);

assert!(!flink.is_file());
}

#[test]
fn open_os_id() {
let s1 = ShmemConf::new().size(4090).create().unwrap();

// Open with the unique os id
let os_id = s1.get_os_id().to_string();
let mut s2 = ShmemConf::new().os_id(&os_id).open().unwrap();

assert!(!s2.is_owner());
assert!(!s2.get_os_id().is_empty());
assert!(s2.len() >= 4090);
assert!(!s2.as_ptr().is_null());
unsafe {
assert_eq!(s2.as_slice().len(), s2.len());
assert_eq!(s2.as_slice_mut().len(), s2.len());
}

// Drop the owner of the mapping
drop(s1);

// Make sure it can be openned again
assert!(ShmemConf::new().os_id(&os_id).open().is_err());

drop(s2);
}

#[test]
fn open_flink() {
let flink = Path::new("create_new2");
let s1 = ShmemConf::new().flink(flink).size(4090).create().unwrap();

// Open with file base link
let mut s2 = ShmemConf::new().flink(&flink).open().unwrap();

assert!(!s2.is_owner());
assert!(!s2.get_os_id().is_empty());
assert!(flink.is_file());
assert!(s2.len() >= 4090);
assert!(!s2.as_ptr().is_null());
unsafe {
assert_eq!(s2.as_slice().len(), s2.len());
assert_eq!(s2.as_slice_mut().len(), s2.len());
}

// Drop the owner of the mapping
drop(s1);

// Make sure it can be openned again
assert!(ShmemConf::new().flink(&flink).open().is_err());

drop(s2);
}

#[test]
fn share_data() {
let s1 = ShmemConf::new()
.size(core::mem::size_of::<u32>())
.create()
.unwrap();

// Open with the unique os id
let os_id = s1.get_os_id().to_string();
let s2 = ShmemConf::new().os_id(&os_id).open().unwrap();

let ptr1 = s1.as_ptr() as *mut u32;
let ptr2 = s2.as_ptr() as *mut u32;

// Confirm that the two pointers are different
assert_ne!(ptr1, ptr2);

// Write a value from s1 and read it from s2
unsafe {
let shared_val = 0xBADC0FEE;
ptr1.write_volatile(shared_val);
let read_val = ptr2.read_volatile();
assert_eq!(read_val, shared_val);
}
}

0 comments on commit f845530

Please sign in to comment.