Skip to content

Commit 3d53bef

Browse files
test: add more tests (#1)
Co-authored-by: Asakura Mizu <asakuramizu111@gmail.com>
1 parent ce0522d commit 3d53bef

File tree

3 files changed

+139
-17
lines changed

3 files changed

+139
-17
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ repository = "https://github.com/Starry-OS/scope-local"
1010

1111
[dependencies]
1212
percpu = "0.2"
13-
spin = { version = "0.9", default-features = false, features = ["lazy"] }
13+
spin = { version = "0.10", default-features = false, features = ["lazy"] }
1414

1515
[dev-dependencies]
16-
ctor = "0.4.2"
16+
ctor = "0.6"
17+
percpu = { version = "0.2", features = ["non-zero-vma"] }

percpu.x

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ SECTIONS
55
. = ALIGN(4K);
66
_percpu_start = .;
77
_percpu_end = _percpu_start + SIZEOF(.percpu);
8-
.percpu 0x0 (NOLOAD) : AT(_percpu_start) {
8+
.percpu (NOLOAD) : AT(_percpu_start) {
99
_percpu_load_start = .;
1010
*(.percpu .percpu.*)
1111
_percpu_load_end = .;
12-
. = _percpu_load_start + ALIGN(64) * CPU_NUM;
12+
_percpu_load_end_aligned = ALIGN(64);
13+
. = _percpu_load_start + (_percpu_load_end_aligned - _percpu_load_start) * CPU_NUM;
1314
}
1415
. = _percpu_end;
1516
}

tests/scope_local.rs

Lines changed: 133 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1-
use std::sync::Arc;
1+
use std::{
2+
panic,
3+
sync::{
4+
Arc,
5+
atomic::{AtomicUsize, Ordering},
6+
},
7+
thread,
8+
};
29

310
use ctor::ctor;
411
use scope_local::{ActiveScope, Scope, scope_local};
512

613
#[ctor]
7-
fn init() {
14+
fn init_percpu() {
815
percpu::init();
916

1017
unsafe { percpu::write_percpu_reg(percpu::percpu_area_base(0)) };
@@ -14,18 +21,22 @@ fn init() {
1421
println!("per-CPU area size = {}", percpu::percpu_area_size());
1522
}
1623

17-
scope_local! {
18-
static DATA: usize = 0;
19-
}
20-
2124
#[test]
22-
fn global() {
23-
assert_eq!(*DATA, 0);
25+
fn scope_init() {
26+
scope_local! {
27+
static DATA: usize = 42;
28+
}
29+
assert_eq!(*DATA, 42);
2430
}
2531

2632
#[test]
2733
fn scope() {
34+
scope_local! {
35+
static DATA: usize = 0;
36+
}
37+
2838
let mut scope = Scope::new();
39+
assert_eq!(*DATA, 0);
2940
assert_eq!(*DATA.scope(&scope), 0);
3041

3142
*DATA.scope_mut(&mut scope) = 42;
@@ -35,14 +46,16 @@ fn scope() {
3546
assert_eq!(*DATA, 42);
3647

3748
ActiveScope::set_global();
38-
}
39-
40-
scope_local! {
41-
static SHARED: Arc<String> = Arc::new("qwq".to_string());
49+
assert_eq!(*DATA, 0);
50+
assert_eq!(*DATA.scope(&scope), 42);
4251
}
4352

4453
#[test]
45-
fn shared() {
54+
fn scope_drop() {
55+
scope_local! {
56+
static SHARED: Arc<()> = Arc::new(());
57+
}
58+
4659
assert_eq!(Arc::strong_count(&SHARED), 1);
4760

4861
{
@@ -55,3 +68,110 @@ fn shared() {
5568

5669
assert_eq!(Arc::strong_count(&SHARED), 1);
5770
}
71+
72+
#[test]
73+
fn scope_panic_unwind_drop() {
74+
scope_local! {
75+
static SHARED: Arc<()> = Arc::new(());
76+
}
77+
78+
let panic = panic::catch_unwind(|| {
79+
let mut scope = Scope::new();
80+
*SHARED.scope_mut(&mut scope) = SHARED.clone();
81+
assert_eq!(Arc::strong_count(&SHARED), 2);
82+
panic!("panic");
83+
});
84+
assert!(panic.is_err());
85+
86+
assert_eq!(Arc::strong_count(&SHARED), 1);
87+
}
88+
89+
#[test]
90+
fn thread_share_item() {
91+
scope_local! {
92+
static SHARED: Arc<()> = Arc::new(());
93+
}
94+
95+
let handles: Vec<_> = (0..10)
96+
.map(|_| {
97+
thread::spawn(move || {
98+
let global = &*SHARED;
99+
100+
let mut scope = Scope::new();
101+
*SHARED.scope_mut(&mut scope) = global.clone();
102+
103+
unsafe { ActiveScope::set(&scope) };
104+
105+
assert!(Arc::strong_count(&SHARED) >= 2);
106+
assert!(Arc::ptr_eq(&SHARED, global));
107+
108+
ActiveScope::set_global();
109+
})
110+
})
111+
.collect();
112+
113+
for h in handles {
114+
h.join().unwrap();
115+
}
116+
117+
assert_eq!(Arc::strong_count(&SHARED), 1);
118+
}
119+
120+
#[test]
121+
fn thread_share_scope() {
122+
scope_local! {
123+
static SHARED: Arc<()> = Arc::new(());
124+
}
125+
126+
let scope = Arc::new(Scope::new());
127+
128+
let handles: Vec<_> = (0..10)
129+
.map(|_| {
130+
let scope = scope.clone();
131+
thread::spawn(move || {
132+
unsafe { ActiveScope::set(&scope) };
133+
assert_eq!(Arc::strong_count(&SHARED), 1);
134+
assert!(Arc::ptr_eq(&SHARED, &SHARED.scope(&scope)));
135+
ActiveScope::set_global();
136+
})
137+
})
138+
.collect();
139+
140+
for h in handles {
141+
h.join().unwrap();
142+
}
143+
144+
assert_eq!(Arc::strong_count(&SHARED), 1);
145+
assert_eq!(Arc::strong_count(&SHARED.scope(&scope)), 1);
146+
}
147+
148+
#[test]
149+
fn thread_isolation() {
150+
scope_local! {
151+
static DATA: usize = 42;
152+
static DATA2: AtomicUsize = AtomicUsize::new(42);
153+
}
154+
155+
let handles: Vec<_> = (0..10)
156+
.map(|i| {
157+
thread::spawn(move || {
158+
let mut scope = Scope::new();
159+
*DATA.scope_mut(&mut scope) = i;
160+
161+
unsafe { ActiveScope::set(&scope) };
162+
assert_eq!(*DATA, i);
163+
164+
DATA2.store(i, Ordering::Relaxed);
165+
166+
ActiveScope::set_global();
167+
})
168+
})
169+
.collect();
170+
171+
for h in handles {
172+
h.join().unwrap();
173+
}
174+
175+
assert_eq!(*DATA, 42);
176+
assert_eq!(DATA2.load(Ordering::Relaxed), 42);
177+
}

0 commit comments

Comments
 (0)