[PATCH v1 1/2] rust: time: add example and KUnit test for Delta::as_millis_ceil()

FUJITA Tomonori <[email protected]>
Newsgroups org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
From: FUJITA Tomonori <[email protected]>

Add an example showing that the value is rounded towards positive
infinity, for both positive and negative spans.

as_millis_ceil() uses the same idiom as as_micros_ceil(), which dropped
the rounding bias near i64::MAX before commit ec90dfcf05f0 ("rust: time:
fix as_micros_ceil() rounding near i64::MAX"), so add a KUnit test for
the i64::MAX and i64::MIN extremes.

Signed-off-by: FUJITA Tomonori <[email protected]>
---
 rust/kernel/Kconfig.test | 10 ++++++++++
 rust/kernel/time.rs      | 42 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/rust/kernel/Kconfig.test b/rust/kernel/Kconfig.test
index e6a5c7a795f0..0087749995d2 100644
--- a/rust/kernel/Kconfig.test
+++ b/rust/kernel/Kconfig.test
@@ -83,4 +83,14 @@ config RUST_BITFIELD_KUNIT_TEST
 
 	  If unsure, say N.
 
+config RUST_TIME_KUNIT_TEST
+	bool "KUnit tests for the Rust time API" if !KUNIT_ALL_TESTS
+	default KUNIT_ALL_TESTS
+	help
+	  This option enables KUnit tests for the Rust time API.
+	  These are only for development and testing, not for regular
+	  kernel use cases.
+
+	  If unsure, say N.
+
 endif
diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index 6c0a5e8090d0..b0b43ad3aa47 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -530,6 +530,21 @@ pub fn as_millis(self) -> i64 {
 
     /// Return the smallest number of milliseconds greater than or equal
     /// to the value in the [`Delta`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use kernel::time::Delta;
+    ///
+    /// // Whole milliseconds are returned as-is.
+    /// assert_eq!(Delta::from_millis(2).as_millis_ceil(), 2);
+    /// assert_eq!(Delta::from_nanos(1_000_000).as_millis_ceil(), 1);
+    /// assert_eq!(Delta::from_nanos(-1_000_000).as_millis_ceil(), -1);
+    ///
+    /// // Anything else is rounded towards positive infinity.
+    /// assert_eq!(Delta::from_nanos(1_000_001).as_millis_ceil(), 2);
+    /// assert_eq!(Delta::from_nanos(-1_000_001).as_millis_ceil(), -1);
+    /// ```
     #[inline]
     pub fn as_millis_ceil(self) -> i64 {
         // Only positive values need to be rounded up: truncating division already
@@ -580,3 +595,30 @@ pub fn rem_nanos(self, dividend: i32) -> Self {
         }
     }
 }
+
+#[cfg(CONFIG_RUST_TIME_KUNIT_TEST)]
+#[macros::kunit_tests(rust_kernel_time)]
+mod tests {
+    use super::*;
+
+    /// `i64::MAX` nanoseconds in milliseconds, rounded towards positive infinity.
+    const MAX_MILLIS_CEIL: i64 = 9_223_372_036_855;
+
+    /// `i64::MIN` nanoseconds in milliseconds, rounded towards positive infinity.
+    const MIN_MILLIS_CEIL: i64 = -9_223_372_036_854;
+
+    #[test]
+    fn as_millis_ceil_extremes() {
+        // The rounding bias must survive near `i64::MAX`.
+        assert_eq!(
+            Delta::from_nanos(i64::MAX).as_millis_ceil(),
+            MAX_MILLIS_CEIL
+        );
+
+        // No bias is applied to negative values, so `i64::MIN` cannot overflow.
+        assert_eq!(
+            Delta::from_nanos(i64::MIN).as_millis_ceil(),
+            MIN_MILLIS_CEIL
+        );
+    }
+}
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.