Allow non-fatal timestamp solver failures

This refactors the timestamp filters so that it is possible to observe
timestamp solver failures without having the application crash.

This also makes it so that the timestamp_extractor code gets at least
somewhat exercised by our tests.

The only behavioral change this should cause for normal users is that
the stack trace will look slightly different when errors occur, because
the LOG(FATAL) now occurs when evaluating the result of QueueNextTimestamp()
instead of deep in the code (the prior LOG(FATAL)'s are replaced by
LOG(ERROR)'s to keep them visible).

Change-Id: I01e4de8df724c2853cc62ac588668b811563b33d
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
diff --git a/aos/network/testing_time_converter.cc b/aos/network/testing_time_converter.cc
index c175fe6..9dc5fff 100644
--- a/aos/network/testing_time_converter.cc
+++ b/aos/network/testing_time_converter.cc
@@ -22,7 +22,10 @@
 
 TestingTimeConverter::~TestingTimeConverter() {
   if (at_end_) {
-    CHECK(!NextTimestamp()) << ": At the end but there is more data.";
+    auto next_timestamp = NextTimestamp();
+    CHECK(next_timestamp.has_value()) << ": Unexpected error";
+    CHECK(!next_timestamp.value().has_value())
+        << ": At the end but there is more data.";
   }
 }
 
@@ -105,13 +108,17 @@
   ts_.emplace_back(std::make_tuple(time, std::move(times)));
 }
 
-std::optional<std::tuple<distributed_clock::time_point,
-                         std::vector<logger::BootTimestamp>>>
+std::optional<std::optional<std::tuple<distributed_clock::time_point,
+                                       std::vector<logger::BootTimestamp>>>>
 TestingTimeConverter::NextTimestamp() {
   CHECK(!first_) << ": Tried to pull a timestamp before one was added.  This "
                     "is unlikely to be what you want.";
   if (ts_.empty()) {
-    return std::nullopt;
+    std::optional<std::optional<std::tuple<distributed_clock::time_point,
+                                           std::vector<logger::BootTimestamp>>>>
+        result;
+    result.emplace(std::nullopt);
+    return result;
   }
   auto result = ts_.front();
   ts_.pop_front();