[Python-checkins] cpython: Fix test_time on Windows

victor.stinner python-checkins at python.org
Thu Sep 10 09:37:34 CEST 2015


https://hg.python.org/cpython/rev/ea7e19bc22c9
changeset:   97849:ea7e19bc22c9
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Thu Sep 10 09:10:14 2015 +0200
summary:
  Fix test_time on Windows

* Filter values which would overflow on conversion to the C long type
  (for timeval.tv_sec).
* Adjust also the message of OverflowError on PyTime conversions
* test_time: add debug information if a timestamp conversion fails

files:
  Lib/test/test_time.py |  33 ++++++++++++++++++++++--------
  Python/pytime.c       |  28 +++++++------------------
  2 files changed, 32 insertions(+), 29 deletions(-)


diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -756,10 +756,15 @@
             context.rounding = decimal_rnd
 
             for value in valid_values:
-                expected = expected_func(value)
-                self.assertEqual(pytime_converter(value, time_rnd),
+                debug_info = {'value': value, 'rounding': decimal_rnd}
+                try:
+                    result = pytime_converter(value, time_rnd)
+                    expected = expected_func(value)
+                except Exception as exc:
+                    self.fail("Error on timestamp conversion: %s" % debug_info)
+                self.assertEqual(result,
                                  expected,
-                                 {'value': value, 'rounding': decimal_rnd})
+                                 debug_info)
 
         # test overflow
         ns = self.OVERFLOW_SECONDS * SEC_TO_NS
@@ -770,14 +775,15 @@
                 with self.assertRaises(OverflowError):
                     pytime_converter(value, time_rnd)
 
-    def check_int_rounding(self, pytime_converter, expected_func, unit_to_sec=1,
-                           value_filter=None):
+    def check_int_rounding(self, pytime_converter, expected_func,
+                           unit_to_sec=1, value_filter=None):
         self._check_rounding(pytime_converter, expected_func,
                              False, unit_to_sec, value_filter)
 
-    def check_float_rounding(self, pytime_converter, expected_func, unit_to_sec=1):
+    def check_float_rounding(self, pytime_converter, expected_func,
+                             unit_to_sec=1, value_filter=None):
         self._check_rounding(pytime_converter, expected_func,
-                             True, unit_to_sec)
+                             True, unit_to_sec, value_filter)
 
     def decimal_round(self, x):
         d = decimal.Decimal(x)
@@ -845,9 +851,19 @@
             us = us_converter(ns)
             return divmod(us, SEC_TO_US)
 
+        if sys.platform == 'win32':
+            from _testcapi import LONG_MIN, LONG_MAX
+
+            # On Windows, timeval.tv_sec type is a C long
+            def seconds_filter(secs):
+                return LONG_MIN <= secs <= LONG_MAX
+        else:
+            seconds_filter = None
+
         self.check_int_rounding(PyTime_AsTimeval,
                                 timeval_converter,
-                                NS_TO_SEC)
+                                NS_TO_SEC,
+                                value_filter=seconds_filter)
 
     @unittest.skipUnless(hasattr(_testcapi, 'PyTime_AsTimespec'),
                          'need _testcapi.PyTime_AsTimespec')
@@ -927,6 +943,5 @@
                                   self.create_converter(SEC_TO_NS))
 
 
-
 if __name__ == "__main__":
     unittest.main()
diff --git a/Python/pytime.c b/Python/pytime.c
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -288,18 +288,21 @@
     else {
 #ifdef HAVE_LONG_LONG
         PY_LONG_LONG sec;
+        assert(sizeof(PY_LONG_LONG) <= sizeof(_PyTime_t));
+
         sec = PyLong_AsLongLong(obj);
-        assert(sizeof(PY_LONG_LONG) <= sizeof(_PyTime_t));
 #else
         long sec;
+        assert(sizeof(PY_LONG_LONG) <= sizeof(_PyTime_t));
+
         sec = PyLong_AsLong(obj);
-        assert(sizeof(PY_LONG_LONG) <= sizeof(_PyTime_t));
 #endif
         if (sec == -1 && PyErr_Occurred()) {
             if (PyErr_ExceptionMatches(PyExc_OverflowError))
                 _PyTime_overflow();
             return -1;
         }
+
         *t = sec * unit_to_ns;
         if (*t / unit_to_ns != sec) {
             _PyTime_overflow();
@@ -404,27 +407,12 @@
     ns = t % SEC_TO_NS;
 
 #ifdef MS_WINDOWS
-    /* On Windows, timeval.tv_sec is a long (32 bit),
-       whereas time_t can be 64-bit. */
-    assert(sizeof(tv->tv_sec) == sizeof(long));
-#if SIZEOF_TIME_T > SIZEOF_LONG
-    if (secs > LONG_MAX) {
-        secs = LONG_MAX;
-        res = -1;
-    }
-    else if (secs < LONG_MIN) {
-        secs = LONG_MIN;
-        res = -1;
-    }
-#endif
     tv->tv_sec = (long)secs;
 #else
-    /* On OpenBSD 5.4, timeval.tv_sec is a long.
-       Example: long is 64-bit, whereas time_t is 32-bit. */
     tv->tv_sec = secs;
+#endif
     if ((_PyTime_t)tv->tv_sec != secs)
         res = -1;
-#endif
 
     usec = (int)_PyTime_Divide(ns, US_TO_NS, round);
     if (usec < 0) {
@@ -440,7 +428,7 @@
     tv->tv_usec = usec;
 
     if (res && raise)
-        _PyTime_overflow();
+        error_time_t_overflow();
     return res;
 }
 
@@ -473,7 +461,7 @@
     ts->tv_nsec = nsec;
 
     if ((_PyTime_t)ts->tv_sec != secs) {
-        _PyTime_overflow();
+        error_time_t_overflow();
         return -1;
     }
     return 0;

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list