Timing unit tests: more protection against infinite loops

If timing_timer_simple fails because it detects that timers are likely
to never expire (e.g. going backward or not incrementing), skip all
tests that rely on timers.
diff --git a/tests/suites/test_suite_timing.function b/tests/suites/test_suite_timing.function
index 71fe7ed..1610155 100644
--- a/tests/suites/test_suite_timing.function
+++ b/tests/suites/test_suite_timing.function
@@ -38,6 +38,14 @@
             0 );
 }
 
+/* Some conditions in timing_timer_simple suggest that timers are unreliable.
+   Most other test cases rely on timers to terminate, and could loop
+   indefinitely if timers are too broken. So if timing_timer_simple detected a
+   timer that risks not terminating (going backwards, or not reaching the
+   desired count in the alloted clock cycles), set this flag to immediately
+   fail those other tests without running any timers. */
+static int timers_are_badly_broken = 0;
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -73,6 +81,15 @@
     return;
 
 exit:
+    if( iterations >= TIMING_SHORT_TEST_ITERATIONS_MAX ||
+        new_millis < millis )
+    {
+        /* The timer was very unreliable: it didn't increment and the loop ran
+           out, or it went backwards. Other tests that use timers might go
+           into an infinite loop, so we'll skip them. */
+        timers_are_badly_broken = 1;
+    }
+
     /* No cleanup needed, but show some diagnostic iterations, because timing
        problems can be hard to reproduce. */
     mbedtls_fprintf( stdout, "  Finished with millis=%lu new_millis=%lu get(timer)<=%lu iterations=%lu\n",
@@ -87,6 +104,11 @@
     struct mbedtls_timing_hr_time timer;
     unsigned long millis = 0;
     unsigned long iterations = 0;
+
+    /* Skip this test if it looks like timers don't work at all, to avoid an
+       infinite loop below. */
+    TEST_ASSERT( !timers_are_badly_broken );
+
     /* Start the timer. Timers are always reset to 0. */
     TEST_ASSERT( mbedtls_timing_get_timer( &timer, 1 ) == 0 );
     /* Busy-wait loop for a few milliseconds */
@@ -107,9 +129,10 @@
 exit:
     /* No cleanup needed, but show some diagnostic information, because timing
        problems can be hard to reproduce. */
-    mbedtls_fprintf( stdout, "  Finished with millis=%lu get(timer)<=%lu iterations=%lu\n",
-                     millis, mbedtls_timing_get_timer( &timer, 0 ),
-                     iterations );
+    if( !timers_are_badly_broken )
+        mbedtls_fprintf( stdout, "  Finished with millis=%lu get(timer)<=%lu iterations=%lu\n",
+                         millis, mbedtls_timing_get_timer( &timer, 0 ),
+                         iterations );
 }
 /* END_CASE */
 
@@ -117,7 +140,11 @@
 void timing_two_timers( int delta )
 {
     struct mbedtls_timing_hr_time timer1, timer2;
-    unsigned long millis1, millis2;
+    unsigned long millis1 = 0, millis2 = 0;
+
+    /* Skip this test if it looks like timers don't work at all, to avoid an
+       infinite loop below. */
+    TEST_ASSERT( !timers_are_badly_broken );
 
     /* Start the first timer and wait for a short time. */
     (void) mbedtls_timing_get_timer( &timer1, 1 );
@@ -153,9 +180,10 @@
 exit:
     /* No cleanup needed, but show some diagnostic iterations, because timing
        problems can be hard to reproduce. */
-    mbedtls_fprintf( stdout, "  Finished with millis1=%lu get(timer1)<=%lu millis2=%lu get(timer2)<=%lu\n",
-                     millis1, mbedtls_timing_get_timer( &timer1, 0 ),
-                     millis2, mbedtls_timing_get_timer( &timer2, 0 ) );
+    if( !timers_are_badly_broken )
+        mbedtls_fprintf( stdout, "  Finished with millis1=%lu get(timer1)<=%lu millis2=%lu get(timer2)<=%lu\n",
+                         millis1, mbedtls_timing_get_timer( &timer1, 0 ),
+                         millis2, mbedtls_timing_get_timer( &timer2, 0 ) );
 }
 /* END_CASE */
 
@@ -177,6 +205,10 @@
                                  TIMING_ALARM_0_DELAY_MS );
     unsigned long iterations = 0;
 
+    /* Skip this test if it looks like timers don't work at all, to avoid an
+       infinite loop below. */
+    TEST_ASSERT( !timers_are_badly_broken );
+
     /* Set an alarm and count how long it takes with a timer. */
     (void) mbedtls_timing_get_timer( &timer, 1 );
     mbedtls_set_alarm( seconds );
@@ -209,10 +241,11 @@
 exit:
     /* Show some diagnostic iterations, because timing
        problems can be hard to reproduce. */
-    mbedtls_fprintf( stdout, "  Finished with alarmed=%d millis=%lu get(timer)<=%lu iterations=%lu\n",
-                     mbedtls_timing_alarmed,
-                     millis, mbedtls_timing_get_timer( &timer, 0 ),
-                     iterations );
+    if( !timers_are_badly_broken )
+        mbedtls_fprintf( stdout, "  Finished with alarmed=%d millis=%lu get(timer)<=%lu iterations=%lu\n",
+                         mbedtls_timing_alarmed,
+                         millis, mbedtls_timing_get_timer( &timer, 0 ),
+                         iterations );
     /* Cleanup */
     mbedtls_timing_alarmed = 0;
 }
@@ -228,7 +261,7 @@
 
     mbedtls_timing_delay_context delay;
     struct mbedtls_timing_hr_time timer;
-    unsigned long delta; /* delay started between timer=0 and timer=delta */
+    unsigned long delta = 0; /* delay started between timer=0 and timer=delta */
     unsigned long before = 0, after = 0;
     unsigned long iterations = 0;
     int status = -2;
@@ -238,6 +271,10 @@
     assert( int_ms >= 0 );
     assert( fin_ms >= 0 );
 
+    /* Skip this test if it looks like timers don't work at all, to avoid an
+       infinite loop below. */
+    TEST_ASSERT( !timers_are_badly_broken );
+
     /* Start a reference timer. Program a delay, and verify that the status of
        the delay is consistent with the time given by the reference timer. */
     (void) mbedtls_timing_get_timer( &timer, 1 );
@@ -310,8 +347,9 @@
 exit:
     /* No cleanup needed, but show some diagnostic iterations, because timing
        problems can be hard to reproduce. */
-    mbedtls_fprintf( stdout, "  Finished with delta=%lu before=%lu after=%lu status=%d iterations=%lu\n",
-                     delta, before, after, status, iterations );
+    if( !timers_are_badly_broken )
+        mbedtls_fprintf( stdout, "  Finished with delta=%lu before=%lu after=%lu status=%d iterations=%lu\n",
+                         delta, before, after, status, iterations );
     if( warn_inconclusive )
         mbedtls_fprintf( stdout, "  Inconclusive test, try running it on a less heavily loaded machine.\n" );
  }
@@ -326,7 +364,11 @@
        completely nonsensical values. */
 
     struct mbedtls_timing_hr_time timer;
-    unsigned long hardclock0, hardclock1, delta1;
+    unsigned long hardclock0 = -1, hardclock1 = -1, delta1 = -1;
+
+    /* Skip this test if it looks like timers don't work at all, to avoid an
+       infinite loop below. */
+    TEST_ASSERT( !timers_are_badly_broken );
 
     hardclock0 = mbedtls_timing_hardclock( );
     /* Wait 2ms to ensure a nonzero delay. Since the timer interface has 1ms
@@ -354,7 +396,8 @@
 exit:
     /* No cleanup needed, but show some diagnostic iterations, because timing
        problems can be hard to reproduce. */
-    mbedtls_fprintf( stdout, "  Finished with hardclock=%lu,%lu\n",
-                     hardclock0, hardclock1 );
+    if( !timers_are_badly_broken )
+        mbedtls_fprintf( stdout, "  Finished with hardclock=%lu,%lu\n",
+                         hardclock0, hardclock1 );
 }
 /* END_CASE */