blob: e60952ae84e19049a0fb0c51ddad72ef55c04409 [file] [log] [blame]
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
use googletest::prelude::*;
use static_assertions::assert_impl_all;
use std::cell::RefCell;
use std::cmp::Ordering;
use std::ffi::c_void;
use std::hash::BuildHasher;
use std::rc::Rc;
#[gtest]
fn test_vector_new() {
let v = cc_std::std::vector::<i64>::new();
expect_eq!(v.len(), 0);
expect_eq!(v.capacity(), 0);
expect_eq!(v.is_empty(), true);
}
#[gtest]
fn test_set_len() {
let mut v = cc_std::std::vector::<isize>::with_capacity(10);
unsafe {
let p = v.as_mut_ptr();
v.prepare_to_write_into_tail();
for i in 0..3 {
std::ptr::write(p.offset(i), i);
}
v.set_len(3);
}
expect_eq!(v, [0, 1, 2]);
expect_that!(v.capacity(), ge(10));
unsafe {
v.set_len(0);
}
expect_eq!(v, []);
expect_that!(v.capacity(), ge(10));
}
#[gtest]
fn test_vector_push() {
let mut v = cc_std::std::vector::new();
v.push(1);
expect_eq!(v.len(), 1);
expect_that!(v.capacity(), ge(1));
expect_eq!(v.get(0), Some(&1));
v.push(5);
expect_eq!(v.len(), 2);
expect_that!(v.capacity(), ge(2));
expect_eq!(v.get(0), Some(&1));
expect_eq!(v.get(1), Some(&5));
}
#[gtest]
fn test_vector_deref() {
let mut v = cc_std::std::vector::new();
v.push(1);
v.push(5);
expect_eq!((*v)[0], 1);
expect_eq!((*v)[1], 5);
}
#[gtest]
fn test_vector_get_range() {
let mut v = cc_std::std::vector::new();
v.push(1);
v.push(-2);
expect_eq!(v.get_mut(0), Some(&mut 1));
expect_eq!(v.get(0..2), Some(&[1, -2][..]));
}
#[gtest]
fn test_vector_deref_mut() {
let mut v = cc_std::std::vector::new();
v.push(1);
v.push(5);
(*v)[0] = 2;
expect_eq!((*v)[0], 2);
(*v)[1] = 6;
expect_eq!((*v)[1], 6);
}
#[gtest]
fn test_vector_debug() {
let v = cc_std::std::vector::from([1, 2, 3]);
expect_eq!(format!("{:?}", v), "[1, 2, 3]");
}
struct InstanceCounted {
counter: Rc<RefCell<i32>>,
}
impl Drop for InstanceCounted {
fn drop(&mut self) {
*self.counter.borrow_mut() -= 1;
}
}
impl InstanceCounted {
fn new(counter: Rc<RefCell<i32>>) -> InstanceCounted {
*counter.borrow_mut() += 1;
InstanceCounted { counter }
}
}
#[gtest]
fn test_vector_as_mut() {
let mut v = cc_std::std::vector::from(vec![2, 5]);
{
let mut_v: &mut [i32] = <cc_std::std::vector<i32> as AsMut<[i32]>>::as_mut(&mut v);
expect_eq!(mut_v, &[2, 5]);
mut_v[0] = 0;
}
expect_eq!(v, [0, 5]);
}
#[gtest]
fn test_vector_as_ref() {
let v = cc_std::std::vector::from(vec![2, 5]);
expect_eq!(<cc_std::std::vector<i32> as AsRef<[i32]>>::as_ref(&v), &[2, 5]);
}
#[gtest]
fn test_vector_borrow() {
let v = cc_std::std::vector::from(vec![2, 5]);
expect_eq!(<cc_std::std::vector<i32> as std::borrow::Borrow<[i32]>>::borrow(&v), &[2, 5]);
}
#[gtest]
fn test_vector_borrow_mut() {
let mut v = cc_std::std::vector::from(vec![1, 3]);
{
let borrowed: &mut [i32] =
<cc_std::std::vector<i32> as std::borrow::BorrowMut<[i32]>>::borrow_mut(&mut v);
expect_eq!(borrowed, &[1, 3]);
borrowed[0] = 2;
}
expect_eq!(v, [2, 3]);
}
#[gtest]
fn test_vector_drop() {
let mut v = cc_std::std::vector::new();
let counter = Rc::new(RefCell::new(0i32));
v.push(InstanceCounted::new(counter.clone()));
v.push(InstanceCounted::new(counter.clone()));
v.push(InstanceCounted::new(counter.clone()));
expect_eq!(*counter.borrow(), 3);
drop(v);
expect_eq!(*counter.borrow(), 0);
}
#[gtest]
fn test_vector_index() {
let v = cc_std::std::vector::from(vec![1, 2, 3, 4]);
expect_eq!(v[0], 1);
expect_eq!(v[1], 2);
expect_eq!(v[..], [1, 2, 3, 4]);
expect_eq!(v[1..], [2, 3, 4]);
expect_eq!(v[1..2], [2]);
}
#[gtest]
#[should_panic]
fn test_vector_index_out_of_bounds() {
let v = cc_std::std::vector::<i64>::new();
use_variable(v[0]);
}
#[gtest]
fn test_vector_mut_index() {
let mut v = cc_std::std::vector::from(vec![1, 2, 3, 4]);
v[0] = 5;
expect_eq!(v, vec![5, 2, 3, 4]);
v[1..3][0] = 6;
expect_eq!(v, vec![5, 6, 3, 4]);
}
#[gtest]
fn test_vector_to_vec() {
let v = cc_std::std::vector::from(vec![4, 5, 6]);
let v2 = v.to_vec();
expect_eq!(v2, vec![4, 5, 6]);
}
#[gtest]
fn test_clone() {
let v = cc_std::std::vector::from(vec![4, 5, 6]);
let v2 = v.clone();
expect_eq!(v2, vec![4, 5, 6]);
}
struct CloneCounter {
counter: Rc<RefCell<i32>>,
}
impl Clone for CloneCounter {
fn clone(&self) -> Self {
*self.counter.borrow_mut() += 1;
CloneCounter { counter: self.counter.clone() }
}
}
#[gtest]
fn test_clone_once_clone() {
let counter = Rc::new(RefCell::new(0i32));
let v = cc_std::std::vector::from(vec![CloneCounter { counter: counter.clone() }]);
expect_eq!(*counter.borrow(), 0);
let _ = v.clone();
expect_eq!(*counter.borrow(), 1); // the element was cloned once.
}
#[gtest]
#[should_panic]
fn test_vector_mut_index_out_of_bounds() {
let mut v = cc_std::std::vector::new();
v.push(1);
v[1] = 10;
}
#[gtest]
fn test_vector_from_iter() {
let v = cc_std::std::vector::from_iter(std::iter::repeat(1).take(3));
expect_eq!(v, [1, 1, 1]);
}
#[gtest]
fn test_emtpy_vector_into_iter() {
let v = cc_std::std::vector::<i64>::new();
let mut sum = 0;
for x in v {
sum += x;
}
expect_eq!(sum, 0);
}
#[gtest]
fn test_vector_into_iter() {
let mut v = cc_std::std::vector::new();
v.push(1);
v.push(2);
v.push(5);
let mut sum = 0;
for x in v {
sum += x;
}
expect_eq!(sum, 8);
}
#[gtest]
fn test_vector_into_iter_size() {
let mut v = cc_std::std::vector::new();
for i in 0..15 {
v.push(i);
}
let mut iter = v.into_iter();
expect_eq!(iter.size_hint(), (15, Option::Some(15)));
iter.next();
expect_eq!(iter.size_hint(), (14, Option::Some(14)));
expect_eq!(iter.count(), 14);
}
#[gtest]
fn test_vector_into_iter_as_slice() {
let mut v = cc_std::std::vector::new();
for i in 0..5 {
v.push(i);
}
let mut iter = v.into_iter();
expect_eq!(iter.as_slice(), &[0, 1, 2, 3, 4]);
iter.next();
expect_eq!(iter.as_slice(), &[1, 2, 3, 4]);
}
#[gtest]
fn test_vector_into_iter_as_mut_slice() {
let mut v = cc_std::std::vector::new();
for i in 0..5 {
v.push(i);
}
let mut iter = v.into_iter();
expect_eq!(iter.as_mut_slice(), &mut [0, 1, 2, 3, 4]);
iter.next();
expect_eq!(iter.as_mut_slice(), &mut [1, 2, 3, 4]);
}
#[gtest]
fn test_vector_ref_iter() {
let mut v = cc_std::std::vector::new();
v.push(1);
v.push(5);
v.push(10);
let mut sum = 0;
for x in &v {
sum += x;
}
// Sum the elements in the vector 2nd time to ensure that the vector is still
// valid.
for x in &v {
sum += x;
}
expect_eq!(sum, 32);
}
#[gtest]
fn test_vector_mut_ref_iter() {
let mut v = cc_std::std::vector::new();
v.push(1);
v.push(2);
// Increment the elements in the vector (mut access).
for x in &mut v {
*x += 1;
}
// Check that the elements were incremented.
let mut sum = 0;
for x in &v {
sum += x;
}
expect_eq!(sum, 5);
}
#[gtest]
fn test_iterator_as_ref() {
let mut v = cc_std::std::vector::new();
for i in 0..5 {
v.push(i);
}
let mut iter = v.into_iter();
expect_eq!(iter.as_ref(), &[0, 1, 2, 3, 4]);
iter.next();
expect_eq!(iter.as_ref(), &[1, 2, 3, 4]);
}
#[gtest]
fn test_iterator_debug() {
let mut v = cc_std::std::vector::new();
v.push(1);
v.push(2);
v.push(3);
expect_eq!(format!("{:?}", v.into_iter()), "IntoIter([1, 2, 3])");
}
#[gtest]
fn test_iterator_default() {
expect_eq!(
format!("{:?}", <cc_std::std::vector<i32> as IntoIterator>::IntoIter::default()),
"IntoIter([])"
);
}
#[gtest]
fn test_iterator_next_back() {
let mut v = cc_std::std::vector::new();
v.push(1);
v.push(2);
let mut iter = v.into_iter();
expect_eq!(iter.next_back(), Some(2));
expect_eq!(iter.next_back(), Some(1));
expect_eq!(iter.next_back(), None);
}
#[gtest]
fn test_iterator_drop() {
let mut v = cc_std::std::vector::new();
v.push(10);
let it = v.into_iter();
drop(it)
}
/// Use a variable in a way that can't be optimized out.
fn use_variable<T>(v: T) {
std::hint::black_box(v);
}
#[gtest]
fn test_vector_reserve() {
let mut v = cc_std::std::vector::<i32>::new();
v.reserve(10);
expect_that!(v.capacity(), ge(10));
let current_capacity = v.capacity();
v.reserve(5); // 5 < 10, so it should do nothing.
expect_eq!(v.capacity(), current_capacity);
}
#[gtest]
fn test_vector_reserve_exact() {
let mut v = cc_std::std::vector::<usize>::new();
v.reserve_exact(10);
expect_that!(v.capacity(), ge(10));
let current_capacity = v.capacity();
// Add elements to the current capacity.
for i in v.len()..current_capacity {
v.push(i);
}
v.reserve_exact(5); // it ensures that the capacity for additional 5 elements.
expect_that!(v.capacity(), ge(current_capacity + 5));
}
#[gtest]
fn test_vector_try_reserve() {
let mut v = cc_std::std::vector::<i32>::new();
v.try_reserve(100).unwrap();
expect_that!(v.capacity(), ge(100));
}
#[gtest]
fn test_vector_try_reserve_exact() {
let mut v = cc_std::std::vector::<usize>::new();
v.try_reserve_exact(10).unwrap();
expect_that!(v.capacity(), ge(10));
let current_capacity = v.capacity();
// Add elements to the current capacity.
for i in v.len()..current_capacity {
v.push(i);
}
v.try_reserve_exact(5).unwrap(); // it ensures that the capacity for additional 5 elements.
expect_that!(v.capacity(), ge(current_capacity + 5));
}
#[gtest]
fn test_shrink_to_fit() {
let mut v = cc_std::std::vector::<i32>::new();
for i in 0..100 {
v.push(i);
}
v.clear(); // doesn't shrink the capacity.
v.shrink_to_fit();
expect_eq!(v.capacity(), 0);
}
#[gtest]
fn test_shrink_to() {
let mut v = cc_std::std::vector::<i32>::new();
for i in 0..100 {
v.push(i);
}
v.clear(); // doesn't shrink the capacity.
v.shrink_to(10);
expect_that!(v.capacity(), le(99));
expect_that!(v.capacity(), ge(10));
}
#[gtest]
fn test_vector_with_capacity() {
let v = cc_std::std::vector::<i32>::with_capacity(100);
expect_that!(v.capacity(), ge(100));
}
#[gtest]
fn test_vector_insert() {
let mut v = cc_std::std::vector::<i32>::new();
v.insert(0, 1);
v.insert(0, 2);
expect_eq!(v, [2, 1]);
v.insert(1, 3);
expect_eq!(v, [2, 3, 1]);
}
#[gtest]
fn test_vector_append() {
let mut v = cc_std::std::vector::from(vec![1, 2]);
let mut v2 = cc_std::std::vector::from(vec![3, 4]);
v.append(&mut v2);
expect_eq!(v, [1, 2, 3, 4]);
expect_eq!(v2, []);
expect_eq!(v2.is_empty(), true);
}
#[gtest]
fn test_swap_remove() {
let mut v = cc_std::std::vector::from(vec![1, 2, 3, 4]);
expect_eq!(v.swap_remove(1), 2);
expect_eq!(v, [1, 4, 3]);
expect_eq!(v.swap_remove(0), 1);
expect_eq!(v, [3, 4]);
expect_eq!(v.swap_remove(0), 3);
expect_eq!(v, [4]);
expect_eq!(v.swap_remove(0), 4);
expect_eq!(v.is_empty(), true);
}
#[gtest]
#[should_panic]
fn test_swap_remove_out_of_bounds() {
let mut v = cc_std::std::vector::from(vec![1, 2, 3, 4]);
v.swap_remove(4);
}
#[gtest]
fn test_remove() {
let mut v = cc_std::std::vector::from(vec![1, 2, 3, 4]);
expect_eq!(v.remove(1), 2);
expect_eq!(v, [1, 3, 4]);
expect_eq!(v.remove(0), 1);
expect_eq!(v, [3, 4]);
expect_eq!(v.remove(1), 4);
expect_eq!(v, [3]);
expect_eq!(v.remove(0), 3);
expect_eq!(v.is_empty(), true);
}
#[gtest]
#[should_panic]
fn test_remove_out_of_bounds() {
let mut v = cc_std::std::vector::from(vec![1, 2, 3]);
v.remove(3);
}
#[gtest]
fn test_pop() {
let mut v = cc_std::std::vector::from(vec![1, 2, 3, 4]);
expect_eq!(v.pop(), Some(4));
expect_eq!(v, [1, 2, 3]);
expect_eq!(v.pop(), Some(3));
expect_eq!(v, [1, 2]);
expect_eq!(v.pop(), Some(2));
expect_eq!(v, [1]);
expect_eq!(v.pop(), Some(1));
expect_eq!(v.is_empty(), true);
expect_eq!(v.pop(), None);
}
#[gtest]
fn test_vector_clear() {
let mut v = cc_std::std::vector::from(vec![1, 2, 3, 4]);
v.clear();
expect_eq!(v.is_empty(), true);
expect_eq!(v.capacity(), 4);
}
#[gtest]
fn test_truncate() {
let mut v = cc_std::std::vector::from(vec![1, 2, 3, 4, 5]);
let capacity = v.capacity();
v.truncate(2);
expect_eq!(v, [1, 2]);
expect_eq!(v.capacity(), capacity);
v.truncate(3); // no effect
expect_eq!(v, [1, 2]);
v.truncate(0);
expect_eq!(v, []);
expect_eq!(v.capacity(), capacity);
}
#[gtest]
fn test_vector_resize() {
let mut v = cc_std::std::vector::from(vec![1, 2]);
v.resize(6, 5);
expect_eq!(v, [1, 2, 5, 5, 5, 5]);
v.resize(0, 5);
expect_eq!(v, []);
v.resize(1, 5);
expect_eq!(v, [5]);
}
#[gtest]
fn test_vector_resize_with() {
let mut v = cc_std::std::vector::from(vec![1, 2]);
v.resize_with(6, Default::default);
expect_eq!(v, [1, 2, 0, 0, 0, 0]);
v.resize_with(0, Default::default);
expect_eq!(v, []);
}
#[gtest]
fn test_vector_dedup() {
let mut v = cc_std::std::vector::from(vec![1, 2, 2, 3, 3, 3, 4, 4, 4, 4]);
v.dedup();
expect_eq!(v, [1, 2, 3, 4]);
}
#[gtest]
fn test_vector_dedup_by() {
let mut v = cc_std::std::vector::from(vec![1, 2, 2, 3, 3, 3, 4, 4, 4, 4]);
v.dedup_by(|a, b| a == b);
expect_eq!(v, [1, 2, 3, 4]);
}
#[gtest]
fn test_vector_dedup_by_key() {
let mut v = cc_std::std::vector::from(vec![1, 2, 2, 6, 3, 3, 5, 4, 4, 4, 4]);
v.dedup_by_key(|a| *a % 2);
expect_eq!(v, [1, 2, 3, 4]);
}
#[gtest]
fn test_retain() {
let mut v = cc_std::std::vector::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
v.retain(|&x| x % 2 == 0);
expect_eq!(v, [2, 4, 6, 8, 10]);
}
#[gtest]
fn test_retain_mut() {
let mut v = cc_std::std::vector::from(vec![1, 2, 3, 4]);
v.retain_mut(|x| {
if *x <= 3 {
*x += 1;
true
} else {
false
}
});
expect_eq!(v, [2, 3, 4]);
}
#[gtest]
fn test_split_off() {
let mut vec = cc_std::std::vector::from(vec![1, 2, 3]);
let vec2 = vec.split_off(1);
expect_eq!(vec, [1]);
expect_eq!(vec2, [2, 3]);
}
#[gtest]
fn test_vector_into_vec() {
let mut v = cc_std::std::vector::<i32>::new();
v.push(1);
v.push(2);
v.push(3);
let v2 = v.into_vec();
expect_eq!(v2, vec![1, 2, 3]);
}
#[gtest]
fn test_extend_from_slice() {
let mut v = cc_std::std::vector::from(vec![1, 2, 3]);
v.extend_from_slice(&[4, 5, 6]);
expect_eq!(v, [1, 2, 3, 4, 5, 6]);
}
#[gtest]
fn test_vector_extend_from_within() {
let mut v = cc_std::std::vector::from(vec![0, 1, 2, 3, 4]);
v.extend_from_within(2..);
expect_eq!(v, [0, 1, 2, 3, 4, 2, 3, 4]);
v.extend_from_within(..2);
expect_eq!(v, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1]);
v.extend_from_within(4..8);
expect_eq!(v, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1, 4, 2, 3, 4]);
}
#[gtest]
fn test_vector_into_dropped_counter() {
let mut v = cc_std::std::vector::new();
let counter = Rc::new(RefCell::new(0i32));
v.push(InstanceCounted::new(counter.clone()));
v.push(InstanceCounted::new(counter.clone()));
v.push(InstanceCounted::new(counter.clone()));
expect_eq!(*counter.borrow(), 3);
let v2 = v.into_vec();
drop(v2);
expect_eq!(*counter.borrow(), 0);
}
#[gtest]
fn test_vector_from_vec() {
let v = cc_std::std::vector::from(vec![0, 1, 2, 3, 4]);
expect_eq!(v.len(), 5);
for i in 0..5 {
expect_eq!(v[i], i);
}
}
#[gtest]
fn test_vector_extend() {
let mut v = cc_std::std::vector::new();
v.extend(vec![1, 2, 3]);
expect_eq!(v, [1, 2, 3]);
v.extend(vec![4, 5, 6]);
expect_eq!(v, [1, 2, 3, 4, 5, 6]);
}
#[gtest]
fn test_hash() {
let b = std::hash::RandomState::new();
let v: cc_std::std::vector<i64> = cc_std::std::vector::from(vec![10, 12, -4]);
let s: &[i64] = &[10, 12, -4];
expect_eq!(b.hash_one(v), b.hash_one(s));
}
#[gtest]
fn test_partial_ord() {
let u = cc_std::std::vector::from(vec![0.5, 1.0]);
let v = cc_std::std::vector::from(vec![0.5, 2.5, 3.0]);
expect_eq!(u.partial_cmp(&v).unwrap(), Ordering::Less);
expect_eq!(u.partial_cmp(&u).unwrap(), Ordering::Equal);
expect_eq!(v.partial_cmp(&u).unwrap(), Ordering::Greater);
}
#[gtest]
fn test_partial_ord_non_comparable() {
let u = cc_std::std::vector::from(vec![1.0, f64::NAN]);
let v = cc_std::std::vector::from(vec![1.0, 2.0]);
// NAN is not comparable to any other number, so the comparison result is
// undefined.
expect_eq!(u.partial_cmp(&u), None);
expect_eq!(u.partial_cmp(&v), None);
}
#[gtest]
fn test_ord() {
let u = cc_std::std::vector::from(vec![0, 1]);
let v = cc_std::std::vector::from(vec![0, 2]);
expect_eq!(u.cmp(&v), Ordering::Less);
expect_eq!(u.cmp(&u), Ordering::Equal);
expect_eq!(v.cmp(&u), Ordering::Greater);
}
#[gtest]
fn test_comparison_operators() {
let u = cc_std::std::vector::from(vec![0, 1]);
let v = cc_std::std::vector::from(vec![0, 2, 3]);
expect_eq!(u < v, true);
expect_eq!(u <= v, true);
expect_eq!(u > v, false);
expect_eq!(u >= v, false);
}
#[gtest]
fn test_eq() {
assert_impl_all!(cc_std::std::vector<i64>: Eq);
}
#[gtest]
fn test_vector_from_vec_with_capacity() {
let vector = cc_std::std::vector::from(vec![0, 1, 2, 3, 4]);
let vec = Vec::from(vector);
expect_eq!(vec, [0, 1, 2, 3, 4]);
}
#[gtest]
fn test_as_ptr() {
let v = cc_std::std::vector::from(vec!['a', 'b']);
let ptr: *const char = v.as_ptr();
unsafe {
expect_eq!(*ptr, 'a');
}
}
#[gtest]
fn test_as_mut_ptr() {
let mut v = cc_std::std::vector::from(vec!['a', 'b']);
let ptr: *mut char = v.as_mut_ptr();
unsafe {
expect_eq!(*ptr, 'a');
*ptr = 'c';
}
expect_eq!(v[0], 'c');
}
#[gtest]
fn test_as_slice() {
let v = cc_std::std::vector::from(vec![5, 6, 7]);
let slice: &[i32] = v.as_slice();
expect_eq!(slice, &[5, 6, 7]);
}
#[gtest]
fn test_as_mut_slice() {
let mut v = cc_std::std::vector::from(vec![5, 6, 7]);
let slice: &mut [i32] = v.as_mut_slice();
expect_eq!(slice, &[5, 6, 7]);
slice[1] = 1;
expect_eq!(v[1], 1);
}
#[gtest]
fn test_is_send() {
assert_impl_all!(cc_std::std::vector<i64>: Send);
}
#[gtest]
fn test_is_sync() {
assert_impl_all!(cc_std::std::vector<i64>: Sync);
}
mod layout_tests {
use crate::to_void_ptr;
use googletest::prelude::*;
/// Tests that `vector` has the same memory layout as `std::vector` in C++.
#[gtest]
fn test_begin_end() {
let mut v = cc_std::std::vector::<i32>::new();
v.push(1);
v.push(2);
v.push(3);
unsafe {
expect_eq!(cc_helper_functions::crubit_test::vector_int32_sum(to_void_ptr(&v)), 6);
}
}
/// Tests that `vector` has the same memory layout as `std::vector` in C++.
#[gtest]
fn test_capacity() {
let mut v = cc_std::std::vector::<i32>::new();
for i in 0..100 {
v.push(i);
}
unsafe {
expect_eq!(
cc_helper_functions::crubit_test::vector_int32_capacity(to_void_ptr(&v)),
v.capacity(),
);
}
}
}
mod allocation_tests {
use crate::to_void_ptr;
use googletest::prelude::*;
use std::mem::forget;
use std::mem::MaybeUninit;
// The following tests check that the memory allocated in one language is
// correctly reallocated and dealocated in another language.
#[gtest]
fn test_allocate_in_rust_deallocate_in_cc() {
let mut v = cc_std::std::vector::<i32>::new();
// Allocate heap memory in Rust (by adding elements)
for i in 0..10000 {
v.push(i);
}
// Deallocate the heap memory in C++.
unsafe {
cc_helper_functions::crubit_test::vector_int32_call_destructor(to_void_ptr(&v));
}
forget(v);
}
#[gtest]
fn test_allocate_in_cc_delocate_in_rust() {
unsafe {
// Allocate heap memory in C++ (by adding many elements)
let maybe_uninit_v = MaybeUninit::<cc_std::std::vector<i32>>::uninit();
cc_helper_functions::crubit_test::vector_int32_construct(to_void_ptr(&maybe_uninit_v));
let v = maybe_uninit_v.assume_init();
expect_eq!(v.is_empty(), true);
for i in 0..10000 {
cc_helper_functions::crubit_test::vector_int32_push_back(to_void_ptr(&v), i);
}
expect_eq!(v.len(), 10000);
// Deallocate the heap memory in Rust.
drop(v)
}
}
#[gtest]
fn test_allocate_in_cc_interchangeble_reallocate_in_different_languages() {
unsafe {
let maybe_uninit_v = MaybeUninit::<cc_std::std::vector<i32>>::uninit();
cc_helper_functions::crubit_test::vector_int32_construct(to_void_ptr(&maybe_uninit_v));
let mut v = maybe_uninit_v.assume_init();
expect_eq!(v.is_empty(), true);
// Allocate heap memory in C++.
for i in 0..10 {
cc_helper_functions::crubit_test::vector_int32_push_back(to_void_ptr(&v), i);
}
// Reallocate heap memory in Rust by adding much more elements.
for i in 10..1000 {
v.push(i);
}
// Reallocate heap memory in C++ by adding much much more elements.
for i in 1000..100000 {
cc_helper_functions::crubit_test::vector_int32_push_back(to_void_ptr(&v), i);
}
expect_eq!(v.len(), 100000);
// Deallocate the heap memory in Rust.
drop(v)
}
}
#[gtest]
fn test_allocate_in_rust_interchangeble_reallocate_in_different_languages() {
let mut v = cc_std::std::vector::<i32>::new();
// Allocate heap memory in Rust (by adding elements)
for i in 0..10 {
v.push(i);
}
unsafe {
// Reallocate heap memory in C++ by adding much more elements.
for i in 10..1000 {
cc_helper_functions::crubit_test::vector_int32_push_back(to_void_ptr(&v), i);
}
}
// Reallocate heap memory in Rust (by adding much much more elements)
for i in 1000..10000 {
v.push(i);
}
}
}
mod alignment_tests {
use googletest::prelude::*;
// Tests that vector can hold a struct with correct alignment.
#[repr(align(1024))]
struct OveralignedStuct {
x: i32,
}
#[gtest]
fn test_vector_of_overaligned_struct() {
let mut v = cc_std::std::vector::<OveralignedStuct>::new();
v.push(OveralignedStuct { x: 1 });
v.push(OveralignedStuct { x: 2 });
expect_eq!(v[0].x, 1);
expect_eq!(v[1].x, 2);
expect_eq!(&raw const v[0] as usize % 1024, 0);
}
}
mod partial_equal_tests {
use googletest::prelude::*;
#[gtest]
fn test_vector_eq() {
let v = cc_std::std::vector::from(vec![1, 2, 3]);
let u = cc_std::std::vector::from(vec![1, 2]);
expect_eq!(v == v, true);
expect_eq!(v == u, false);
expect_eq!(v != u, true);
expect_eq!(v != v, false);
}
#[gtest]
fn test_vec_partial_eq() {
let v = cc_std::std::vector::from(vec![1, 2, 3]);
expect_eq!(v == vec![1, 2, 3], true);
expect_eq!(vec![1, 2, 3] == v, true);
expect_eq!(v == vec![1, 2], false);
expect_eq!(v == vec![1i16, 2i16, 3i16], true); // i64 and i16 are
// comparable.
}
#[gtest]
fn test_slice_partial_eq() {
let v = cc_std::std::vector::from(vec![1, 2, 3]);
expect_eq!(v == [1, 2, 3].as_slice(), true);
expect_eq!([1, 2, 3].as_slice() == v, true);
expect_eq!(v == [1, 2, 3].as_mut_slice(), true);
expect_eq!([1, 2, 3].as_mut_slice() == v, true);
}
#[gtest]
fn test_array_partial_eq() {
let v = cc_std::std::vector::from(vec![1, 2, 3]);
expect_eq!(v == [1, 2, 3], true);
expect_eq!(v == &[1, 2, 3], true);
}
}
#[gtest]
fn test_vector_from_slice() {
let v = cc_std::std::vector::from(vec![2, 3, 4].as_slice());
expect_eq!(v, [2, 3, 4]);
}
#[gtest]
fn test_vector_from_mut_slice() {
let v = cc_std::std::vector::from(vec![1.0, 2.0, 3.0].as_mut_slice());
expect_eq!(v, [1.0, 2.0, 3.0]);
}
#[gtest]
fn test_vector_from_array() {
let v = cc_std::std::vector::from(['a', 'b']);
expect_eq!(v, ['a', 'b']);
}
#[gtest]
fn test_vector_from_array_ref() {
let v = cc_std::std::vector::from(&["ab", "cd"]);
expect_eq!(v, ["ab", "cd"])
}
#[gtest]
fn test_vector_from_array_mut_ref() {
let v = cc_std::std::vector::from(&mut [0, 1]);
expect_eq!(v, [0, 1])
}
#[gtest]
fn test_vector_covariant() {
// If this compiles, the test passes.
fn _compile_test<'a>(
mut _v1: cc_std::std::vector<&'a i32>,
v2: cc_std::std::vector<&'static i32>,
) {
_v1 = v2;
}
}
fn to_void_ptr<T>(t: &T) -> *mut c_void {
t as *const _ as *mut c_void
}