blob: c06ea442137d4ccc80e11eb93fc706da448dc7e9 [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
use arc_anyhow::Result;
use googletest::prelude::gtest;
use multiplatform_ir_testing::ir_from_cc;
use quote::quote;
use test_generators::generate_bindings_tokens_for_test;
use token_stream_matchers::{assert_rs_matches, assert_rs_not_matches};
#[gtest]
fn test_generate_enum_basic() -> Result<()> {
let ir = ir_from_cc("enum Color { kRed = 5, kBlue };")?;
let rs_api = generate_bindings_tokens_for_test(ir)?.rs_api;
assert_rs_matches!(
rs_api,
quote! {
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)]
#[doc="CRUBIT_ANNOTATE: cpp_type=Color"]
pub struct Color(::core::ffi::c_uint);
impl Color {
pub const kRed: Color = Color(5);
pub const kBlue: Color = Color(6);
}
impl From<::core::ffi::c_uint> for Color {
fn from(value: ::core::ffi::c_uint) -> Color {
Color(value)
}
}
impl From<Color> for ::core::ffi::c_uint {
fn from(value: Color) -> ::core::ffi::c_uint {
value.0
}
}
}
);
Ok(())
}
#[gtest]
fn test_generate_opaque_enum() -> Result<()> {
let ir = ir_from_cc("enum Color : int;")?;
let rs_api = generate_bindings_tokens_for_test(ir)?.rs_api;
assert_rs_not_matches!(rs_api, quote! {Color});
Ok(())
}
#[gtest]
fn test_generate_scoped_enum_basic() -> Result<()> {
let ir = ir_from_cc("enum class Color { kRed = -5, kBlue };")?;
let rs_api = generate_bindings_tokens_for_test(ir)?.rs_api;
assert_rs_matches!(
rs_api,
quote! {
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)]
#[doc="CRUBIT_ANNOTATE: cpp_type=Color"]
pub struct Color(::core::ffi::c_int);
impl Color {
pub const kRed: Color = Color(-5);
pub const kBlue: Color = Color(-4);
}
impl From<::core::ffi::c_int> for Color {
fn from(value: ::core::ffi::c_int) -> Color {
Color(value)
}
}
impl From<Color> for ::core::ffi::c_int {
fn from(value: Color) -> ::core::ffi::c_int {
value.0
}
}
}
);
Ok(())
}
#[gtest]
fn test_generate_enum_with_64_bit_signed_vals() -> Result<()> {
let ir = ir_from_cc(
r#"enum Color : long {
kViolet = -9223372036854775807 - 1LL,
kRed = -5,
kBlue,
kGreen = 3,
kMagenta = 9223372036854775807
};"#,
)?;
let rs_api = generate_bindings_tokens_for_test(ir)?.rs_api;
assert_rs_matches!(
rs_api,
quote! {
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)]
#[doc="CRUBIT_ANNOTATE: cpp_type=Color"]
pub struct Color(::core::ffi::c_long);
impl Color {
pub const kViolet: Color = Color(-9223372036854775808);
pub const kRed: Color = Color(-5);
pub const kBlue: Color = Color(-4);
pub const kGreen: Color = Color(3);
pub const kMagenta: Color = Color(9223372036854775807);
}
impl From<::core::ffi::c_long> for Color {
fn from(value: ::core::ffi::c_long) -> Color {
Color(value)
}
}
impl From<Color> for ::core::ffi::c_long {
fn from(value: Color) -> ::core::ffi::c_long {
value.0
}
}
}
);
Ok(())
}
#[gtest]
fn test_generate_enum_with_64_bit_unsigned_vals() -> Result<()> {
let ir = ir_from_cc(
r#" enum Color: unsigned long {
kRed,
kBlue,
kLimeGreen = 18446744073709551615
}; "#,
)?;
let rs_api = generate_bindings_tokens_for_test(ir)?.rs_api;
assert_rs_matches!(
rs_api,
quote! {
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)]
#[doc="CRUBIT_ANNOTATE: cpp_type=Color"]
pub struct Color(::core::ffi::c_ulong);
impl Color {
pub const kRed: Color = Color(0);
pub const kBlue: Color = Color(1);
pub const kLimeGreen: Color = Color(18446744073709551615);
}
impl From<::core::ffi::c_ulong> for Color {
fn from(value: ::core::ffi::c_ulong) -> Color {
Color(value)
}
}
impl From<Color> for ::core::ffi::c_ulong {
fn from(value: Color) -> ::core::ffi::c_ulong {
value.0
}
}
}
);
Ok(())
}
#[gtest]
fn test_generate_enum_with_32_bit_signed_vals() -> Result<()> {
let ir = ir_from_cc(
"enum Color { kViolet = -2147483647 - 1, kRed = -5, kBlue, kGreen = 3, kMagenta = 2147483647 };",
)?;
let rs_api = generate_bindings_tokens_for_test(ir)?.rs_api;
assert_rs_matches!(
rs_api,
quote! {
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)]
#[doc="CRUBIT_ANNOTATE: cpp_type=Color"]
pub struct Color(::core::ffi::c_int);
impl Color {
pub const kViolet: Color = Color(-2147483648);
pub const kRed: Color = Color(-5);
pub const kBlue: Color = Color(-4);
pub const kGreen: Color = Color(3);
pub const kMagenta: Color = Color(2147483647);
}
impl From<::core::ffi::c_int> for Color {
fn from(value: ::core::ffi::c_int) -> Color {
Color(value)
}
}
impl From<Color> for ::core::ffi::c_int {
fn from(value: Color) -> ::core::ffi::c_int {
value.0
}
}
}
);
Ok(())
}
#[gtest]
fn test_generate_enum_with_32_bit_unsigned_vals() -> Result<()> {
let ir = ir_from_cc("enum Color: unsigned int { kRed, kBlue, kLimeGreen = 4294967295 };")?;
let rs_api = generate_bindings_tokens_for_test(ir)?.rs_api;
assert_rs_matches!(
rs_api,
quote! {
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)]
#[doc="CRUBIT_ANNOTATE: cpp_type=Color"]
pub struct Color(::core::ffi::c_uint);
impl Color {
pub const kRed: Color = Color(0);
pub const kBlue: Color = Color(1);
pub const kLimeGreen: Color = Color(4294967295);
}
impl From<::core::ffi::c_uint> for Color {
fn from(value: ::core::ffi::c_uint) -> Color {
Color(value)
}
}
impl From<Color> for ::core::ffi::c_uint {
fn from(value: Color) -> ::core::ffi::c_uint {
value.0
}
}
}
);
Ok(())
}
#[gtest]
fn test_generate_enum_bool() -> Result<()> {
let ir = ir_from_cc("enum Bool : bool { kFalse, kTrue };")?;
let rs_api = generate_bindings_tokens_for_test(ir)?.rs_api;
assert_rs_matches!(
rs_api,
quote! {
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)]
#[doc="CRUBIT_ANNOTATE: cpp_type=Bool"]
pub struct Bool(bool);
impl Bool {
pub const kFalse: Bool = Bool(false);
pub const kTrue: Bool = Bool(true);
}
impl From<bool> for Bool {
fn from(value: bool) -> Bool {
Bool(value)
}
}
impl From<Bool> for bool {
fn from(value: Bool) -> bool {
value.0
}
}
}
);
Ok(())
}
#[gtest]
fn test_generate_enum_bool_alias() -> Result<()> {
let ir = ir_from_cc("using MyBool = bool; enum Bool : MyBool { kFalse, kTrue };")?;
let rs_api = generate_bindings_tokens_for_test(ir)?.rs_api;
assert_rs_matches!(
rs_api,
quote! {
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)]
#[doc="CRUBIT_ANNOTATE: cpp_type=Bool"]
pub struct Bool(crate::MyBool);
impl Bool {
pub const kFalse: Bool = Bool(false);
pub const kTrue: Bool = Bool(true);
}
impl From<crate::MyBool> for Bool {
fn from(value: crate::MyBool) -> Bool {
Bool(value)
}
}
impl From<Bool> for crate::MyBool {
fn from(value: Bool) -> crate::MyBool {
value.0
}
}
}
);
Ok(())
}