mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 12:56:48 +00:00
Add ktests for the XArray
This commit is contained in:
parent
c3dd607777
commit
1fe0fef410
@ -72,6 +72,9 @@ mod mark;
|
||||
mod node;
|
||||
mod range;
|
||||
|
||||
#[cfg(ktest)]
|
||||
mod test;
|
||||
|
||||
const BITS_PER_LAYER: usize = 6;
|
||||
const SLOT_SIZE: usize = 1 << BITS_PER_LAYER;
|
||||
const SLOT_MASK: usize = SLOT_SIZE - 1;
|
||||
|
335
kernel/libs/xarray/src/test.rs
Normal file
335
kernel/libs/xarray/src/test.rs
Normal file
@ -0,0 +1,335 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use alloc::{boxed::Box, sync::Arc};
|
||||
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
|
||||
use ostd::{
|
||||
prelude::ktest,
|
||||
task::{disable_preempt, Task},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
macro_rules! n {
|
||||
( $x:expr ) => {
|
||||
$x * 10
|
||||
};
|
||||
}
|
||||
|
||||
fn init_continuous_with_arc<M>(xarray: &XArray<Arc<i32>, M>, item_num: i32) {
|
||||
for i in 0..item_num {
|
||||
let value = Arc::new(i);
|
||||
xarray.lock().store(i as u64, value);
|
||||
}
|
||||
}
|
||||
|
||||
fn init_sparse_with_arc<M>(xarray: &XArray<Arc<i32>, M>, item_num: i32) {
|
||||
for i in 0..2 * item_num {
|
||||
if i % 2 == 0 {
|
||||
let value = Arc::new(i);
|
||||
xarray.lock().store(i as u64, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn store_continuous() {
|
||||
let xarray_arc: XArray<Arc<i32>> = XArray::new();
|
||||
init_continuous_with_arc(&xarray_arc, n!(100));
|
||||
let guard = disable_preempt();
|
||||
for i in 0..n!(100) {
|
||||
let value = xarray_arc.load(&guard, i as u64).unwrap();
|
||||
assert_eq!(*value.as_ref(), i);
|
||||
}
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn store_sparse() {
|
||||
let xarray_arc: XArray<Arc<i32>> = XArray::new();
|
||||
init_sparse_with_arc(&xarray_arc, n!(100));
|
||||
|
||||
let guard = disable_preempt();
|
||||
for i in 0..n!(100) {
|
||||
if i % 2 == 0 {
|
||||
let value = xarray_arc.load(&guard, i as u64).unwrap();
|
||||
assert_eq!(*value.as_ref(), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn store_overwrite() {
|
||||
let xarray_arc: XArray<Arc<i32>> = XArray::new();
|
||||
init_continuous_with_arc(&xarray_arc, n!(100));
|
||||
|
||||
let mut locked_xarray = xarray_arc.lock();
|
||||
// Overwrite 20 at index 10.
|
||||
let value = Arc::new(20);
|
||||
locked_xarray.store(10, value);
|
||||
let v = locked_xarray.load(10).unwrap();
|
||||
assert_eq!(*v.as_ref(), 20);
|
||||
// Overwrite 40 at index 10.
|
||||
let value = Arc::new(40);
|
||||
locked_xarray.store(10, value);
|
||||
let v = locked_xarray.load(10).unwrap();
|
||||
assert_eq!(*v.as_ref(), 40);
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn remove() {
|
||||
let xarray_arc: XArray<Arc<i32>> = XArray::new();
|
||||
assert!(xarray_arc.lock().remove(n!(1)).is_none());
|
||||
init_continuous_with_arc(&xarray_arc, n!(100));
|
||||
|
||||
let mut locked_xarray = xarray_arc.lock();
|
||||
for i in 0..n!(100) {
|
||||
assert_eq!(*locked_xarray.remove(i as u64).unwrap().as_ref(), i);
|
||||
let value = locked_xarray.load(i as u64);
|
||||
assert!(value.is_none());
|
||||
assert!(locked_xarray.remove(i as u64).is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn cursor_load() {
|
||||
let xarray_arc: XArray<Arc<i32>> = XArray::new();
|
||||
init_continuous_with_arc(&xarray_arc, n!(100));
|
||||
|
||||
let guard = disable_preempt();
|
||||
let mut cursor = xarray_arc.cursor(&guard, 0);
|
||||
|
||||
for i in 0..n!(100) {
|
||||
let value = cursor.load().unwrap();
|
||||
assert_eq!(*value.as_ref(), i);
|
||||
cursor.next();
|
||||
}
|
||||
|
||||
cursor.reset_to(n!(200));
|
||||
assert!(cursor.load().is_none());
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn cursor_load_very_sparse() {
|
||||
let xarray_arc: XArray<Arc<i32>> = XArray::new();
|
||||
let mut locked_xarray = xarray_arc.lock();
|
||||
locked_xarray.store(0, Arc::new(1));
|
||||
locked_xarray.store(n!(100), Arc::new(2));
|
||||
|
||||
let mut cursor = locked_xarray.cursor(0);
|
||||
assert_eq!(*cursor.load().unwrap().as_ref(), 1);
|
||||
for _ in 0..n!(100) {
|
||||
cursor.next();
|
||||
}
|
||||
assert_eq!(*cursor.load().unwrap().as_ref(), 2);
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn cursor_store_continuous() {
|
||||
let xarray_arc: XArray<Arc<i32>> = XArray::new();
|
||||
let mut locked_xarray = xarray_arc.lock();
|
||||
let mut cursor = locked_xarray.cursor_mut(0);
|
||||
|
||||
for i in 0..n!(100) {
|
||||
let value = Arc::new(i);
|
||||
cursor.store(value);
|
||||
cursor.next();
|
||||
}
|
||||
|
||||
for i in 0..n!(100) {
|
||||
let value = locked_xarray.load(i as u64).unwrap();
|
||||
assert_eq!(*value.as_ref(), i);
|
||||
}
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn cursor_store_sparse() {
|
||||
let xarray_arc: XArray<Arc<i32>> = XArray::new();
|
||||
let mut locked_xarray = xarray_arc.lock();
|
||||
let mut cursor = locked_xarray.cursor_mut(0);
|
||||
|
||||
for i in 0..n!(100) {
|
||||
if i % 2 == 0 {
|
||||
let value = Arc::new(i);
|
||||
cursor.store(value);
|
||||
}
|
||||
cursor.next();
|
||||
}
|
||||
|
||||
for i in 0..n!(100) {
|
||||
if i % 2 == 0 {
|
||||
let value = locked_xarray.load(i as u64).unwrap();
|
||||
assert_eq!(*value.as_ref(), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn set_mark() {
|
||||
let xarray_arc: XArray<Arc<i32>, XMark> = XArray::new();
|
||||
init_continuous_with_arc(&xarray_arc, n!(100));
|
||||
|
||||
let mut locked_xarray = xarray_arc.lock();
|
||||
let mut cursor = locked_xarray.cursor_mut(n!(10));
|
||||
cursor.set_mark(XMark::Mark0).unwrap();
|
||||
cursor.set_mark(XMark::Mark1).unwrap();
|
||||
cursor.reset_to(n!(20));
|
||||
cursor.set_mark(XMark::Mark1).unwrap();
|
||||
|
||||
cursor.reset_to(n!(10));
|
||||
let value1_mark0 = cursor.is_marked(XMark::Mark0);
|
||||
let value1_mark1 = cursor.is_marked(XMark::Mark1);
|
||||
|
||||
cursor.reset_to(n!(20));
|
||||
let value2_mark0 = cursor.is_marked(XMark::Mark0);
|
||||
let value2_mark1 = cursor.is_marked(XMark::Mark1);
|
||||
|
||||
cursor.reset_to(n!(30));
|
||||
let value3_mark1 = cursor.is_marked(XMark::Mark1);
|
||||
|
||||
assert!(value1_mark0);
|
||||
assert!(value1_mark1);
|
||||
assert!(!value2_mark0);
|
||||
assert!(value2_mark1);
|
||||
assert!(!value3_mark1);
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn unset_mark() {
|
||||
let xarray_arc: XArray<Arc<i32>, XMark> = XArray::new();
|
||||
init_continuous_with_arc(&xarray_arc, n!(100));
|
||||
|
||||
let mut locked_xarray = xarray_arc.lock();
|
||||
let mut cursor = locked_xarray.cursor_mut(n!(10));
|
||||
cursor.set_mark(XMark::Mark0).unwrap();
|
||||
cursor.set_mark(XMark::Mark1).unwrap();
|
||||
|
||||
cursor.unset_mark(XMark::Mark0).unwrap();
|
||||
cursor.unset_mark(XMark::Mark2).unwrap();
|
||||
|
||||
let value1_mark0 = cursor.is_marked(XMark::Mark0);
|
||||
let value1_mark2 = cursor.is_marked(XMark::Mark2);
|
||||
assert!(!value1_mark0);
|
||||
assert!(!value1_mark2);
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn mark_overflow() {
|
||||
let xarray_arc: XArray<Arc<i32>, XMark> = XArray::new();
|
||||
init_continuous_with_arc(&xarray_arc, n!(100));
|
||||
let mut locked_xarray = xarray_arc.lock();
|
||||
let mut cursor = locked_xarray.cursor_mut(n!(200));
|
||||
|
||||
assert!(cursor.set_mark(XMark::Mark1).is_err());
|
||||
assert!(!cursor.is_marked(XMark::Mark1));
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn box_operate() {
|
||||
let xarray_box: XArray<Box<i32>> = XArray::new();
|
||||
let mut locked_xarray = xarray_box.lock();
|
||||
let mut cursor_mut = locked_xarray.cursor_mut(0);
|
||||
for i in 0..n!(100) {
|
||||
if i % 2 == 0 {
|
||||
cursor_mut.store(Box::new(i * 2));
|
||||
}
|
||||
cursor_mut.next();
|
||||
}
|
||||
|
||||
cursor_mut.reset_to(0);
|
||||
for i in 0..n!(100) {
|
||||
if i % 2 == 0 {
|
||||
assert_eq!(*cursor_mut.load().unwrap().as_ref(), i * 2);
|
||||
} else {
|
||||
assert!(cursor_mut.load().is_none());
|
||||
}
|
||||
cursor_mut.next();
|
||||
}
|
||||
|
||||
let mut cursor = locked_xarray.cursor(0);
|
||||
for i in 0..n!(100) {
|
||||
if i % 2 == 0 {
|
||||
assert_eq!(*cursor.load().unwrap().as_ref(), i * 2);
|
||||
} else {
|
||||
assert!(cursor.load().is_none());
|
||||
}
|
||||
cursor.next();
|
||||
}
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn range() {
|
||||
let xarray_arc: XArray<Arc<i32>> = XArray::new();
|
||||
for i in 0..n!(100) {
|
||||
let value = Arc::new(i * 2);
|
||||
xarray_arc.lock().store((i * 2) as u64, value);
|
||||
}
|
||||
|
||||
let mut count = 0;
|
||||
let guard = disable_preempt();
|
||||
for (index, item) in xarray_arc.range(&guard, n!(10)..n!(20)) {
|
||||
assert_eq!(*item.as_ref() as u64, index);
|
||||
count += 1;
|
||||
}
|
||||
assert_eq!(count, n!(5));
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn load_after_clear() {
|
||||
let xarray_arc: XArray<Arc<i32>> = XArray::new();
|
||||
init_continuous_with_arc(&xarray_arc, n!(100));
|
||||
|
||||
let guard = disable_preempt();
|
||||
let mut cursor = xarray_arc.cursor(&guard, 100);
|
||||
let mut locked_xarray = xarray_arc.lock();
|
||||
|
||||
let value = cursor.load().unwrap();
|
||||
assert_eq!(*value.as_ref(), 100);
|
||||
|
||||
// Read the old data.
|
||||
locked_xarray.clear();
|
||||
let value = cursor.load().unwrap();
|
||||
assert_eq!(*value.as_ref(), 100);
|
||||
|
||||
// Read the new data.
|
||||
cursor.reset();
|
||||
assert!(cursor.load().is_none());
|
||||
}
|
||||
|
||||
static TEST_LEAKAGE: AtomicBool = AtomicBool::new(false);
|
||||
static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
impl<P: NonNullPtr + Send + Sync> Drop for node::XNode<P> {
|
||||
fn drop(&mut self) {
|
||||
if TEST_LEAKAGE.load(Ordering::Relaxed) {
|
||||
DROP_COUNT.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
fn no_leakage() {
|
||||
fn finish_grace_period() {
|
||||
let task = || {};
|
||||
let _ = ostd::task::TaskOptions::new(task).data(()).spawn();
|
||||
Task::yield_now();
|
||||
}
|
||||
|
||||
// Drop the nodes created by the previous tests.
|
||||
finish_grace_period();
|
||||
TEST_LEAKAGE.store(true, Ordering::Relaxed);
|
||||
|
||||
let xarray_arc: XArray<Arc<i32>> = XArray::new();
|
||||
init_sparse_with_arc(&xarray_arc, (SLOT_SIZE * SLOT_SIZE / 2 + 1) as i32);
|
||||
drop(xarray_arc);
|
||||
|
||||
// Drop the nodes created in the test.
|
||||
finish_grace_period();
|
||||
TEST_LEAKAGE.store(false, Ordering::Relaxed);
|
||||
|
||||
let count = DROP_COUNT.load(Ordering::Relaxed);
|
||||
// layer 3: 1
|
||||
// layer 2: 1 + 1
|
||||
// layer 1: 64 + 1
|
||||
let expected = 68;
|
||||
assert_eq!(count, expected);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user