blob: 3bdacdd9488a5e5fdcc947155e99f5d7d7206143 [file]
// 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
#[cfg(test)]
mod tests {
use field_destruction_order::*;
use googletest::prelude::*;
use std::mem::ManuallyDrop;
#[gtest]
fn test_field_destruction_order() {
let field1_value = 1;
let field2_value = 2;
let field3_value = 3;
let expected_destruction_order_in_cpp = 321;
let expected_destruction_order_in_rust = 321;
// The 3 statements below just confirm what C++ documentation says in
// https://en.cppreference.com/w/cpp/language/destructor: For both
// user-defined or implicitly-defined destructors, after the body of the
// destructor is executed, the compiler calls the destructors for all
// non-static non-variant members of the class, in **reverse order of
// declaration**.
DestructionOrderRecorder::ClearDestructionRecord();
FieldDestructionOrderTester::DestructFromCpp(field1_value, field2_value, field3_value);
assert_eq!(
expected_destruction_order_in_cpp,
DestructionOrderRecorder::GetDestructionRecord()
);
// The main test is below - it tries to confirm that the destruction
// order of the C++ object is preserved when the destruction is
// triggered from Rust, via `impl Drop` emitted by the bindings
// generator.
DestructionOrderRecorder::ClearDestructionRecord();
{
// The code below constructs the same FieldDestructionOrderTester object
// as done internally in DestructFromCpp above.
let tester = FieldDestructionOrderTester {
field1: ManuallyDrop::new(DestructionOrderRecorder { int_field: field1_value }),
field2: ManuallyDrop::new(DestructionOrderRecorder { int_field: field2_value }),
field3: ManuallyDrop::new(DestructionOrderRecorder { int_field: field3_value }),
};
// Dropping the `tester` should invoke destructors of field1/2/3 in the
// same order as C++ (e.g. by calling into the C++ destructor of
// FieldDestructionOrderTester). Note that Rust uses a different order
// as explains in https://doc.rust-lang.org/reference/destructors.html:
// The fields of a struct are dropped in **declaration order**.
drop(tester);
}
assert_eq!(
expected_destruction_order_in_rust,
DestructionOrderRecorder::GetDestructionRecord()
);
}
}