summaryrefslogtreecommitdiffstats
path: root/xpcom/rust/gtest/nsstring
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/rust/gtest/nsstring')
-rw-r--r--xpcom/rust/gtest/nsstring/Cargo.toml12
-rw-r--r--xpcom/rust/gtest/nsstring/TestnsString.cpp177
-rw-r--r--xpcom/rust/gtest/nsstring/test.rs131
3 files changed, 320 insertions, 0 deletions
diff --git a/xpcom/rust/gtest/nsstring/Cargo.toml b/xpcom/rust/gtest/nsstring/Cargo.toml
new file mode 100644
index 0000000000..fd997926a7
--- /dev/null
+++ b/xpcom/rust/gtest/nsstring/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "nsstring-gtest"
+version = "0.1.0"
+authors = ["nobody@mozilla.com"]
+license = "MPL-2.0"
+description = "Tests for rust bindings to xpcom string types"
+
+[dependencies]
+nsstring = { path = "../../nsstring" }
+
+[lib]
+path = "test.rs"
diff --git a/xpcom/rust/gtest/nsstring/TestnsString.cpp b/xpcom/rust/gtest/nsstring/TestnsString.cpp
new file mode 100644
index 0000000000..4e14c7bca5
--- /dev/null
+++ b/xpcom/rust/gtest/nsstring/TestnsString.cpp
@@ -0,0 +1,177 @@
+#include "gtest/gtest.h"
+#include <stdint.h>
+#include <utility>
+#include "nsString.h"
+
+extern "C" {
+// This function is called by the rust code in test.rs if a non-fatal test
+// failure occurs.
+void GTest_ExpectFailure(const char* aMessage) { EXPECT_STREQ(aMessage, ""); }
+}
+
+#define SIZE_ALIGN_CHECK(Clazz) \
+ extern "C" void Rust_Test_ReprSizeAlign_##Clazz(size_t* size, \
+ size_t* align); \
+ TEST(RustNsString, ReprSizeAlign_##Clazz) \
+ { \
+ size_t size, align; \
+ Rust_Test_ReprSizeAlign_##Clazz(&size, &align); \
+ EXPECT_EQ(size, sizeof(Clazz)); \
+ EXPECT_EQ(align, alignof(Clazz)); \
+ }
+
+SIZE_ALIGN_CHECK(nsString)
+SIZE_ALIGN_CHECK(nsCString)
+
+#define MEMBER_CHECK(Clazz, Member) \
+ extern "C" void Rust_Test_Member_##Clazz##_##Member( \
+ size_t* size, size_t* align, size_t* offset); \
+ TEST(RustNsString, ReprMember_##Clazz##_##Member) \
+ { \
+ class Hack : public Clazz { \
+ public: \
+ static void RunTest() { \
+ size_t size, align, offset; \
+ Rust_Test_Member_##Clazz##_##Member(&size, &align, &offset); \
+ EXPECT_EQ(size, sizeof(std::declval<Hack>().Member)); \
+ EXPECT_EQ(align, alignof(decltype(std::declval<Hack>().Member))); \
+ EXPECT_EQ(offset, offsetof(Hack, Member)); \
+ } \
+ }; \
+ static_assert(sizeof(Clazz) == sizeof(Hack), "Hack matches class"); \
+ Hack::RunTest(); \
+ }
+
+MEMBER_CHECK(nsString, mData)
+MEMBER_CHECK(nsString, mLength)
+MEMBER_CHECK(nsString, mDataFlags)
+MEMBER_CHECK(nsString, mClassFlags)
+MEMBER_CHECK(nsCString, mData)
+MEMBER_CHECK(nsCString, mLength)
+MEMBER_CHECK(nsCString, mDataFlags)
+MEMBER_CHECK(nsCString, mClassFlags)
+
+extern "C" void Rust_Test_NsStringFlags(
+ uint16_t* f_terminated, uint16_t* f_voided, uint16_t* f_refcounted,
+ uint16_t* f_owned, uint16_t* f_inline, uint16_t* f_literal,
+ uint16_t* f_class_inline, uint16_t* f_class_null_terminated);
+TEST(RustNsString, NsStringFlags)
+{
+ uint16_t f_terminated, f_voided, f_refcounted, f_owned, f_inline, f_literal,
+ f_class_inline, f_class_null_terminated;
+ Rust_Test_NsStringFlags(&f_terminated, &f_voided, &f_refcounted, &f_owned,
+ &f_inline, &f_literal, &f_class_inline,
+ &f_class_null_terminated);
+ EXPECT_EQ(f_terminated, uint16_t(nsAString::DataFlags::TERMINATED));
+ EXPECT_EQ(f_terminated, uint16_t(nsACString::DataFlags::TERMINATED));
+ EXPECT_EQ(f_voided, uint16_t(nsAString::DataFlags::VOIDED));
+ EXPECT_EQ(f_voided, uint16_t(nsACString::DataFlags::VOIDED));
+ EXPECT_EQ(f_refcounted, uint16_t(nsAString::DataFlags::REFCOUNTED));
+ EXPECT_EQ(f_refcounted, uint16_t(nsACString::DataFlags::REFCOUNTED));
+ EXPECT_EQ(f_owned, uint16_t(nsAString::DataFlags::OWNED));
+ EXPECT_EQ(f_owned, uint16_t(nsACString::DataFlags::OWNED));
+ EXPECT_EQ(f_inline, uint16_t(nsAString::DataFlags::INLINE));
+ EXPECT_EQ(f_inline, uint16_t(nsACString::DataFlags::INLINE));
+ EXPECT_EQ(f_literal, uint16_t(nsAString::DataFlags::LITERAL));
+ EXPECT_EQ(f_literal, uint16_t(nsACString::DataFlags::LITERAL));
+ EXPECT_EQ(f_class_inline, uint16_t(nsAString::ClassFlags::INLINE));
+ EXPECT_EQ(f_class_inline, uint16_t(nsACString::ClassFlags::INLINE));
+ EXPECT_EQ(f_class_null_terminated,
+ uint16_t(nsAString::ClassFlags::NULL_TERMINATED));
+ EXPECT_EQ(f_class_null_terminated,
+ uint16_t(nsACString::ClassFlags::NULL_TERMINATED));
+}
+
+extern "C" void Rust_StringFromCpp(const nsACString* aCStr,
+ const nsAString* aStr);
+TEST(RustNsString, StringFromCpp)
+{
+ nsAutoCString foo;
+ foo.AssignASCII("Hello, World!");
+
+ nsAutoString bar;
+ bar.AssignASCII("Hello, World!");
+
+ Rust_StringFromCpp(&foo, &bar);
+}
+
+extern "C" void Rust_AssignFromRust(nsACString* aCStr, nsAString* aStr);
+TEST(RustNsString, AssignFromRust)
+{
+ nsAutoCString cs;
+ nsAutoString s;
+ Rust_AssignFromRust(&cs, &s);
+ EXPECT_TRUE(cs.EqualsASCII("Hello, World!"));
+ EXPECT_TRUE(s.EqualsASCII("Hello, World!"));
+}
+
+extern "C" {
+void Cpp_AssignFromCpp(nsACString* aCStr, nsAString* aStr) {
+ aCStr->AssignASCII("Hello, World!");
+ aStr->AssignASCII("Hello, World!");
+}
+}
+extern "C" void Rust_AssignFromCpp();
+TEST(RustNsString, AssignFromCpp)
+{ Rust_AssignFromCpp(); }
+
+extern "C" void Rust_StringWrite();
+TEST(RustNsString, StringWrite)
+{ Rust_StringWrite(); }
+
+extern "C" void Rust_FromEmptyRustString();
+TEST(RustNsString, FromEmptyRustString)
+{ Rust_FromEmptyRustString(); }
+
+extern "C" void Rust_WriteToBufferFromRust(nsACString* aCStr, nsAString* aStr,
+ nsACString* aFallibleCStr,
+ nsAString* aFallibleStr);
+TEST(RustNsString, WriteToBufferFromRust)
+{
+ nsAutoCString cStr;
+ nsAutoString str;
+ nsAutoCString fallibleCStr;
+ nsAutoString fallibleStr;
+
+ cStr.AssignLiteral("abc");
+ str.AssignLiteral("abc");
+ fallibleCStr.AssignLiteral("abc");
+ fallibleStr.AssignLiteral("abc");
+
+ Rust_WriteToBufferFromRust(&cStr, &str, &fallibleCStr, &fallibleStr);
+
+ EXPECT_TRUE(cStr.EqualsASCII("ABC"));
+ EXPECT_TRUE(str.EqualsASCII("ABC"));
+ EXPECT_TRUE(fallibleCStr.EqualsASCII("ABC"));
+ EXPECT_TRUE(fallibleStr.EqualsASCII("ABC"));
+}
+
+extern "C" void Rust_InlineCapacityFromRust(const nsACString* aCStr,
+ const nsAString* aStr,
+ size_t* aCStrCapacity,
+ size_t* aStrCapacity);
+TEST(RustNsString, InlineCapacityFromRust)
+{
+ size_t cStrCapacity;
+ size_t strCapacity;
+ nsAutoCStringN<93> cs;
+ nsAutoStringN<93> s;
+ Rust_InlineCapacityFromRust(&cs, &s, &cStrCapacity, &strCapacity);
+ EXPECT_EQ(cStrCapacity, 92U);
+ EXPECT_EQ(strCapacity, 92U);
+}
+
+extern "C" void Rust_VoidStringFromRust(nsACString* aCStr, nsAString* aStr);
+TEST(RustNsString, VoidStringFromRust)
+{
+ nsAutoCString cs;
+ nsAutoString s;
+
+ EXPECT_FALSE(cs.IsVoid());
+ EXPECT_FALSE(s.IsVoid());
+
+ Rust_VoidStringFromRust(&cs, &s);
+
+ EXPECT_TRUE(cs.IsVoid());
+ EXPECT_TRUE(s.IsVoid());
+}
diff --git a/xpcom/rust/gtest/nsstring/test.rs b/xpcom/rust/gtest/nsstring/test.rs
new file mode 100644
index 0000000000..a5d142f2b2
--- /dev/null
+++ b/xpcom/rust/gtest/nsstring/test.rs
@@ -0,0 +1,131 @@
+#![allow(non_snake_case)]
+
+extern crate nsstring;
+
+use nsstring::*;
+use std::ffi::CString;
+use std::fmt::Write;
+use std::os::raw::c_char;
+
+fn nonfatal_fail(msg: String) {
+ extern "C" {
+ fn GTest_ExpectFailure(message: *const c_char);
+ }
+ unsafe {
+ let msg = CString::new(msg).unwrap();
+ GTest_ExpectFailure(msg.as_ptr());
+ }
+}
+
+/// This macro checks if the two arguments are equal, and causes a non-fatal
+/// GTest test failure if they are not.
+macro_rules! expect_eq {
+ ($x:expr, $y:expr) => {
+ match (&$x, &$y) {
+ (x, y) => {
+ if *x != *y {
+ nonfatal_fail(format!(
+ "check failed: (`{:?}` == `{:?}`) at {}:{}",
+ x,
+ y,
+ file!(),
+ line!()
+ ))
+ }
+ }
+ }
+ };
+}
+
+#[no_mangle]
+pub extern "C" fn Rust_StringFromCpp(cs: *const nsACString, s: *const nsAString) {
+ unsafe {
+ expect_eq!(&*cs, "Hello, World!");
+ expect_eq!(&*s, "Hello, World!");
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn Rust_AssignFromRust(cs: *mut nsACString, s: *mut nsAString) {
+ unsafe {
+ (*cs).assign(&nsCString::from("Hello, World!"));
+ expect_eq!(&*cs, "Hello, World!");
+ (*s).assign(&nsString::from("Hello, World!"));
+ expect_eq!(&*s, "Hello, World!");
+ }
+}
+
+extern "C" {
+ fn Cpp_AssignFromCpp(cs: *mut nsACString, s: *mut nsAString);
+}
+
+#[no_mangle]
+pub extern "C" fn Rust_AssignFromCpp() {
+ let mut cs = nsCString::new();
+ let mut s = nsString::new();
+ unsafe {
+ Cpp_AssignFromCpp(&mut *cs, &mut *s);
+ }
+ expect_eq!(cs, "Hello, World!");
+ expect_eq!(s, "Hello, World!");
+}
+
+#[no_mangle]
+pub extern "C" fn Rust_StringWrite() {
+ let mut cs = nsCString::new();
+ let mut s = nsString::new();
+
+ write!(s, "a").unwrap();
+ write!(cs, "a").unwrap();
+ expect_eq!(s, "a");
+ expect_eq!(cs, "a");
+ write!(s, "bc").unwrap();
+ write!(cs, "bc").unwrap();
+ expect_eq!(s, "abc");
+ expect_eq!(cs, "abc");
+ write!(s, "{}", 123).unwrap();
+ write!(cs, "{}", 123).unwrap();
+ expect_eq!(s, "abc123");
+ expect_eq!(cs, "abc123");
+}
+
+#[no_mangle]
+pub extern "C" fn Rust_FromEmptyRustString() {
+ let mut test = nsString::from("Blah");
+ test.assign_utf8(&nsCString::from(String::new()));
+ assert!(test.is_empty());
+}
+
+#[no_mangle]
+pub extern "C" fn Rust_WriteToBufferFromRust(
+ cs: *mut nsACString,
+ s: *mut nsAString,
+ fallible_cs: *mut nsACString,
+ fallible_s: *mut nsAString,
+) {
+ unsafe {
+ let cs_buf = (*cs).to_mut();
+ let s_buf = (*s).to_mut();
+ let fallible_cs_buf = (*fallible_cs).fallible_to_mut().unwrap();
+ let fallible_s_buf = (*fallible_s).fallible_to_mut().unwrap();
+
+ cs_buf[0] = b'A';
+ cs_buf[1] = b'B';
+ cs_buf[2] = b'C';
+ s_buf[0] = b'A' as u16;
+ s_buf[1] = b'B' as u16;
+ s_buf[2] = b'C' as u16;
+ fallible_cs_buf[0] = b'A';
+ fallible_cs_buf[1] = b'B';
+ fallible_cs_buf[2] = b'C';
+ fallible_s_buf[0] = b'A' as u16;
+ fallible_s_buf[1] = b'B' as u16;
+ fallible_s_buf[2] = b'C' as u16;
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn Rust_VoidStringFromRust(cs: &mut nsACString, s: &mut nsAString) {
+ cs.set_is_void(true);
+ s.set_is_void(true);
+}