Skip to content

Commit f845530

Browse files
authored
Merge pull request #90 from elast0ny/feature/add_tests
Feature/add tests
2 parents 1f3b6a1 + 8dfa117 commit f845530

File tree

7 files changed

+181
-29
lines changed

7 files changed

+181
-29
lines changed

.github/workflows/rust.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,16 @@ jobs:
4343
uses: actions-rs/cargo@v1.0.3
4444
with:
4545
command: build
46-
args: --all
46+
47+
- name: Tests
48+
uses: actions-rs/cargo@v1.0.3
49+
with:
50+
command: test
51+
4752
- name: Examples
4853
uses: actions-rs/cargo@v1.0.3
4954
env:
5055
RUST_LOG: "trace"
5156
with:
5257
command: run
53-
args: --all-features --example mutex -- 2
58+
args: --all-features --example mutex -- 15

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "shared_memory"
33
description = "A user friendly crate that allows you to share memory between processes"
4-
version = "0.12.3"
4+
version = "0.12.4"
55
authors = ["ElasT0ny <elast0ny00@gmail.com>"]
66
license = "MIT OR Apache-2.0"
77
edition = "2018"
@@ -35,7 +35,7 @@ nix = "0.23"
3535
libc = "0.2"
3636

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

4040
[dev-dependencies]
4141
raw_sync = "0.1"

examples/mutex.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,14 @@ fn increment_value(shmem_flink: &str, thread_num: usize) {
5858

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

6362
unsafe {
6463
is_init = &mut *(raw_ptr as *mut u8 as *mut AtomicU8);
6564
raw_ptr = raw_ptr.add(8);
6665
};
6766

6867
// Initialize or wait for initialized mutex
69-
if shmem.is_owner() {
68+
let mutex = if shmem.is_owner() {
7069
is_init.store(0, Ordering::Relaxed);
7170
// Initialize the mutex
7271
let (lock, _bytes_used) = unsafe {
@@ -77,7 +76,7 @@ fn increment_value(shmem_flink: &str, thread_num: usize) {
7776
.unwrap()
7877
};
7978
is_init.store(1, Ordering::Relaxed);
80-
mutex = lock;
79+
lock
8180
} else {
8281
// wait until mutex is initialized
8382
while is_init.load(Ordering::Relaxed) != 1 {}
@@ -89,8 +88,8 @@ fn increment_value(shmem_flink: &str, thread_num: usize) {
8988
)
9089
.unwrap()
9190
};
92-
mutex = lock;
93-
}
91+
lock
92+
};
9493

9594
// Loop until mutex data reaches 10
9695
loop {

src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub struct ShmemConf {
5252
overwrite_flink: bool,
5353
flink_path: Option<PathBuf>,
5454
size: usize,
55+
ext: os_impl::ShmemConfExt,
5556
}
5657
impl Drop for ShmemConf {
5758
fn drop(&mut self) {
@@ -184,6 +185,7 @@ impl ShmemConf {
184185
let mut retry = 0;
185186
loop {
186187
let unique_id = if let Some(ref unique_id) = self.os_id {
188+
retry = 5;
187189
unique_id.as_str()
188190
} else {
189191
let flink_path = self.flink_path.as_ref().unwrap();
@@ -202,7 +204,7 @@ impl ShmemConf {
202204
flink_uid.as_str()
203205
};
204206

205-
match os_impl::open_mapping(unique_id, self.size) {
207+
match os_impl::open_mapping(unique_id, self.size, &self.ext) {
206208
Ok(m) => {
207209
self.size = m.map_size;
208210
self.owner = false;

src/unix.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ use nix::unistd::{close, ftruncate};
99

1010
use crate::ShmemError;
1111

12+
#[derive(Clone, Default)]
13+
pub struct ShmemConfExt;
14+
1215
pub struct MapData {
1316
//On linux, you must shm_unlink() the object created for the mapping. It wont disappear automatically.
1417
owner: bool,
@@ -145,7 +148,11 @@ pub fn create_mapping(unique_id: &str, map_size: usize) -> Result<MapData, Shmem
145148
}
146149

147150
/// Opens an existing mapping specified by its uid
148-
pub fn open_mapping(unique_id: &str, _map_size: usize) -> Result<MapData, ShmemError> {
151+
pub fn open_mapping(
152+
unique_id: &str,
153+
_map_size: usize,
154+
_ext: &ShmemConfExt,
155+
) -> Result<MapData, ShmemError> {
149156
//Open shared memory
150157
debug!("Openning persistent mapping at {}", unique_id);
151158
let shmem_fd = match shm_open(

src/windows.rs

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,24 @@ use std::io::ErrorKind;
33
use std::os::windows::{fs::OpenOptionsExt, io::AsRawHandle};
44
use std::path::PathBuf;
55

6-
use crate::log::*;
6+
use crate::{log::*, ShmemConf};
77
use win_sys::*;
88

99
use crate::ShmemError;
1010

11+
#[derive(Clone, Default)]
12+
pub struct ShmemConfExt {
13+
allow_raw: bool,
14+
}
15+
16+
impl ShmemConf {
17+
/// If set to true, enables openning raw shared memory that is not managed by this crate
18+
pub fn allow_raw(mut self, allow: bool) -> Self {
19+
self.ext.allow_raw = allow;
20+
self
21+
}
22+
}
23+
1124
pub struct MapData {
1225
owner: bool,
1326

@@ -118,7 +131,12 @@ fn get_tmp_dir() -> Result<PathBuf, ShmemError> {
118131
}
119132
}
120133

121-
fn new_map(unique_id: &str, map_size: usize, create: bool) -> Result<MapData, ShmemError> {
134+
fn new_map(
135+
unique_id: &str,
136+
mut map_size: usize,
137+
create: bool,
138+
allow_raw: bool,
139+
) -> Result<MapData, ShmemError> {
122140
// Create file to back the shared memory
123141
let mut file_path = get_tmp_dir()?;
124142
file_path.push(unique_id.trim_start_matches('/'));
@@ -188,6 +206,8 @@ fn new_map(unique_id: &str, map_size: usize, create: bool) -> Result<MapData, Sh
188206
Err(e) => {
189207
if create {
190208
return Err(ShmemError::MapCreateFailed(e.raw_os_error().unwrap() as _));
209+
} else if !allow_raw {
210+
return Err(ShmemError::MapOpenFailed(ERROR_FILE_NOT_FOUND.0));
191211
}
192212

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

230-
let mut new_map = MapData {
231-
owner: create,
232-
file_map: map_h,
233-
persistent_file,
234-
unique_id: unique_id.to_string(),
235-
map_size: 0,
236-
view: map_ptr,
237-
};
238-
239250
if !create {
240251
//Get the real size of the openned mapping
241252
let mut info = MEMORY_BASIC_INFORMATION::default();
242-
if let Err(e) = VirtualQuery(new_map.view.as_mut_ptr() as _, &mut info) {
253+
if let Err(e) = VirtualQuery(map_ptr.as_mut_ptr(), &mut info) {
243254
return Err(ShmemError::UnknownOsError(e.win32_error().unwrap().0));
244255
}
245-
new_map.map_size = info.RegionSize;
256+
map_size = info.RegionSize;
246257
}
247258

248-
Ok(new_map)
259+
Ok(MapData {
260+
owner: create,
261+
file_map: map_h,
262+
persistent_file,
263+
unique_id: unique_id.to_string(),
264+
map_size,
265+
view: map_ptr,
266+
})
249267
}
250268

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

256274
//Opens an existing mapping specified by its uid
257-
pub fn open_mapping(unique_id: &str, map_size: usize) -> Result<MapData, ShmemError> {
258-
new_map(unique_id, map_size, false)
275+
pub fn open_mapping(
276+
unique_id: &str,
277+
map_size: usize,
278+
ext: &ShmemConfExt,
279+
) -> Result<MapData, ShmemError> {
280+
new_map(unique_id, map_size, false, ext.allow_raw)
259281
}

tests/general.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use std::path::Path;
2+
3+
use shared_memory::ShmemConf;
4+
5+
#[test]
6+
fn create_new() {
7+
let mut s = ShmemConf::new().size(4090).create().unwrap();
8+
9+
assert!(s.is_owner());
10+
assert!(!s.get_os_id().is_empty());
11+
assert!(s.len() >= 4090);
12+
assert!(!s.as_ptr().is_null());
13+
unsafe {
14+
assert_eq!(s.as_slice().len(), s.len());
15+
assert_eq!(s.as_slice_mut().len(), s.len());
16+
}
17+
}
18+
19+
#[test]
20+
fn create_with_flink() {
21+
let flink = Path::new("create_new1");
22+
23+
let mut s = ShmemConf::new().flink(flink).size(4090).create().unwrap();
24+
25+
assert!(s.is_owner());
26+
assert!(!s.get_os_id().is_empty());
27+
assert!(flink.is_file());
28+
assert!(s.len() >= 4090);
29+
assert!(!s.as_ptr().is_null());
30+
unsafe {
31+
assert_eq!(s.as_slice().len(), s.len());
32+
assert_eq!(s.as_slice_mut().len(), s.len());
33+
}
34+
35+
drop(s);
36+
37+
assert!(!flink.is_file());
38+
}
39+
40+
#[test]
41+
fn open_os_id() {
42+
let s1 = ShmemConf::new().size(4090).create().unwrap();
43+
44+
// Open with the unique os id
45+
let os_id = s1.get_os_id().to_string();
46+
let mut s2 = ShmemConf::new().os_id(&os_id).open().unwrap();
47+
48+
assert!(!s2.is_owner());
49+
assert!(!s2.get_os_id().is_empty());
50+
assert!(s2.len() >= 4090);
51+
assert!(!s2.as_ptr().is_null());
52+
unsafe {
53+
assert_eq!(s2.as_slice().len(), s2.len());
54+
assert_eq!(s2.as_slice_mut().len(), s2.len());
55+
}
56+
57+
// Drop the owner of the mapping
58+
drop(s1);
59+
60+
// Make sure it can be openned again
61+
assert!(ShmemConf::new().os_id(&os_id).open().is_err());
62+
63+
drop(s2);
64+
}
65+
66+
#[test]
67+
fn open_flink() {
68+
let flink = Path::new("create_new2");
69+
let s1 = ShmemConf::new().flink(flink).size(4090).create().unwrap();
70+
71+
// Open with file base link
72+
let mut s2 = ShmemConf::new().flink(&flink).open().unwrap();
73+
74+
assert!(!s2.is_owner());
75+
assert!(!s2.get_os_id().is_empty());
76+
assert!(flink.is_file());
77+
assert!(s2.len() >= 4090);
78+
assert!(!s2.as_ptr().is_null());
79+
unsafe {
80+
assert_eq!(s2.as_slice().len(), s2.len());
81+
assert_eq!(s2.as_slice_mut().len(), s2.len());
82+
}
83+
84+
// Drop the owner of the mapping
85+
drop(s1);
86+
87+
// Make sure it can be openned again
88+
assert!(ShmemConf::new().flink(&flink).open().is_err());
89+
90+
drop(s2);
91+
}
92+
93+
#[test]
94+
fn share_data() {
95+
let s1 = ShmemConf::new()
96+
.size(core::mem::size_of::<u32>())
97+
.create()
98+
.unwrap();
99+
100+
// Open with the unique os id
101+
let os_id = s1.get_os_id().to_string();
102+
let s2 = ShmemConf::new().os_id(&os_id).open().unwrap();
103+
104+
let ptr1 = s1.as_ptr() as *mut u32;
105+
let ptr2 = s2.as_ptr() as *mut u32;
106+
107+
// Confirm that the two pointers are different
108+
assert_ne!(ptr1, ptr2);
109+
110+
// Write a value from s1 and read it from s2
111+
unsafe {
112+
let shared_val = 0xBADC0FEE;
113+
ptr1.write_volatile(shared_val);
114+
let read_val = ptr2.read_volatile();
115+
assert_eq!(read_val, shared_val);
116+
}
117+
}

0 commit comments

Comments
 (0)