[Git][NTPsec/ntpsec][master] Fixed 0.000, and filt* display errors. Added relevant tests.

Gary E. Miller gitlab at mg.gitlab.com
Fri Apr 14 22:19:49 UTC 2017


Gary E. Miller pushed to branch master at NTPsec / ntpsec


Commits:
c77b2593 by Ian Bruene at 2017-04-14T22:19:41+00:00
Fixed 0.000, and filt* display errors. Added relevant tests.

- - - - -


2 changed files:

- pylib/util.py
- tests/pylib/test_util.py


Changes:

=====================================
pylib/util.py
=====================================
--- a/pylib/util.py
+++ b/pylib/util.py
@@ -94,14 +94,19 @@ def stringfiltcooker(data):
     "Cooks a filt* string of space seperated numbers, expects milliseconds"
     parts = data.split()
     oomcount = {}
+    minscale = -100000  # Keep track of the maxdownscale for each value
     # Find out what the 'natural' unit of each value is
     for part in parts:
         value, oom = scalestring(part)
+        ds = maxdownscale(part)
+        minscale = max(ds, minscale)
         oomcount[oom] = oomcount.get(oom, 0) + 1
     # Find the most common unit
-    mostcommon = None
+    mostcommon = 0
     highestcount = 0
     for key in oomcount.keys():
+        if key < minscale:
+            continue  # skip any scale that would result in making up data
         count = oomcount[key]
         if count > highestcount:
             mostcommon = key
@@ -162,6 +167,15 @@ def gluenumberstring(above, below, isnegative):
     return newvalue
 
 
+def maxdownscale(value):
+    "Maximum units a value can be scaled down without inventing data"
+    if "." in value:
+        digitcount = len(value.split(".")[1])
+        return -(digitcount // 3)
+    else:
+        return 0
+
+
 def rescalestring(value, unitsscaled):
     "Rescale a number string by a given number of units"
     whole, dec, negative = breaknumberstring(value)
@@ -173,8 +187,10 @@ def rescalestring(value, unitsscaled):
     hilen = len(whole)
     lolen = len(dec)
     digitsmoved = abs(unitsscaled * 3)
-    if unitsscaled > 0:  # Scale to a larger unit
-        if hilen < digitsmoved:  # Scaling beyond the digits, pad it out
+    if unitsscaled > 0:  # Scale to a larger unit, move decimal left
+        if hilen < digitsmoved:
+            # Scaling beyond the digits, pad it out. We can pad here
+            # without making up digits that don't exist
             padcount = digitsmoved - hilen
             newwhole = "0"
             newdec = ("0" * padcount) + whole + dec
@@ -184,14 +200,16 @@ def rescalestring(value, unitsscaled):
             newwhole = whole[:choppoint]
             if newwhole == "":
                 newwhole = "0"
-    elif unitsscaled < 0:  # scale to a smaller unit
-        if lolen < digitsmoved:  # Scaling beyone the digits, pad it out
-            padcount = digitsmoved - lolen
-            newwhole = whole + dec + ("0" * padcount)
-            newdec = ""
+    elif unitsscaled < 0:  # scale to a smaller unit, move decimal right
+        if lolen < digitsmoved:
+            # Scaling beyond the digits would force us to make up data
+            # that doesn't exist. So fail.
+            # The caller should have already caught this with maxdownscale()
+            return None
         else:
             newwhole = whole + dec[:digitsmoved]
             newdec = dec[digitsmoved:]
+    newwhole = newwhole.lstrip("0")
     newvalue = gluenumberstring(newwhole, newdec, negative)
     return newvalue
 
@@ -215,7 +233,12 @@ def scalestring(value):
         else:
             lounits = (i // 3) + 1  # always need to shift one more unit
             movechars = lounits * 3
-            newwhole = dec[:movechars].lstrip('0')
+            if lolen < movechars:
+                # Not enough digits to scale all the way down. Inventing
+                # digits is unacceptable, so scale down as much as we can.
+                lounits = (i // 3)  # "always", unless out of digits
+                movechars = lounits * 3
+            newwhole = dec[:movechars].lstrip("0")
             newdec = dec[movechars:]
             unitsmoved = -lounits
     else:  # Shift to larger units
@@ -316,8 +339,9 @@ def unitify(value, startingunit, baseunit=None, strip=False, width=8):
         baseunit = getunitgroup(startingunit)[0]
     if isstringzero(value) is True:  # display highest precision zero
         if strip is False:
-            value = fitinfield("0", width - len(baseunit))
-        value = value + baseunit
+            value = fitinfield("0", width - len(baseunit)) + baseunit
+        else:
+            value = "0" + baseunit
         return value
     ooms = oomsbetweenunits(startingunit, baseunit)
     newvalue = cropprecision(value, ooms)


=====================================
tests/pylib/test_util.py
=====================================
--- a/tests/pylib/test_util.py
+++ b/tests/pylib/test_util.py
@@ -37,6 +37,8 @@ class TestPylibUtilMethods(unittest.TestCase):
 
         # Scale all decimals
         self.assertEqual(f("0.042"), ("42", -1))
+        # Unscalable
+        self.assertEqual(f(".23"), ("0.23", 0))
         # Typical length, positive value, no scaling
         self.assertEqual(f("1.23450"), ("1.23450", 0))
         # Ditto, negative
@@ -89,9 +91,11 @@ class TestPylibUtilMethods(unittest.TestCase):
         # ditto, negative
         self.assertEqual(f("-1.23456", -1), "-1234.56")
         # Scale to lower unit, beyond available digits
-        self.assertEqual(f("1.23456", -2), "1234560")
+        self.assertEqual(f("1.23456", -2), None)
         # ditto, negative
-        self.assertEqual(f("-1.23456", -2), "-1234560")
+        self.assertEqual(f("-1.23456", -2), None)
+        # Scale from below the decimal
+        self.assertEqual(f("0.420", -1), "420")
 
     def test_breaknumberstring(self):
         f = ntp.util.breaknumberstring
@@ -204,12 +208,23 @@ class TestPylibUtilMethods(unittest.TestCase):
             "1.02 34.5 0.67835 -23.0 9 6.7 1.00 .1"),
             "   1.02    34.5 0.67835   -23.0       9     6.7    1.00     0.1 ms"
         )
-        # Scale
+        # Scale to larger unit
         self.assertEqual(ntp.util.stringfiltcooker(
             "1000.02 3400.5 0.67835 -23.0 9001 6.7 1.00 1234"),
             "1.00002  3.4005 0.00068 -0.0230   9.001  0.0067 0.00100   1.234 s"
         )
-
+        # Scale to smaller unit
+        self.assertEqual(ntp.util.stringfiltcooker(
+            "0.470 0.420 0.430 0.500 0.460 0.4200 0.490 0.480"),
+            u"    470     420     430     500     460   420.0     490     480 \u03bcs")
+        # Can't scale
+        self.assertEqual(ntp.util.stringfiltcooker(
+            "0.47 0.42 0.43 0.50 0.46 0.42 0.49 0.48"),
+            "   0.47    0.42    0.43    0.50    0.46    0.42    0.49    0.48 ms")
+        # Can't scale, only one value blocking
+        self.assertEqual(ntp.util.stringfiltcooker(
+            "0.47 0.4200 0.4300 0.5000 0.4600 0.4200 0.4900 0.4800"),
+            "   0.47  0.4200  0.4300  0.5000  0.4600  0.4200  0.4900  0.4800 ms")
     def test_unitrelativeto(self):
         f = ntp.util.unitrelativeto
 



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/c77b2593e382664de948d040ee719ccc554c9551

---
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/c77b2593e382664de948d040ee719ccc554c9551
You're receiving this email because of your account on gitlab.com.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20170414/2948f3cc/attachment.html>


More information about the vc mailing list