Add and test TryMakeFetcher, TryMakeSender, and NodeHasTag helpers

Using a Fetcher for a channel on nodes where it exists and triggering
logic to handle other nodes based on whether the fetcher is valid works
well for some use cases. Add a method to EventLoop to support that
directly, instead of forcing the caller to redo the logic around whether
a channel exists and is readable. Basing similar logic off whether the
node has a given tag is also fairly common.

In the process, fill out the EventLoop tests around channels that don't
exist or aren't readable/writable a bit better.

Change-Id: I168e3c1e98adc4461a01d98360f0f0a78d24bbb5
Signed-off-by: Brian Silverman <brian.silverman@bluerivertech.com>
diff --git a/aos/configuration.cc b/aos/configuration.cc
index e9c7160..d6394bb 100644
--- a/aos/configuration.cc
+++ b/aos/configuration.cc
@@ -1133,6 +1133,18 @@
   return nodes;
 }
 
+bool NodeHasTag(const Node *node, std::string_view tag) {
+  if (node == nullptr) {
+    return true;
+  }
+
+  const auto *const tags = node->tags();
+  return std::find_if(tags->begin(), tags->end(),
+                      [tag](const flatbuffers::String *candidate) {
+                        return candidate->string_view() == tag;
+                      }) != tags->end();
+}
+
 bool MultiNode(const Configuration *config) { return config->has_nodes(); }
 
 bool ChannelIsSendableOnNode(const Channel *channel, const Node *node) {