From cc48211db16833c99243965563b1868149418183 Mon Sep 17 00:00:00 2001 From: Yaroslav Dynnikov <yaroslav.dynnikov@gmail.com> Date: Thu, 15 Sep 2022 13:56:45 +0300 Subject: [PATCH] feature: check raft_storage auto_impl correctness --- src/traft/raft_storage.rs | 5 +++++ src/util.rs | 42 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/traft/raft_storage.rs b/src/traft/raft_storage.rs index cc5cf16433..d34a62985e 100644 --- a/src/traft/raft_storage.rs +++ b/src/traft/raft_storage.rs @@ -11,6 +11,7 @@ use crate::traft; use crate::traft::RaftId; use crate::traft::RaftIndex; use crate::traft::RaftTerm; +use crate::util::str_eq; fn box_err(e: impl std::error::Error + Sync + Send + 'static) -> StorageError { StorageError::Other(Box::new(e)) @@ -57,6 +58,10 @@ macro_rules! auto_impl { $( $(#[$meta])* $vis fn $setter(&mut self, value: $ty) -> tarantool::Result<()> { + const _: () = assert!(str_eq( + stringify!($setter), + concat!("persist_", stringify!($key)) + )); let key: &str = stringify!($key); self.space_raft_state.$mod(&(key, value))?; Ok(()) diff --git a/src/util.rs b/src/util.rs index c3f9ec2b1f..4125a7f05e 100644 --- a/src/util.rs +++ b/src/util.rs @@ -214,12 +214,33 @@ impl std::borrow::Borrow<str> for Uppercase { } } +//////////////////////////////////////////////////////////////////////////////// +/// Compare string literals at compile time. + +#[allow(dead_code)] // suppress the warning since it's only used at compile time +pub const fn str_eq(lhs: &str, rhs: &str) -> bool { + let lhs = lhs.as_bytes(); + let rhs = rhs.as_bytes(); + if lhs.len() != rhs.len() { + return false; + } + let mut i = 0; + loop { + if i == lhs.len() { + return true; + } + if lhs[i] != rhs[i] { + return false; + } + i += 1; + } +} + #[cfg(test)] mod tests { - use super::*; - #[test] fn uppercase() { + use super::Uppercase; assert_eq!(&*Uppercase::from(""), ""); assert_eq!(&*Uppercase::from("hello"), "HELLO"); assert_eq!(&*Uppercase::from("HELLO"), "HELLO"); @@ -227,6 +248,23 @@ mod tests { assert_eq!(&*Uppercase::from(String::from("hello")), "HELLO"); assert_eq!(&*Uppercase::from(String::from("HELLO")), "HELLO"); } + + #[test] + fn str_eq() { + use super::str_eq; + assert!(str_eq("", "")); + assert!(str_eq("a", "a")); + assert!(str_eq("\0b", "\0b")); + assert!(str_eq("foobar", concat!("foo", "bar"))); + + assert!(!str_eq("", "x")); + assert!(!str_eq("x", "")); + assert!(!str_eq("x", "y")); + assert!(!str_eq("ы", "Ы")); + assert!(!str_eq("\0x", "\0y")); + assert!(!str_eq("foo1", "bar1")); + assert!(!str_eq("foo1", "foo2")); + } } //////////////////////////////////////////////////////////////////////////////// -- GitLab