| // 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(()) |
| } |