Add SendJson to AOS Sender

It is proven to be useful for writing tests

Change-Id: Ic98419de581ce2d2ea3cf4552bd461e02296fb77
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
diff --git a/aos/events/event_loop.h b/aos/events/event_loop.h
index 1ff0fb7..ac43acb 100644
--- a/aos/events/event_loop.h
+++ b/aos/events/event_loop.h
@@ -506,6 +506,16 @@
   // the buffer the caller can fill out.
   int buffer_index() const { return CHECK_NOTNULL(sender_)->buffer_index(); }
 
+  // Convenience function to build and send a message created from JSON
+  // representation.
+  RawSender::Error SendJson(std::string_view json) {
+    auto builder = MakeBuilder();
+    flatbuffers::Offset<T> json_offset =
+        aos::JsonToFlatbuffer<T>(json, builder.fbb());
+    CHECK(!json_offset.IsNull()) << ": Invalid JSON";
+    return builder.Send(json_offset);
+  }
+
  private:
   friend class EventLoop;
   Sender(std::unique_ptr<RawSender> sender) : sender_(std::move(sender)) {}
diff --git a/aos/events/event_loop_param_test.cc b/aos/events/event_loop_param_test.cc
index 3fb9e9a..f4f2fcc 100644
--- a/aos/events/event_loop_param_test.cc
+++ b/aos/events/event_loop_param_test.cc
@@ -162,6 +162,29 @@
   EXPECT_EQ(fetcher->value(), 200);
 }
 
+// Tests that fetcher can receive messages from a sender, sent via SendJson.
+TEST_P(AbstractEventLoopTest, BasicSendJson) {
+  auto loop1 = Make();
+  auto loop2 = MakePrimary();
+
+  aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
+  sender.CheckOk(sender.SendJson(R"json({"value":201})json"));
+
+  auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
+  ASSERT_TRUE(fetcher.Fetch());
+  EXPECT_EQ(fetcher->value(), 201);
+}
+
+// Tests that invalid JSON isn't sent.
+TEST_P(AbstractEventLoopDeathTest, InvalidSendJson) {
+  auto loop1 = Make();
+  auto loop2 = MakePrimary();
+
+  aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
+  EXPECT_DEATH({ sender.CheckOk(sender.SendJson(R"json({"val)json")); },
+               "Invalid JSON");
+}
+
 // Verifies that a no-arg watcher will not have a data pointer.
 TEST_P(AbstractEventLoopTest, NoArgNoData) {
   auto loop1 = Make();