]> git.lizzy.rs Git - rust.git/commitdiff
save an Instant for the timeout instead of a Duration
authorFelix Rath <felixr@archlinux.info>
Sat, 6 Aug 2016 13:07:16 +0000 (15:07 +0200)
committerFelix Rath <felixr@archlinux.info>
Sun, 7 Aug 2016 11:40:04 +0000 (13:40 +0200)
requires less bookkeeping. also move some functionality into functions,
to keep the loop cleaner.

src/libtest/lib.rs

index 106c14850ca24582887e26ea33519c885e1ce1f8..64515b900d5b188e5b364319ecdd2d40ebd2ce90 100644 (file)
@@ -596,7 +596,9 @@ pub fn write_result(&mut self, result: &TestResult) -> io::Result<()> {
     }
 
     pub fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
-        self.write_plain(&format!("test {} has been running for over {} seconds\n", desc.name, TEST_WARN_TIMEOUT_S))
+        self.write_plain(&format!("test {} has been running for over {} seconds\n",
+                                  desc.name,
+                                  TEST_WARN_TIMEOUT_S))
     }
 
     pub fn write_log(&mut self, test: &TestDesc, result: &TestResult) -> io::Result<()> {
@@ -879,7 +881,28 @@ fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) ->
 
     let (tx, rx) = channel::<MonitorMsg>();
 
-    let mut running_tests: HashMap<TestDesc, Duration> = HashMap::new();
+    let mut running_tests: HashMap<TestDesc, Instant> = HashMap::new();
+
+    fn get_timed_out_tests(running_tests: &mut HashMap<TestDesc, Instant>) -> Vec<TestDesc> {
+        let now = Instant::now();
+        let timed_out = running_tests.iter()
+            .filter_map(|(desc, timeout)| if &now >= timeout { Some(desc.clone())} else { None })
+            .collect();
+        for test in &timed_out {
+            running_tests.remove(test);
+        }
+        timed_out
+    };
+
+    fn calc_timeout(running_tests: &HashMap<TestDesc, Instant>) -> Option<Duration> {
+        running_tests.values().min().map(|next_timeout| {
+            let now = Instant::now();
+            if *next_timeout >= now {
+                *next_timeout - now
+            } else {
+                Duration::new(0, 0)
+            }})
+    };
 
     while pending > 0 || !remaining.is_empty() {
         while pending < concurrency && !remaining.is_empty() {
@@ -890,38 +913,26 @@ fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) ->
                 // that hang forever.
                 callback(TeWait(test.desc.clone(), test.testfn.padding()))?;
             }
-            running_tests.insert(test.desc.clone(), Duration::from_secs(TEST_WARN_TIMEOUT_S));
+            let timeout = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S);
+            running_tests.insert(test.desc.clone(), timeout);
             run_test(opts, !opts.run_tests, test, tx.clone());
             pending += 1;
         }
 
         let mut res;
-        if let Some(min_timeout) = running_tests.values().min().cloned() {
-            loop {
-                let before = Instant::now();
-                res = rx.recv_timeout(min_timeout);
-                let elapsed = Instant::now() - before;
-
-                let mut to_remove = Vec::new();
-                for (desc, time_left) in &mut running_tests {
-                    if *time_left >= elapsed {
-                        *time_left -= elapsed;
-                    } else {
-                        to_remove.push(desc.clone());
-                        callback(TeTimeout(desc.clone()))?;
-                    }
-                }
-
-                for rem in to_remove {
-                    running_tests.remove(&rem);
+        loop {
+            if let Some(timeout) = calc_timeout(&running_tests) {
+                res = rx.recv_timeout(timeout);
+                for test in get_timed_out_tests(&mut running_tests) {
+                    callback(TeTimeout(test))?;
                 }
-
                 if res != Err(RecvTimeoutError::Timeout) {
                     break;
                 }
+            } else {
+                res = rx.recv().map_err(|_| RecvTimeoutError::Disconnected);
+                break;
             }
-        } else {
-            res = rx.recv().map_err(|_| RecvTimeoutError::Disconnected);
         }
 
         let (desc, result, stdout) = res.unwrap();