public inbox for yew-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: yew-devel@lists.proxmox.com
Subject: [yew-devel] [PATCH yew-comp 05/20] rrd: units: add tests
Date: Fri, 30 May 2025 14:21:47 +0200	[thread overview]
Message-ID: <20250530122202.2779300-6-d.csapak@proxmox.com> (raw)
In-Reply-To: <20250530122202.2779300-1-d.csapak@proxmox.com>

so we can argue about code changes more easily, also expand the range
check for negative ranges, since that should not happen.

this also adds some comments what the functions should do

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/rrd/units.rs | 149 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 145 insertions(+), 4 deletions(-)

diff --git a/src/rrd/units.rs b/src/rrd/units.rs
index b29a238..ad72565 100644
--- a/src/rrd/units.rs
+++ b/src/rrd/units.rs
@@ -1,16 +1,21 @@
+// calculates the distance of the x axis labels + grid for base10 units
+// The distance calculated is always between 1/2 and 1/10 of the range
 pub(crate) fn get_grid_unit_base10(min: f64, max: f64) -> f64 {
     let range = max - min;
 
-    if range == 0.0 {
-        panic!("get_grid_unit_base10: got zero range - internal error");
+    if range <= 0.0 {
+        panic!("get_grid_unit_base10: got zero or negative range - internal error");
     }
 
     let mut l = range.log10() as i32;
 
+    // the count can be between 1 and 10
     while (range / 10.0_f64.powi(l)) < 2.0 {
         l -= 1;
     }
 
+    // now it must be between 2 and 20
+
     let mut res = 10.0_f64.powi(l);
 
     let count = range / res;
@@ -20,15 +25,18 @@ pub(crate) fn get_grid_unit_base10(min: f64, max: f64) -> f64 {
     } else if count > 10.0 {
         res *= 2.0;
     }
+    // here the count must be between 2 and 10
 
     res
 }
 
+// calculates the distance of the x axis labels + grid for base2 units
+// The distance calculated is always smaller than 1/4 of the range
 pub(crate) fn get_grid_unit_base2(min: f64, max: f64) -> f64 {
     let range = max - min;
 
-    if range == 0.0 {
-        panic!("get_grid_unit_base2: got zero range - internal error");
+    if range <= 0.0 {
+        panic!("get_grid_unit_base2: got zero or negative range - internal error");
     }
 
     let mut l = range.log2() as i32;
@@ -93,3 +101,136 @@ pub(crate) fn get_time_grid_unit(min: i64, max: i64) -> i64 {
 
     l
 }
+
+#[cfg(test)]
+mod test {
+    use std::panic;
+
+    use crate::rrd::units::get_time_grid_unit;
+
+    use super::{get_grid_unit_base10, get_grid_unit_base2};
+
+    const DELTA: f64 = 0.0000001;
+
+    #[test]
+    fn test_grid_unit_base2() {
+        // min, max, result
+        let test_data = [
+            // normal range tests
+            (0.0, 0.01, Some(2.0_f64.powi(-9))),
+            (0.0, 2.0, Some(2.0_f64.powi(-1))),
+            (0.0, 0.00001, Some(2.0_f64.powi(-19))),
+            (0.0, 100.0, Some(2.0_f64.powi(4))),
+            (0.0, 1_000_000.0, Some(2.0_f64.powi(17))),
+            (0.0, f64::MAX, Some(2.0_f64.powi(1021))),
+            (
+                10.0 * 1024.0 * 1024.0,
+                12.5 * 1024.0 * 1024.0,
+                Some(2.0_f64.powi(19)),
+            ),
+            // ranges with negative data
+            (-500.0, -100.0, Some(2.0_f64.powi(6))),
+            (-500.0, 100.0, Some(2.0_f64.powi(7))),
+            // panic tests
+            (0.0, 0.0, None),
+            (100.0, 0.01, None),
+        ];
+
+        for (min, max, expected) in test_data {
+            match (
+                panic::catch_unwind(|| get_grid_unit_base2(min, max)).ok(),
+                expected,
+            ) {
+                (Some(result), Some(expected)) => {
+                    let diff = result - expected;
+                    assert_eq!(
+                        diff < DELTA,
+                        diff > -DELTA,
+                        "{min} .. {max} ->\n {expected} \n {result}"
+                    )
+                }
+                (None, Some(expected)) => {
+                    panic!("panic'ed when it shouldn't: {min} .. {max} -> {expected}")
+                }
+                (Some(result), None) => {
+                    panic!("result when it should have panic'ed: {min} .. {max} -> {result}")
+                }
+                (None, None) => {}
+            }
+        }
+    }
+
+    #[test]
+    fn test_grid_unit_base10() {
+        // min, max, result
+        let test_data = [
+            // normal range tests
+            (0.0, 0.01, Some(0.001)),
+            (0.0, 2.0, Some(1.0)),
+            (0.0, 0.00001, Some(0.000002)),
+            (0.0, 100.0, Some(10.0)),
+            (0.0, 1_000_000.0, Some(100_000.0)),
+            (
+                0.0,
+                f64::MAX,
+                Some(5000000000000002.0 * 10.0_f64.powf(292.0)),
+            ),
+            (
+                10.0 * 1024.0 * 1024.0,
+                12.5 * 1024.0 * 1024.0,
+                Some(1_000_000.0),
+            ),
+            // ranges with negative data
+            (-500.0, -100.0, Some(100.0)),
+            (-500.0, 100.0, Some(100.0)),
+            // panic tests
+            (0.0, 0.0, None),
+            (100.0, 0.01, None),
+        ];
+
+        for (min, max, expected) in test_data {
+            match (
+                panic::catch_unwind(|| get_grid_unit_base10(min, max)).ok(),
+                expected,
+            ) {
+                (Some(result), Some(expected)) => {
+                    let diff = result - expected;
+                    assert_eq!(
+                        diff < DELTA,
+                        diff > -DELTA,
+                        "{min} .. {max} ->\n {expected} \n {result}"
+                    )
+                }
+                (None, Some(expected)) => {
+                    panic!("panic'ed when it shouldn't: {min} .. {max} -> {expected}")
+                }
+                (Some(result), None) => {
+                    panic!("result when it should have panic'ed: {min} .. {max} -> {result}")
+                }
+                (None, None) => {}
+            }
+        }
+    }
+
+    #[test]
+    fn test_time_grid_unit() {
+        // min max result
+        let test_data = [
+            (0, 10, 1),
+            (0, 100, 15),
+            (0, 1_000_000, 172800),
+            (0, i64::MAX, 1519964874237542400),
+            (-1000, 1_000_000, 172800),
+            (0, 0, 1),
+            (1, 0, 1),
+        ];
+
+        for (min, max, expected) in test_data {
+            assert_eq!(
+                get_time_grid_unit(min, max),
+                expected,
+                "{min}..{max} -> {expected}"
+            )
+        }
+    }
+}
-- 
2.39.5



_______________________________________________
yew-devel mailing list
yew-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/yew-devel


  parent reply	other threads:[~2025-05-30 12:22 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-30 12:21 [yew-devel] [PATCH yew-comp 00/20] refactor and improve rrd graph code Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 01/20] remove old rrd uplot code Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 02/20] rrd: refactor code for compute_min_max Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 03/20] rrd: move into own module Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 04/20] rrd: move unit calculation to " Dominik Csapak
2025-05-30 12:21 ` Dominik Csapak [this message]
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 06/20] rrd: units: simplify calculations for get_grid_unit_base Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 07/20] rrd: remove unnecessary `no_data` field Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 08/20] rrd: align tooltip directly to pointer position Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 09/20] rrd: use 'cross_pos' state instead of 'draw_cross' Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 10/20] rrd: give all elements in svg keys Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 11/20] rrd: simplify toggle Msg Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 12/20] rrd: remove wrongly annotated lifetime Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 13/20] rrd: refactor series related struct and functions into own module Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 14/20] rrd: clamp view range when time_data changes Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 15/20] rrd: refactor grid data computation Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 16/20] rrd: introduce GraphSpace struct and use it to precalculate graph data Dominik Csapak
2025-05-30 12:21 ` [yew-devel] [PATCH yew-comp 17/20] rrd: precalculate the grid line and label positions Dominik Csapak
2025-05-30 12:22 ` [yew-devel] [PATCH yew-comp 18/20] rrd: calculate series svg data only when necessary Dominik Csapak
2025-05-30 12:22 ` [yew-devel] [PATCH yew-comp 19/20] rrd: refactor selection rectangle calculation Dominik Csapak
2025-05-30 12:22 ` [yew-devel] [PATCH yew-comp 20/20] rrd: refactor the cross position calculation Dominik Csapak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250530122202.2779300-6-d.csapak@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=yew-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal