Add version string to AOS timing report

This sets us up to more readily indicate what version of an application
crashed when the starter observes an application crash. This also will
help us to identify situations where there are mixed versions of
binaries on sprayers.

Change-Id: I4d265552d6c3cadd43b834f343da50aec46be4ef
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
diff --git a/aos/events/event_loop_param_test.cc b/aos/events/event_loop_param_test.cc
index ba2d426..c861284 100644
--- a/aos/events/event_loop_param_test.cc
+++ b/aos/events/event_loop_param_test.cc
@@ -1488,6 +1488,84 @@
   }
 }
 
+// Test that setting a default version string results in it getting populated
+// correctly.
+TEST_P(AbstractEventLoopTest, DefaultVersionStringInTimingReport) {
+  gflags::FlagSaver flag_saver;
+  FLAGS_timing_report_ms = 1000;
+
+  EventLoop::SetDefaultVersionString("default_version_string");
+
+  auto loop = MakePrimary();
+
+  Fetcher<timing::Report> report_fetcher =
+      loop->MakeFetcher<timing::Report>("/aos");
+
+  TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
+  loop->OnRun([exit_timer, &loop, &report_fetcher]() {
+    report_fetcher.Fetch();
+    exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
+  });
+
+  Run();
+
+  bool found_primary_report = false;
+  while (report_fetcher.FetchNext()) {
+    if (report_fetcher->name()->string_view() == "primary") {
+      found_primary_report = true;
+      EXPECT_EQ("default_version_string",
+                report_fetcher->version()->string_view());
+    } else {
+      FAIL() << report_fetcher->name()->string_view();
+    }
+  }
+
+  if (do_timing_reports() == DoTimingReports::kYes) {
+    EXPECT_TRUE(found_primary_report);
+  } else {
+    EXPECT_FALSE(found_primary_report);
+  }
+}
+
+// Test that overriding the default version string results in it getting
+// populated correctly.
+TEST_P(AbstractEventLoopTest, OverrideDersionStringInTimingReport) {
+  gflags::FlagSaver flag_saver;
+  FLAGS_timing_report_ms = 1000;
+
+  EventLoop::SetDefaultVersionString("default_version_string");
+
+  auto loop = MakePrimary();
+  loop->SetVersionString("override_version");
+
+  Fetcher<timing::Report> report_fetcher =
+      loop->MakeFetcher<timing::Report>("/aos");
+
+  TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
+  loop->OnRun([exit_timer, &loop, &report_fetcher]() {
+    report_fetcher.Fetch();
+    exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
+  });
+
+  Run();
+
+  bool found_primary_report = false;
+  while (report_fetcher.FetchNext()) {
+    if (report_fetcher->name()->string_view() == "primary") {
+      found_primary_report = true;
+      EXPECT_EQ("override_version", report_fetcher->version()->string_view());
+    } else {
+      FAIL() << report_fetcher->name()->string_view();
+    }
+  }
+
+  if (do_timing_reports() == DoTimingReports::kYes) {
+    EXPECT_TRUE(found_primary_report);
+  } else {
+    EXPECT_FALSE(found_primary_report);
+  }
+}
+
 // Verify that we can change a timer's parameters during execution.
 TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
   auto loop = MakePrimary();
@@ -3409,6 +3487,19 @@
                "May only send the buffer detached from this Sender");
 }
 
+// Tests that senders fail when created on the wrong node.
+TEST_P(AbstractEventLoopDeathTest, SetVersionWhileRunning) {
+  auto loop1 = MakePrimary();
+
+  loop1->OnRun([&loop1, this]() {
+    EXPECT_DEATH({ loop1->SetVersionString("abcdef"); },
+                 "timing report while running");
+    Exit();
+  });
+
+  Run();
+}
+
 int TestChannelFrequency(EventLoop *event_loop) {
   return event_loop->GetChannel<TestMessage>("/test")->frequency();
 }