Skip to content

Commit

Permalink
BackingStore tests
Browse files Browse the repository at this point in the history
  • Loading branch information
aapoalas committed Oct 2, 2023
1 parent e8fc53e commit f5816cf
Showing 1 changed file with 88 additions and 7 deletions.
95 changes: 88 additions & 7 deletions nova_vm/src/heap/array_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use super::{
/// the capacity or length. The pointer can be None
/// if the length of the buffer is zero.
#[derive(Debug, Copy, Clone)]
pub(crate) struct BackingStore {
pub struct BackingStore {
ptr: Option<NonNull<u8>>,
cap: u32,
byte_length: u32,
Expand Down Expand Up @@ -129,7 +129,7 @@ impl BackingStore {
}

fn as_ptr(&self, byte_offset: u32) -> Option<*const u8> {
if byte_offset > self.byte_length {
if byte_offset >= self.byte_length {
None
} else if let Some(data) = self.ptr {
// SAFETY: The data is properly initialized, and the T being read is
Expand All @@ -141,7 +141,7 @@ impl BackingStore {
}

fn as_mut_ptr(&mut self, byte_offset: u32) -> Option<*mut u8> {
if byte_offset > self.byte_length {
if byte_offset >= self.byte_length {
None
} else if let Some(data) = self.ptr {
// SAFETY: The data is properly initialized, and the T being read is
Expand All @@ -155,7 +155,7 @@ impl BackingStore {
pub fn get<T: Viewable>(&self, offset: u32) -> Option<T> {
let size = std::mem::size_of::<T>() as u32;
let byte_offset = offset * size;
if byte_offset > self.byte_length {
if byte_offset >= self.byte_length {
None
} else if let Some(data) = self.ptr {
// SAFETY: The data is properly initialized, and the T being read is
Expand Down Expand Up @@ -192,20 +192,20 @@ impl BackingStore {
// SAFETY: Source buffer length is valid, destination buffer
// is likewise at least equal in length to source, and both
// are properly aligned for bytes.
unsafe { std::ptr::copy::<u8>(src, dst, byte_length) }
unsafe { std::ptr::copy::<u8>(src, dst, byte_length as usize) }
}
}
}

#[derive(Debug)]
pub(crate) enum InternalBuffer {
pub enum InternalBuffer {
Detached,
Growable(BackingStore),
Static(BackingStore),
}

#[derive(Debug)]
pub(crate) struct ArrayBufferHeapData {
pub struct ArrayBufferHeapData {
pub(super) object_index: Option<ObjectIndex>,
pub(super) buffer: InternalBuffer,
// detach_key
Expand Down Expand Up @@ -300,3 +300,84 @@ fn array_buffer_species(_heap: &mut Heap, this: Value, _args: &[Value]) -> JsRes
fn array_buffer_todo(_heap: &mut Heap, _this: Value, _args: &[Value]) -> JsResult<Value> {
todo!()
}

#[test]
fn new_backing_store() {
let bs = BackingStore::new(0);
assert_eq!(bs.len(), 0);
assert_eq!(bs.capacity(), 0);
assert_eq!(bs.get::<u8>(0), None);

let bs = BackingStore::new(8);
assert_eq!(bs.len(), 8);
assert_eq!(bs.capacity(), 8);
for i in 0..8 {
assert_eq!(bs.get::<u8>(i as u32), Some(0));
}
}

#[test]
fn new_backing_store_with_capacity() {
let bs = BackingStore::new_with_capacity(0, 8);
assert_eq!(bs.len(), 0);
assert_eq!(bs.capacity(), 8);
for i in 0..8 {
assert_eq!(bs.get::<u8>(i as u32), None);
}

let bs = BackingStore::new_with_capacity(8, 16);
assert_eq!(bs.len(), 8);
assert_eq!(bs.capacity(), 16);
for i in 0..8 {
assert_eq!(bs.get::<u8>(i as u32), Some(0));
}
for i in 8..16 {
assert_eq!(bs.get::<u8>(i as u32), None);
}
}

#[test]
fn backing_store_set() {
let mut bs = BackingStore::new(8);
assert_eq!(bs.len(), 8);
assert_eq!(bs.capacity(), 8);
for i in 0..8 {
assert_eq!(bs.get::<u8>(i as u32), Some(0));
}

for i in 0..8 {
bs.set::<u8>(i as u32, i + 1);
}

for i in 0..8 {
assert_eq!(bs.get::<u8>(i as u32), Some(i + 1));
}
}

#[test]
fn backing_store_resize() {
let mut bs = BackingStore::new_with_capacity(0, 8);
bs.resize(8);
assert_eq!(bs.len(), 8);
assert_eq!(bs.capacity(), 8);
for i in 0..8 {
assert_eq!(bs.get::<u8>(i as u32), Some(0));
}

for i in 0..8 {
bs.set::<u8>(i as u32, i + 1);
}

let ptr = bs.as_ptr(0).unwrap();
bs.resize(0);

// SAFETY: Backing store is not deallocated: Zero index pointer is still valid
// and is not read beyond its allocated capacity. The only usual safety requirement
// broken is to read beyond the buffer length, which is safe as the outside is still
// properly initialized u8s.
unsafe {
for i in 0..8 {
assert_eq!(ptr.add(i).read(), 0);
}
}
}

0 comments on commit f5816cf

Please sign in to comment.