Add fetcher-side utilities for constants code

This make it possible to use the ConstantsFetcher<> to actually get at
published constants easily.

Change-Id: Ib5a7b91ae69b91a221ecef36f1bdc117b89e9fc4
Signed-off-by: James Kuszmaul <jabukuszmaul+collab@gmail.com>
diff --git a/frc971/constants/constants_sender_test.cc b/frc971/constants/constants_sender_test.cc
index 3edc320..1441767 100644
--- a/frc971/constants/constants_sender_test.cc
+++ b/frc971/constants/constants_sender_test.cc
@@ -40,11 +40,10 @@
   ConstantSender<testdata::ConstantsData, testdata::ConstantsList> test971(
       constants_sender_event_loop_.get(),
       "frc971/constants/testdata/test_constants.json", "/constants");
-  test_event_loop->MakeWatcher("/constants",
-                               [](const testdata::ConstantsData &data) {
-                                 EXPECT_EQ(data.max_roller_voltage(), 12);
-                                 EXPECT_EQ(data.min_roller_voltage(), -12);
-                               });
+  ConstantsFetcher<testdata::ConstantsData> fetcher(test_event_loop.get());
+  EXPECT_EQ(fetcher.constants().max_roller_voltage(), 12);
+  EXPECT_EQ(fetcher.constants().min_roller_voltage(), -12);
+  // Ensure that the watcher in ConstantsFetcher never triggers.
   event_loop_factory_.RunFor(std::chrono::seconds(1));
 }
 
@@ -57,14 +56,42 @@
   ConstantSender<testdata::ConstantsData, testdata::ConstantsList> test971(
       constants_sender_event_loop_.get(),
       "frc971/constants/testdata/test_constants.json", 9971, "/constants");
-  test_event_loop->MakeWatcher("/constants",
-                               [](const testdata::ConstantsData &data) {
-                                 EXPECT_EQ(data.max_roller_voltage(), 6);
-                                 EXPECT_EQ(data.min_roller_voltage(), -6);
-                               });
+  ConstantsFetcher<testdata::ConstantsData> fetcher(test_event_loop.get());
+  EXPECT_EQ(fetcher.constants().max_roller_voltage(), 6);
+  EXPECT_EQ(fetcher.constants().min_roller_voltage(), -6);
   event_loop_factory_.RunFor(std::chrono::seconds(1));
 }
 
+// Tests that the ConstantsFetcher dies when there is no data available during
+// construction.
+TEST_F(ConstantSenderTest, NoDataOnStartup) {
+  std::unique_ptr<aos::EventLoop> test_event_loop =
+      event_loop_factory_.MakeEventLoop("constants");
+  EXPECT_DEATH(ConstantsFetcher<testdata::ConstantsData>(test_event_loop.get()),
+               "information must be available at startup");
+}
+
+// Tests that the ConstantsFetcher dies when there is a change to the constants
+// data.
+TEST_F(ConstantSenderTest, DieOnDataUpdate) {
+  std::unique_ptr<aos::EventLoop> test_event_loop =
+      event_loop_factory_.MakeEventLoop("constants");
+  ConstantSender<testdata::ConstantsData, testdata::ConstantsList> test971(
+      constants_sender_event_loop_.get(),
+      "frc971/constants/testdata/test_constants.json", 9971, "/constants");
+  ConstantsFetcher<testdata::ConstantsData> fetcher(test_event_loop.get());
+  auto sender =
+      constants_sender_event_loop_->MakeSender<testdata::ConstantsData>(
+          "/constants");
+  constants_sender_event_loop_->OnRun([&sender]() {
+      auto builder = sender.MakeBuilder();
+      builder.CheckOk(builder.Send(
+          builder.MakeBuilder<testdata::ConstantsData>().Finish()));
+      });
+  EXPECT_DEATH(event_loop_factory_.RunFor(std::chrono::seconds(1)),
+               "changes to constants");
+}
+
 // When given a team number that it not recognized we kill the program.
 
 TEST_F(ConstantSenderTest, TeamNotFound) {