Add channel method to fetchers and senders.

This makes it easy to figure out which channel a fetcher or sender
is connected to.

Also add a test to confirm that the channel pointer points to a channel
inside configuration() for the event loop.

Change-Id: Iee0edca66394ef825dac482d7e3f568c6ed3441f
diff --git a/aos/events/BUILD b/aos/events/BUILD
index 3b3fb52..53b3b05 100644
--- a/aos/events/BUILD
+++ b/aos/events/BUILD
@@ -34,7 +34,10 @@
 
 cc_library(
     name = "event_loop",
-    srcs = ["event_loop_tmpl.h"],
+    srcs = [
+        "event_loop.cc",
+        "event_loop_tmpl.h",
+    ],
     hdrs = [
         "event_loop.h",
     ],
diff --git a/aos/events/event_loop.cc b/aos/events/event_loop.cc
new file mode 100644
index 0000000..6891f92
--- /dev/null
+++ b/aos/events/event_loop.cc
@@ -0,0 +1,18 @@
+#include "aos/events/event_loop.h"
+
+#include "aos/configuration.h"
+#include "aos/configuration_generated.h"
+#include "glog/logging.h"
+
+namespace aos {
+
+void EventLoop::ValidateChannel(const Channel *channel) {
+  CHECK(configuration_->channels() != nullptr) << ": No channels";
+
+  CHECK(std::find(configuration_->channels()->begin(),
+                  configuration_->channels()->end(),
+                  channel) != configuration_->channels()->end())
+      << ": Channel pointer not found in configuration()->channels()";
+}
+
+}  // namespace aos
diff --git a/aos/events/event_loop.h b/aos/events/event_loop.h
index f614517..278fc9c 100644
--- a/aos/events/event_loop.h
+++ b/aos/events/event_loop.h
@@ -34,7 +34,7 @@
 // fetchers.
 class RawFetcher {
  public:
-  RawFetcher() {}
+  RawFetcher(const Channel *channel) : channel_(channel) {}
   virtual ~RawFetcher() {}
 
   // Non-blocking fetch of the next message in the queue. Returns true if there
@@ -50,19 +50,22 @@
 
   const Context &context() const { return context_; }
 
+  const Channel *channel() const { return channel_; }
+
  protected:
   RawFetcher(const RawFetcher &) = delete;
   RawFetcher &operator=(const RawFetcher &) = delete;
 
   void *data_ = nullptr;
   Context context_;
+  const Channel *channel_;
 };
 
 // Raw version of sender.  Sends a block of data.  This is used for reflection
 // and as a building block to implement typed senders.
 class RawSender {
  public:
-  RawSender() {}
+  RawSender(const Channel *channel) : channel_(channel) {}
   virtual ~RawSender() {}
 
   // Sends a message without copying it.  The users starts by copying up to
@@ -78,9 +81,13 @@
   // Returns the name of this sender.
   virtual const absl::string_view name() const = 0;
 
+  const Channel *channel() const { return channel_; }
+
  protected:
   RawSender(const RawSender &) = delete;
   RawSender &operator=(const RawSender &) = delete;
+
+  const Channel *channel_;
 };
 
 
@@ -306,11 +313,14 @@
   // Returns the configuration that this event loop was built with.
   const Configuration *configuration() const { return configuration_; }
 
+  // Will send new messages from channel (path, type).
+  virtual std::unique_ptr<RawSender> MakeRawSender(const Channel *channel) = 0;
+
  protected:
   void set_is_running(bool value) { is_running_.store(value); }
 
-  // Will send new messages from channel (path, type).
-  virtual std::unique_ptr<RawSender> MakeRawSender(const Channel *channel) = 0;
+  // Validates that channel exists inside configuration_.
+  void ValidateChannel(const Channel *channel);
 
  private:
   ::std::atomic<bool> is_running_{false};
diff --git a/aos/events/event_loop_param_test.cc b/aos/events/event_loop_param_test.cc
index 8a0f9b6..3cace56 100644
--- a/aos/events/event_loop_param_test.cc
+++ b/aos/events/event_loop_param_test.cc
@@ -6,8 +6,9 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
-#include "glog/logging.h"
 #include "aos/events/test_message_generated.h"
+#include "aos/flatbuffer_merge.h"
+#include "glog/logging.h"
 
 namespace aos {
 namespace testing {
@@ -535,6 +536,31 @@
   EXPECT_EQ(iteration_list.size(), 3);
 }
 
+// Verifies that the event loop implementations detect when Channel is not a
+// pointer into confguration()
+TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
+  auto loop = MakePrimary();
+
+  const Channel *channel = loop->configuration()->channels()->Get(0);
+
+  FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
+
+  EXPECT_DEATH(
+      { loop->MakeRawSender(&channel_copy.message()); },
+      "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
+
+  EXPECT_DEATH(
+      { loop->MakeRawFetcher(&channel_copy.message()); },
+      "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
+
+  EXPECT_DEATH(
+      {
+        loop->MakeRawWatcher(&channel_copy.message(),
+                             [](const Context, const void *) {});
+      },
+      "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
+}
+
 // Verify that the send time on a message is roughly right.
 TEST_P(AbstractEventLoopTest, MessageSendTime) {
   auto loop1 = MakePrimary();
diff --git a/aos/events/shm_event_loop.cc b/aos/events/shm_event_loop.cc
index 5a88717..7506954 100644
--- a/aos/events/shm_event_loop.cc
+++ b/aos/events/shm_event_loop.cc
@@ -144,7 +144,8 @@
 class ShmFetcher : public RawFetcher {
  public:
   explicit ShmFetcher(const Channel *channel)
-      : lockless_queue_memory_(channel),
+      : RawFetcher(channel),
+        lockless_queue_memory_(channel),
         lockless_queue_(lockless_queue_memory_.memory(),
                         lockless_queue_memory_.config()),
         data_storage_(static_cast<AlignedChar *>(aligned_alloc(
@@ -273,7 +274,7 @@
 class ShmSender : public RawSender {
  public:
   explicit ShmSender(const Channel *channel, const ShmEventLoop *shm_event_loop)
-      : RawSender(),
+      : RawSender(channel),
         shm_event_loop_(shm_event_loop),
         name_(channel->name()->str()),
         lockless_queue_memory_(channel),
@@ -449,11 +450,13 @@
 
 ::std::unique_ptr<RawFetcher> ShmEventLoop::MakeRawFetcher(
     const Channel *channel) {
+  ValidateChannel(channel);
   return ::std::unique_ptr<RawFetcher>(new ShmFetcher(channel));
 }
 
 ::std::unique_ptr<RawSender> ShmEventLoop::MakeRawSender(
     const Channel *channel) {
+  ValidateChannel(channel);
   Take(channel);
   return ::std::unique_ptr<RawSender>(new ShmSender(channel, this));
 }
@@ -461,6 +464,7 @@
 void ShmEventLoop::MakeRawWatcher(
     const Channel *channel,
     std::function<void(const Context &context, const void *message)> watcher) {
+  ValidateChannel(channel);
   Take(channel);
 
   ::std::unique_ptr<internal::WatcherState> state(
diff --git a/aos/events/simulated_event_loop.cc b/aos/events/simulated_event_loop.cc
index 9bc74d5..02270ce 100644
--- a/aos/events/simulated_event_loop.cc
+++ b/aos/events/simulated_event_loop.cc
@@ -98,7 +98,9 @@
 class SimulatedSender : public RawSender {
  public:
   SimulatedSender(SimulatedChannel *simulated_channel, EventLoop *event_loop)
-      : simulated_channel_(simulated_channel), event_loop_(event_loop) {}
+      : RawSender(simulated_channel->channel()),
+        simulated_channel_(simulated_channel),
+        event_loop_(event_loop) {}
   ~SimulatedSender() {}
 
   void *data() override {
@@ -156,7 +158,8 @@
 
 class SimulatedFetcher : public RawFetcher {
  public:
-  explicit SimulatedFetcher(SimulatedChannel *queue) : queue_(queue) {}
+  explicit SimulatedFetcher(SimulatedChannel *queue)
+      : RawFetcher(queue->channel()), queue_(queue) {}
   ~SimulatedFetcher() { queue_->UnregisterFetcher(this); }
 
   bool FetchNext() override {
@@ -393,18 +396,21 @@
 void SimulatedEventLoop::MakeRawWatcher(
     const Channel *channel,
     std::function<void(const Context &channel, const void *message)> watcher) {
+  ValidateChannel(channel);
   Take(channel);
   GetSimulatedChannel(channel)->MakeRawWatcher(watcher);
 }
 
 std::unique_ptr<RawSender> SimulatedEventLoop::MakeRawSender(
     const Channel *channel) {
+  ValidateChannel(channel);
   Take(channel);
   return GetSimulatedChannel(channel)->MakeRawSender(this);
 }
 
 std::unique_ptr<RawFetcher> SimulatedEventLoop::MakeRawFetcher(
     const Channel *channel) {
+  ValidateChannel(channel);
   return GetSimulatedChannel(channel)->MakeRawFetcher();
 }