blob: 242ee17a02f17bec359c91c2beb046937356f5f8 [file] [log] [blame]
Austin Schuhcb108412019-10-13 16:09:54 -07001#include "aos/configuration.h"
2
3#include "absl/strings/strip.h"
4#include "aos/json_to_flatbuffer.h"
Austin Schuh1ef01ef2021-02-07 20:40:36 -08005#include "aos/testing/flatbuffer_eq.h"
Austin Schuh373f1762021-06-02 21:07:09 -07006#include "aos/testing/path.h"
Austin Schuhcb108412019-10-13 16:09:54 -07007#include "aos/testing/test_logging.h"
8#include "aos/util/file.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -07009#include "flatbuffers/reflection.h"
10#include "glog/logging.h"
Austin Schuhe84c3ed2019-12-14 15:29:48 -080011#include "gmock/gmock.h"
Austin Schuh1ef01ef2021-02-07 20:40:36 -080012#include "gtest/gtest.h"
Austin Schuhcb108412019-10-13 16:09:54 -070013
14namespace aos {
15namespace configuration {
16namespace testing {
17
Austin Schuh373f1762021-06-02 21:07:09 -070018using aos::testing::ArtifactPath;
Austin Schuh66602132020-02-28 13:38:37 -080019
Austin Schuhcb108412019-10-13 16:09:54 -070020class ConfigurationTest : public ::testing::Test {
21 public:
22 ConfigurationTest() { ::aos::testing::EnableTestLogging(); }
23};
24
25typedef ConfigurationTest ConfigurationDeathTest;
26
27// *the* expected location for all working tests.
Austin Schuh1ef01ef2021-02-07 20:40:36 -080028aos::FlatbufferDetachedBuffer<Channel> ExpectedLocation() {
29 return JsonToFlatbuffer<Channel>(
30 "{ \"name\": \"/foo\", \"type\": \".aos.bar\", \"max_size\": 5 }");
31}
32
Austin Schuhbca6cf02019-12-22 17:28:34 -080033// And for multinode setups
Austin Schuh1ef01ef2021-02-07 20:40:36 -080034aos::FlatbufferDetachedBuffer<Channel> ExpectedMultinodeLocation() {
35 return JsonToFlatbuffer<Channel>(
36 "{ \"name\": \"/foo\", \"type\": \".aos.bar\", \"max_size\": 5, "
37 "\"source_node\": \"pi1\" }");
38}
Austin Schuhcb108412019-10-13 16:09:54 -070039
40// Tests that we can read and merge a configuration.
41TEST_F(ConfigurationTest, ConfigMerge) {
Austin Schuh40485ed2019-10-26 21:51:44 -070042 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -070043 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Ravago Jonescf453ab2020-05-06 21:14:53 -070044 LOG(INFO) << "Read: " << FlatbufferToJson(config, {.multi_line = true});
Austin Schuhcb108412019-10-13 16:09:54 -070045
Austin Schuh373f1762021-06-02 21:07:09 -070046 EXPECT_EQ(absl::StripSuffix(util::ReadFileToStringOrDie(
47 ArtifactPath("aos/testdata/expected.json")),
48 "\n"),
49 FlatbufferToJson(config, {.multi_line = true}));
Austin Schuhcb108412019-10-13 16:09:54 -070050}
51
Austin Schuhc9e10ec2020-01-26 16:08:28 -080052// Tests that we can get back a ChannelIndex.
53TEST_F(ConfigurationTest, ChannelIndex) {
54 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -070055 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -080056
57 EXPECT_EQ(
58 ChannelIndex(&config.message(), config.message().channels()->Get(1u)),
59 1u);
60}
61
Austin Schuh217a9782019-12-21 23:02:50 -080062// Tests that we can read and merge a multinode configuration.
63TEST_F(ConfigurationTest, ConfigMergeMultinode) {
64 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -070065 ReadConfig(ArtifactPath("aos/testdata/config1_multinode.json"));
Ravago Jonescf453ab2020-05-06 21:14:53 -070066 LOG(INFO) << "Read: " << FlatbufferToJson(config, {.multi_line = true});
Austin Schuh217a9782019-12-21 23:02:50 -080067
Ravago Jonescf453ab2020-05-06 21:14:53 -070068 EXPECT_EQ(std::string(absl::StripSuffix(
Austin Schuh373f1762021-06-02 21:07:09 -070069 util::ReadFileToStringOrDie(
70 ArtifactPath("aos/testdata/expected_multinode.json")),
Ravago Jonescf453ab2020-05-06 21:14:53 -070071 "\n")),
72 FlatbufferToJson(config, {.multi_line = true}));
Austin Schuh217a9782019-12-21 23:02:50 -080073}
74
Alex Perrycb7da4b2019-08-28 19:35:56 -070075// Tests that we sort the entries in a config so we can look entries up.
76TEST_F(ConfigurationTest, UnsortedConfig) {
77 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -070078 ReadConfig(ArtifactPath("aos/testdata/backwards.json"));
Alex Perrycb7da4b2019-08-28 19:35:56 -070079
Ravago Jonescf453ab2020-05-06 21:14:53 -070080 LOG(INFO) << "Read: " << FlatbufferToJson(config, {.multi_line = true});
Alex Perrycb7da4b2019-08-28 19:35:56 -070081
Austin Schuhf1fff282020-03-28 16:57:32 -070082 EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/aos/robot_state",
Austin Schuhbca6cf02019-12-22 17:28:34 -080083 "aos.RobotState", "app1", nullptr)),
Austin Schuhf1fff282020-03-28 16:57:32 -070084 "{ \"name\": \"/aos/robot_state\", \"type\": \"aos.RobotState\", "
Alex Perrycb7da4b2019-08-28 19:35:56 -070085 "\"max_size\": 5 }");
86}
87
Austin Schuhcb108412019-10-13 16:09:54 -070088// Tests that we die when a file is imported twice.
89TEST_F(ConfigurationDeathTest, DuplicateFile) {
90 EXPECT_DEATH(
91 {
Austin Schuh40485ed2019-10-26 21:51:44 -070092 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -070093 ReadConfig(ArtifactPath("aos/testdata/config1_bad.json"));
Austin Schuhcb108412019-10-13 16:09:54 -070094 },
Austin Schuh373f1762021-06-02 21:07:09 -070095 "aos/testdata/config1_bad.json");
Austin Schuhcb108412019-10-13 16:09:54 -070096}
97
Milind Upadhyay17098ba2022-04-15 22:18:50 -070098// Tests that we die when we give an invalid path.
99TEST_F(ConfigurationDeathTest, NonexistentFile) {
100 EXPECT_DEATH(
101 {
102 FlatbufferDetachedBuffer<Configuration> config =
103 ReadConfig("nonexistent/config.json");
104 },
105 "above error");
106}
107
108// Tests that we return std::nullopt when we give an invalid path.
109TEST_F(ConfigurationTest, NonexistentFileOptional) {
110 std::optional<FlatbufferDetachedBuffer<Configuration>> config =
111 MaybeReadConfig("nonexistent/config.json");
112 EXPECT_FALSE(config.has_value());
113}
114
Austin Schuhf1fff282020-03-28 16:57:32 -0700115// Tests that we reject invalid channel names. This means any channels with //
116// in their name, a trailing /, or regex characters.
117TEST_F(ConfigurationDeathTest, InvalidChannelName) {
118 EXPECT_DEATH(
119 {
120 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700121 ReadConfig(ArtifactPath("aos/testdata/invalid_channel_name1.json"));
Austin Schuhf1fff282020-03-28 16:57:32 -0700122 },
123 "Channel names can't end with '/'");
124 EXPECT_DEATH(
125 {
126 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700127 ReadConfig(ArtifactPath("aos/testdata/invalid_channel_name2.json"));
Austin Schuhf1fff282020-03-28 16:57:32 -0700128 },
129 "Invalid channel name");
130 EXPECT_DEATH(
131 {
132 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700133 ReadConfig(ArtifactPath("aos/testdata/invalid_channel_name3.json"));
Austin Schuhf1fff282020-03-28 16:57:32 -0700134 LOG(FATAL) << "Foo";
135 },
136 "Invalid channel name");
137}
138
Austin Schuh8d6cea82020-02-28 12:17:16 -0800139// Tests that we can modify a config with a json snippet.
140TEST_F(ConfigurationTest, MergeWithConfig) {
141 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700142 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Ravago Jonescf453ab2020-05-06 21:14:53 -0700143 LOG(INFO) << "Read: " << FlatbufferToJson(config, {.multi_line = true});
Austin Schuh8d6cea82020-02-28 12:17:16 -0800144
145 FlatbufferDetachedBuffer<Configuration> updated_config =
146 MergeWithConfig(&config.message(),
147 R"channel({
148 "channels": [
149 {
150 "name": "/foo",
151 "type": ".aos.bar",
152 "max_size": 100
153 }
154 ]
155})channel");
156
Austin Schuh373f1762021-06-02 21:07:09 -0700157 EXPECT_EQ(absl::StripSuffix(util::ReadFileToStringOrDie(ArtifactPath(
158 "aos/testdata/expected_merge_with.json")),
Ravago Jonescf453ab2020-05-06 21:14:53 -0700159 "\n"),
160 FlatbufferToJson(updated_config, {.multi_line = true}));
Austin Schuh8d6cea82020-02-28 12:17:16 -0800161}
162
Austin Schuhcb108412019-10-13 16:09:54 -0700163// Tests that we can lookup a location, complete with maps, from a merged
164// config.
Austin Schuh40485ed2019-10-26 21:51:44 -0700165TEST_F(ConfigurationTest, GetChannel) {
166 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700167 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Austin Schuhcb108412019-10-13 16:09:54 -0700168
169 // Test a basic lookup first.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800170 EXPECT_THAT(GetChannel(config, "/foo", ".aos.bar", "app1", nullptr),
171 aos::testing::FlatbufferEq(ExpectedLocation()));
Austin Schuhcb108412019-10-13 16:09:54 -0700172
173 // Test that an invalid name results in nullptr back.
Austin Schuhbca6cf02019-12-22 17:28:34 -0800174 EXPECT_EQ(GetChannel(config, "/invalid_name", ".aos.bar", "app1", nullptr),
175 nullptr);
Austin Schuhcb108412019-10-13 16:09:54 -0700176
177 // Tests that a root map/rename works. And that they get processed from the
178 // bottom up.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800179 EXPECT_THAT(GetChannel(config, "/batman", ".aos.bar", "app1", nullptr),
180 aos::testing::FlatbufferEq(ExpectedLocation()));
Austin Schuhcb108412019-10-13 16:09:54 -0700181
182 // And then test that an application specific map/rename works.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800183 EXPECT_THAT(GetChannel(config, "/bar", ".aos.bar", "app1", nullptr),
184 aos::testing::FlatbufferEq(ExpectedLocation()));
185 EXPECT_THAT(GetChannel(config, "/baz", ".aos.bar", "app2", nullptr),
186 aos::testing::FlatbufferEq(ExpectedLocation()));
Austin Schuhcb108412019-10-13 16:09:54 -0700187
188 // And then test that an invalid application name gets properly ignored.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800189 EXPECT_THAT(GetChannel(config, "/foo", ".aos.bar", "app3", nullptr),
190 aos::testing::FlatbufferEq(ExpectedLocation()));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800191}
192
James Kuszmaulc8503f32022-06-25 16:17:12 -0700193// Tests that we can do reverse-lookups of channel names.
194TEST_F(ConfigurationTest, GetChannelAliases) {
195 FlatbufferDetachedBuffer<Configuration> config =
196 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
197
198 // Test a basic lookup first.
199 EXPECT_THAT(
200 GetChannelAliases(&config.message(), "/foo", ".aos.bar", "app1", nullptr),
201 ::testing::UnorderedElementsAre("/foo", "/batman", "/bar"));
202 EXPECT_THAT(
203 GetChannelAliases(&config.message(), "/bar", ".aos.bar", "app1", nullptr),
204 ::testing::UnorderedElementsAre("/batman", "/bar"));
205 EXPECT_THAT(GetChannelAliases(&config.message(), "/batman", ".aos.bar",
206 "app1", nullptr),
207 ::testing::UnorderedElementsAre("/batman"));
208 // /bar (deliberately) does not get included because of the ordering in the
209 // map.
210 EXPECT_THAT(
211 GetChannelAliases(&config.message(), "/foo", ".aos.bar", "", nullptr),
212 ::testing::UnorderedElementsAre("/foo", "/batman"));
213 EXPECT_THAT(
214 GetChannelAliases(&config.message(), "/foo", ".aos.bar", "app2", nullptr),
215 ::testing::UnorderedElementsAre("/foo", "/batman", "/baz"));
216}
217
Austin Schuhbca6cf02019-12-22 17:28:34 -0800218// Tests that we can lookup a location with node specific maps.
219TEST_F(ConfigurationTest, GetChannelMultinode) {
220 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700221 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800222 const Node *pi1 = GetNode(&config.message(), "pi1");
223 const Node *pi2 = GetNode(&config.message(), "pi2");
224
225 // Test a basic lookup first.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800226 EXPECT_THAT(GetChannel(config, "/foo", ".aos.bar", "app1", pi1),
227 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
228 EXPECT_THAT(GetChannel(config, "/foo", ".aos.bar", "app1", pi2),
229 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800230
231 // Tests that a root map/rename works with a node specific map.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800232 EXPECT_THAT(GetChannel(config, "/batman", ".aos.bar", "app1", pi1),
233 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800234
235 // Tests that a root map/rename fails with a node specific map for the wrong
236 // node.
237 EXPECT_EQ(GetChannel(config, "/batman", ".aos.bar", "app1", pi2), nullptr);
238
239 // And then test that an application specific map/rename works.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800240 EXPECT_THAT(GetChannel(config, "/batman2", ".aos.bar", "app1", pi1),
241 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
242 EXPECT_THAT(GetChannel(config, "/batman3", ".aos.bar", "app1", pi1),
243 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800244
245 // And then that it fails when the node changes.
246 EXPECT_EQ(GetChannel(config, "/batman3", ".aos.bar", "app1", pi2), nullptr);
247}
248
James Kuszmaulc8503f32022-06-25 16:17:12 -0700249// Tests that reverse channel lookup on a multi-node config (including with
250// wildcards) works.
251TEST_F(ConfigurationTest, GetChannelAliasesMultinode) {
252 FlatbufferDetachedBuffer<Configuration> config =
253 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
254
255 const Node *pi1 = GetNode(&config.message(), "pi1");
256 const Node *pi2 = GetNode(&config.message(), "pi2");
257
258 EXPECT_THAT(
259 GetChannelAliases(&config.message(), "/foo", ".aos.bar", "app1", pi1),
260 ::testing::UnorderedElementsAre("/foo", "/batman", "/batman2", "/batman3",
261 "/magic/string"));
262
263 EXPECT_THAT(
264 GetChannelAliases(&config.message(), "/foo", ".aos.baz", "app1", pi1),
265 ::testing::UnorderedElementsAre("/foo", "/batman3", "/magic/string"));
266
267 EXPECT_THAT(
268 GetChannelAliases(&config.message(), "/foo/testing", ".aos.bar", "", pi1),
269 ::testing::UnorderedElementsAre("/foo/testing", "/magic/string/testing"));
270
271 EXPECT_THAT(
272 GetChannelAliases(&config.message(), "/foo/testing", ".aos.bar", "app1",
273 pi2),
274 ::testing::UnorderedElementsAre("/foo/testing", "/magic/string/testing"));
275}
276
Austin Schuhbca6cf02019-12-22 17:28:34 -0800277// Tests that we can lookup a location with type specific maps.
278TEST_F(ConfigurationTest, GetChannelTypedMultinode) {
279 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700280 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800281 const Node *pi1 = GetNode(&config.message(), "pi1");
282
283 // Test a basic lookup first.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800284 EXPECT_THAT(GetChannel(config, "/batman", ".aos.bar", "app1", pi1),
285 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800286
287 // Now confirm that a second message on the same name doesn't get remapped.
288 const char *kExpectedBazMultinodeLocation =
289 "{ \"name\": \"/batman\", \"type\": \".aos.baz\", \"max_size\": 5, "
290 "\"source_node\": \"pi1\" }";
291 EXPECT_EQ(
292 FlatbufferToJson(GetChannel(config, "/batman", ".aos.baz", "app1", pi1)),
293 kExpectedBazMultinodeLocation);
Austin Schuhcb108412019-10-13 16:09:54 -0700294}
295
Austin Schuhf1fff282020-03-28 16:57:32 -0700296// Tests that we can lookup a location with a glob
297TEST_F(ConfigurationTest, GetChannelGlob) {
298 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700299 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhf1fff282020-03-28 16:57:32 -0700300 const Node *pi1 = GetNode(&config.message(), "pi1");
301
302 // Confirm that a glob with nothing after it matches.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800303 EXPECT_THAT(GetChannel(config, "/magic/string", ".aos.bar", "app7", pi1),
304 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
Austin Schuhf1fff282020-03-28 16:57:32 -0700305
306 // Now confirm that glob with something following it matches and renames
307 // correctly.
308 const char *kExpectedSubfolderMultinodeLocation =
309 "{ \"name\": \"/foo/subfolder\", \"type\": \".aos.bar\", \"max_size\": "
310 "5, \"source_node\": \"pi1\" }";
311 EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/magic/string/subfolder",
312 ".aos.bar", "app7", pi1)),
313 kExpectedSubfolderMultinodeLocation);
314}
315
Austin Schuh217a9782019-12-21 23:02:50 -0800316// Tests that we reject a configuration which has a nodes list, but has channels
317// withoout source_node filled out.
318TEST_F(ConfigurationDeathTest, InvalidSourceNode) {
319 EXPECT_DEATH(
320 {
321 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700322 ReadConfig(ArtifactPath("aos/testdata/invalid_nodes.json"));
Austin Schuh217a9782019-12-21 23:02:50 -0800323 },
324 "source_node");
325
326 EXPECT_DEATH(
327 {
328 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700329 ReadConfig(ArtifactPath("aos/testdata/invalid_source_node.json"));
Austin Schuh217a9782019-12-21 23:02:50 -0800330 },
331 "source_node");
332
333 EXPECT_DEATH(
334 {
Austin Schuh373f1762021-06-02 21:07:09 -0700335 FlatbufferDetachedBuffer<Configuration> config = ReadConfig(
336 ArtifactPath("aos/testdata/invalid_destination_node.json"));
Austin Schuh217a9782019-12-21 23:02:50 -0800337 },
338 "destination_nodes");
339
340 EXPECT_DEATH(
341 {
342 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700343 ReadConfig(ArtifactPath("aos/testdata/self_forward.json"));
Austin Schuh217a9782019-12-21 23:02:50 -0800344 },
345 "forwarding data to itself");
346}
347
348// Tests that our node writeable helpers work as intended.
349TEST_F(ConfigurationTest, ChannelIsSendableOnNode) {
350 FlatbufferDetachedBuffer<Channel> good_channel(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800351 R"channel({
Austin Schuh217a9782019-12-21 23:02:50 -0800352 "name": "/test",
353 "type": "aos.examples.Ping",
354 "source_node": "foo"
355})channel",
356 Channel::MiniReflectTypeTable()));
357
358 FlatbufferDetachedBuffer<Channel> bad_channel(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800359 R"channel({
Austin Schuh217a9782019-12-21 23:02:50 -0800360 "name": "/test",
361 "type": "aos.examples.Ping",
362 "source_node": "bar"
363})channel",
364 Channel::MiniReflectTypeTable()));
365
366 FlatbufferDetachedBuffer<Node> node(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800367 R"node({
Austin Schuh217a9782019-12-21 23:02:50 -0800368 "name": "foo"
369})node",
370 Node::MiniReflectTypeTable()));
371
372 EXPECT_TRUE(
373 ChannelIsSendableOnNode(&good_channel.message(), &node.message()));
374 EXPECT_FALSE(
375 ChannelIsSendableOnNode(&bad_channel.message(), &node.message()));
376}
377
378// Tests that our node readable and writeable helpers work as intended.
379TEST_F(ConfigurationTest, ChannelIsReadableOnNode) {
380 FlatbufferDetachedBuffer<Channel> good_channel(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800381 R"channel({
Austin Schuh217a9782019-12-21 23:02:50 -0800382 "name": "/test",
383 "type": "aos.examples.Ping",
384 "source_node": "bar",
385 "destination_nodes": [
Austin Schuh719946b2019-12-28 14:51:01 -0800386 {
387 "name": "baz"
388 },
389 {
390 "name": "foo"
391 }
Austin Schuh217a9782019-12-21 23:02:50 -0800392 ]
393})channel",
394 Channel::MiniReflectTypeTable()));
395
396 FlatbufferDetachedBuffer<Channel> bad_channel1(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800397 R"channel({
Austin Schuh217a9782019-12-21 23:02:50 -0800398 "name": "/test",
399 "type": "aos.examples.Ping",
400 "source_node": "bar"
401})channel",
402 Channel::MiniReflectTypeTable()));
403
404 FlatbufferDetachedBuffer<Channel> bad_channel2(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800405 R"channel({
Austin Schuh217a9782019-12-21 23:02:50 -0800406 "name": "/test",
407 "type": "aos.examples.Ping",
408 "source_node": "bar",
409 "destination_nodes": [
Austin Schuh719946b2019-12-28 14:51:01 -0800410 {
411 "name": "baz"
412 }
Austin Schuh217a9782019-12-21 23:02:50 -0800413 ]
414})channel",
415 Channel::MiniReflectTypeTable()));
416
417 FlatbufferDetachedBuffer<Node> node(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800418 R"node({
Austin Schuh217a9782019-12-21 23:02:50 -0800419 "name": "foo"
420})node",
421 Node::MiniReflectTypeTable()));
422
423 EXPECT_TRUE(
424 ChannelIsReadableOnNode(&good_channel.message(), &node.message()));
425 EXPECT_FALSE(
426 ChannelIsReadableOnNode(&bad_channel1.message(), &node.message()));
427 EXPECT_FALSE(
428 ChannelIsReadableOnNode(&bad_channel2.message(), &node.message()));
429}
430
Austin Schuh719946b2019-12-28 14:51:01 -0800431// Tests that our node message is logged helpers work as intended.
432TEST_F(ConfigurationTest, ChannelMessageIsLoggedOnNode) {
433 FlatbufferDetachedBuffer<Channel> logged_on_self_channel(JsonToFlatbuffer(
434 R"channel({
435 "name": "/test",
436 "type": "aos.examples.Ping",
437 "source_node": "bar",
438 "destination_nodes": [
439 {
440 "name": "baz"
441 }
442 ]
443})channel",
444 Channel::MiniReflectTypeTable()));
Austin Schuh217a9782019-12-21 23:02:50 -0800445
Austin Schuh719946b2019-12-28 14:51:01 -0800446 FlatbufferDetachedBuffer<Channel> not_logged_channel(JsonToFlatbuffer(
447 R"channel({
448 "name": "/test",
449 "type": "aos.examples.Ping",
450 "source_node": "bar",
451 "logger": "NOT_LOGGED",
452 "destination_nodes": [
453 {
454 "name": "baz",
455 "timestamp_logger": "LOCAL_LOGGER"
456 }
457 ]
458})channel",
459 Channel::MiniReflectTypeTable()));
460
461 FlatbufferDetachedBuffer<Channel> logged_on_remote_channel(JsonToFlatbuffer(
462 R"channel({
463 "name": "/test",
464 "type": "aos.examples.Ping",
465 "source_node": "bar",
466 "logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700467 "logger_nodes": ["baz"],
Austin Schuh719946b2019-12-28 14:51:01 -0800468 "destination_nodes": [
469 {
470 "name": "baz"
471 }
472 ]
473})channel",
474 Channel::MiniReflectTypeTable()));
475
476 FlatbufferDetachedBuffer<Channel> logged_on_separate_logger_node_channel(
477 JsonToFlatbuffer(
478 R"channel({
479 "name": "/test",
480 "type": "aos.examples.Ping",
481 "source_node": "bar",
482 "logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700483 "logger_nodes": ["foo"],
Austin Schuh719946b2019-12-28 14:51:01 -0800484 "destination_nodes": [
485 {
486 "name": "baz"
487 }
488 ]
489})channel",
490 Channel::MiniReflectTypeTable()));
491
Ravago Jonescf453ab2020-05-06 21:14:53 -0700492 FlatbufferDetachedBuffer<Channel> logged_on_both_channel(JsonToFlatbuffer(
493 R"channel({
Austin Schuh719946b2019-12-28 14:51:01 -0800494 "name": "/test",
495 "type": "aos.examples.Ping",
496 "source_node": "bar",
497 "logger": "LOCAL_AND_REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700498 "logger_nodes": ["baz"],
Austin Schuh719946b2019-12-28 14:51:01 -0800499 "destination_nodes": [
500 {
501 "name": "baz"
502 }
503 ]
504})channel",
Ravago Jonescf453ab2020-05-06 21:14:53 -0700505 Channel::MiniReflectTypeTable()));
Austin Schuh719946b2019-12-28 14:51:01 -0800506
507 FlatbufferDetachedBuffer<Node> foo_node(JsonToFlatbuffer(
508 R"node({
509 "name": "foo"
510})node",
511 Node::MiniReflectTypeTable()));
512
513 FlatbufferDetachedBuffer<Node> bar_node(JsonToFlatbuffer(
514 R"node({
515 "name": "bar"
516})node",
517 Node::MiniReflectTypeTable()));
518
519 FlatbufferDetachedBuffer<Node> baz_node(JsonToFlatbuffer(
520 R"node({
521 "name": "baz"
522})node",
523 Node::MiniReflectTypeTable()));
524
525 // Local logger.
526 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&logged_on_self_channel.message(),
527 &foo_node.message()));
528 EXPECT_TRUE(ChannelMessageIsLoggedOnNode(&logged_on_self_channel.message(),
529 &bar_node.message()));
530 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&logged_on_self_channel.message(),
531 &baz_node.message()));
Austin Schuh48e94502021-06-18 18:35:53 -0700532 EXPECT_TRUE(
533 ChannelMessageIsLoggedOnNode(&logged_on_self_channel.message(), nullptr));
Austin Schuh719946b2019-12-28 14:51:01 -0800534
535 // No logger.
536 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&not_logged_channel.message(),
537 &foo_node.message()));
538 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&not_logged_channel.message(),
Ravago Jonescf453ab2020-05-06 21:14:53 -0700539 &bar_node.message()));
Austin Schuh719946b2019-12-28 14:51:01 -0800540 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&not_logged_channel.message(),
541 &baz_node.message()));
Austin Schuh48e94502021-06-18 18:35:53 -0700542 EXPECT_FALSE(
543 ChannelMessageIsLoggedOnNode(&not_logged_channel.message(), nullptr));
Austin Schuh719946b2019-12-28 14:51:01 -0800544
545 // Remote logger.
546 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&logged_on_remote_channel.message(),
547 &foo_node.message()));
548 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&logged_on_remote_channel.message(),
549 &bar_node.message()));
550 EXPECT_TRUE(ChannelMessageIsLoggedOnNode(&logged_on_remote_channel.message(),
551 &baz_node.message()));
552
553 // Separate logger.
554 EXPECT_TRUE(ChannelMessageIsLoggedOnNode(
555 &logged_on_separate_logger_node_channel.message(), &foo_node.message()));
556 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(
557 &logged_on_separate_logger_node_channel.message(), &bar_node.message()));
558 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(
559 &logged_on_separate_logger_node_channel.message(), &baz_node.message()));
560
561 // Logged in multiple places.
562 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&logged_on_both_channel.message(),
563 &foo_node.message()));
564 EXPECT_TRUE(ChannelMessageIsLoggedOnNode(&logged_on_both_channel.message(),
565 &bar_node.message()));
566 EXPECT_TRUE(ChannelMessageIsLoggedOnNode(&logged_on_both_channel.message(),
567 &baz_node.message()));
568}
569
Austin Schuh48e94502021-06-18 18:35:53 -0700570// Tests that our node message is logged helpers work as intended.
571TEST_F(ConfigurationDeathTest, ChannelMessageIsLoggedOnNode) {
572 FlatbufferDetachedBuffer<Channel> logged_on_both_channel(JsonToFlatbuffer(
573 R"channel({
574 "name": "/test",
575 "type": "aos.examples.Ping",
576 "source_node": "bar",
577 "logger": "LOCAL_AND_REMOTE_LOGGER",
578 "logger_nodes": ["baz"],
579 "destination_nodes": [
580 {
581 "name": "baz"
582 }
583 ]
584})channel",
585 Channel::MiniReflectTypeTable()));
586
587 FlatbufferDetachedBuffer<Channel> logged_on_separate_logger_node_channel(
588 JsonToFlatbuffer(
589 R"channel({
590 "name": "/test",
591 "type": "aos.examples.Ping",
592 "source_node": "bar",
593 "logger": "REMOTE_LOGGER",
594 "logger_nodes": ["foo"],
595 "destination_nodes": [
596 {
597 "name": "baz"
598 }
599 ]
600})channel",
601 Channel::MiniReflectTypeTable()));
602
603 EXPECT_DEATH(
604 {
605 ChannelMessageIsLoggedOnNode(&logged_on_both_channel.message(),
606 nullptr);
607 },
608 "Unsupported logging configuration in a single node world");
609 EXPECT_DEATH(
610 {
611 ChannelMessageIsLoggedOnNode(
612 &logged_on_separate_logger_node_channel.message(), nullptr);
613 },
614 "Unsupported logging configuration in a single node world");
615}
616
Austin Schuh719946b2019-12-28 14:51:01 -0800617// Tests that our forwarding timestamps are logged helpers work as intended.
618TEST_F(ConfigurationTest, ConnectionDeliveryTimeIsLoggedOnNode) {
619 FlatbufferDetachedBuffer<Channel> logged_on_self_channel(JsonToFlatbuffer(
620 R"channel({
621 "name": "/test",
622 "type": "aos.examples.Ping",
623 "source_node": "bar",
624 "logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700625 "logger_nodes": ["baz"],
Austin Schuh719946b2019-12-28 14:51:01 -0800626 "destination_nodes": [
627 {
628 "name": "baz"
629 }
630 ]
631})channel",
632 Channel::MiniReflectTypeTable()));
633
634 FlatbufferDetachedBuffer<Channel> not_logged_channel(JsonToFlatbuffer(
635 R"channel({
636 "name": "/test",
637 "type": "aos.examples.Ping",
638 "source_node": "bar",
639 "logger": "NOT_LOGGED",
640 "destination_nodes": [
641 {
642 "name": "baz",
643 "timestamp_logger": "NOT_LOGGED"
644 }
645 ]
646})channel",
647 Channel::MiniReflectTypeTable()));
648
649 FlatbufferDetachedBuffer<Channel> logged_on_remote_channel(JsonToFlatbuffer(
650 R"channel({
651 "name": "/test",
652 "type": "aos.examples.Ping",
653 "source_node": "bar",
654 "destination_nodes": [
655 {
656 "name": "baz",
657 "timestamp_logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700658 "timestamp_logger_nodes": ["bar"]
Austin Schuh719946b2019-12-28 14:51:01 -0800659 }
660 ]
661})channel",
662 Channel::MiniReflectTypeTable()));
663
664 FlatbufferDetachedBuffer<Channel> logged_on_separate_logger_node_channel(
665 JsonToFlatbuffer(
666 R"channel({
667 "name": "/test",
668 "type": "aos.examples.Ping",
669 "source_node": "bar",
670 "logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700671 "logger_nodes": ["foo"],
Austin Schuh719946b2019-12-28 14:51:01 -0800672 "destination_nodes": [
673 {
674 "name": "baz",
675 "timestamp_logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700676 "timestamp_logger_nodes": ["foo"]
Austin Schuh719946b2019-12-28 14:51:01 -0800677 }
678 ]
679})channel",
680 Channel::MiniReflectTypeTable()));
681
Ravago Jonescf453ab2020-05-06 21:14:53 -0700682 FlatbufferDetachedBuffer<Channel> logged_on_both_channel(JsonToFlatbuffer(
683 R"channel({
Austin Schuh719946b2019-12-28 14:51:01 -0800684 "name": "/test",
685 "type": "aos.examples.Ping",
686 "source_node": "bar",
687 "destination_nodes": [
688 {
689 "name": "baz",
690 "timestamp_logger": "LOCAL_AND_REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700691 "timestamp_logger_nodes": ["bar"]
Austin Schuh719946b2019-12-28 14:51:01 -0800692 }
693 ]
694})channel",
Ravago Jonescf453ab2020-05-06 21:14:53 -0700695 Channel::MiniReflectTypeTable()));
Austin Schuh719946b2019-12-28 14:51:01 -0800696
697 FlatbufferDetachedBuffer<Node> foo_node(JsonToFlatbuffer(
698 R"node({
699 "name": "foo"
700})node",
701 Node::MiniReflectTypeTable()));
702
703 FlatbufferDetachedBuffer<Node> bar_node(JsonToFlatbuffer(
704 R"node({
705 "name": "bar"
706})node",
707 Node::MiniReflectTypeTable()));
708
709 FlatbufferDetachedBuffer<Node> baz_node(JsonToFlatbuffer(
710 R"node({
711 "name": "baz"
712})node",
713 Node::MiniReflectTypeTable()));
714
715 // Local logger.
716 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
717 &logged_on_self_channel.message(), &baz_node.message(),
718 &foo_node.message()));
719 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
720 &logged_on_self_channel.message(), &baz_node.message(),
721 &bar_node.message()));
722 EXPECT_TRUE(ConnectionDeliveryTimeIsLoggedOnNode(
723 &logged_on_self_channel.message(), &baz_node.message(),
724 &baz_node.message()));
725
726 // No logger means.
727 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
728 &not_logged_channel.message(), &baz_node.message(), &foo_node.message()));
729 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
730 &not_logged_channel.message(), &baz_node.message(), &bar_node.message()));
731 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
732 &not_logged_channel.message(), &baz_node.message(), &baz_node.message()));
733
734 // Remote logger.
735 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
736 &logged_on_remote_channel.message(), &baz_node.message(),
737 &foo_node.message()));
738 EXPECT_TRUE(ConnectionDeliveryTimeIsLoggedOnNode(
739 &logged_on_remote_channel.message(), &baz_node.message(),
740 &bar_node.message()));
741 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
742 &logged_on_remote_channel.message(), &baz_node.message(),
743 &baz_node.message()));
744
745 // Separate logger.
746 EXPECT_TRUE(ConnectionDeliveryTimeIsLoggedOnNode(
747 &logged_on_separate_logger_node_channel.message(), &baz_node.message(),
748 &foo_node.message()));
749 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
750 &logged_on_separate_logger_node_channel.message(), &baz_node.message(),
751 &bar_node.message()));
752 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
753 &logged_on_separate_logger_node_channel.message(), &baz_node.message(),
754 &baz_node.message()));
755
756 // Logged on both the node and a remote node.
757 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
758 &logged_on_both_channel.message(), &baz_node.message(),
759 &foo_node.message()));
760 EXPECT_TRUE(ConnectionDeliveryTimeIsLoggedOnNode(
761 &logged_on_both_channel.message(), &baz_node.message(),
762 &bar_node.message()));
763 EXPECT_TRUE(ConnectionDeliveryTimeIsLoggedOnNode(
764 &logged_on_both_channel.message(), &baz_node.message(),
765 &baz_node.message()));
766}
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800767
768// Tests that we can deduce source nodes from a multinode config.
769TEST_F(ConfigurationTest, SourceNodeNames) {
770 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700771 ReadConfig(ArtifactPath("aos/testdata/config1_multinode.json"));
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800772
773 // This is a bit simplistic in that it doesn't test deduplication, but it does
774 // exercise a lot of the logic.
775 EXPECT_THAT(
776 SourceNodeNames(&config.message(), config.message().nodes()->Get(0)),
777 ::testing::ElementsAreArray({"pi2"}));
778 EXPECT_THAT(
779 SourceNodeNames(&config.message(), config.message().nodes()->Get(1)),
780 ::testing::ElementsAreArray({"pi1"}));
781}
782
783// Tests that we can deduce destination nodes from a multinode config.
784TEST_F(ConfigurationTest, DestinationNodeNames) {
785 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700786 ReadConfig(ArtifactPath("aos/testdata/config1_multinode.json"));
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800787
788 // This is a bit simplistic in that it doesn't test deduplication, but it does
789 // exercise a lot of the logic.
790 EXPECT_THAT(
791 DestinationNodeNames(&config.message(), config.message().nodes()->Get(0)),
792 ::testing::ElementsAreArray({"pi2"}));
793 EXPECT_THAT(
794 DestinationNodeNames(&config.message(), config.message().nodes()->Get(1)),
795 ::testing::ElementsAreArray({"pi1"}));
796}
797
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800798// Tests that we can pull out all the nodes.
799TEST_F(ConfigurationTest, GetNodes) {
800 {
801 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700802 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800803 const Node *pi1 = GetNode(&config.message(), "pi1");
804 const Node *pi2 = GetNode(&config.message(), "pi2");
805
806 EXPECT_THAT(GetNodes(&config.message()), ::testing::ElementsAre(pi1, pi2));
807 }
808
809 {
810 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700811 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800812 EXPECT_THAT(GetNodes(&config.message()), ::testing::ElementsAre(nullptr));
813 }
814}
815
Austin Schuh65465332020-11-05 17:36:53 -0800816// Tests that we can pull out all the nodes with a tag.
817TEST_F(ConfigurationTest, GetNodesWithTag) {
818 {
819 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700820 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuh65465332020-11-05 17:36:53 -0800821 const Node *pi1 = GetNode(&config.message(), "pi1");
822 const Node *pi2 = GetNode(&config.message(), "pi2");
823
824 EXPECT_THAT(GetNodesWithTag(&config.message(), "a"),
825 ::testing::ElementsAre(pi1));
826 EXPECT_THAT(GetNodesWithTag(&config.message(), "b"),
827 ::testing::ElementsAre(pi2));
828 EXPECT_THAT(GetNodesWithTag(&config.message(), "c"),
829 ::testing::ElementsAre(pi1, pi2));
830 }
831
832 {
833 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700834 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Austin Schuh65465332020-11-05 17:36:53 -0800835 EXPECT_THAT(GetNodesWithTag(&config.message(), "arglfish"),
836 ::testing::ElementsAre(nullptr));
837 }
838}
839
Brian Silverman631b6262021-11-10 12:25:08 -0800840// Tests that we can check if a node has a tag.
841TEST_F(ConfigurationTest, NodeHasTag) {
842 {
843 FlatbufferDetachedBuffer<Configuration> config =
844 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
845 const Node *pi1 = GetNode(&config.message(), "pi1");
846 const Node *pi2 = GetNode(&config.message(), "pi2");
847
848 EXPECT_TRUE(NodeHasTag(pi1, "a"));
849 EXPECT_FALSE(NodeHasTag(pi2, "a"));
850 EXPECT_FALSE(NodeHasTag(pi1, "b"));
851 EXPECT_TRUE(NodeHasTag(pi2, "b"));
852 EXPECT_TRUE(NodeHasTag(pi1, "c"));
853 EXPECT_TRUE(NodeHasTag(pi2, "c"));
854 EXPECT_FALSE(NodeHasTag(pi1, "nope"));
855 EXPECT_FALSE(NodeHasTag(pi2, "nope"));
856 }
857
858 EXPECT_TRUE(NodeHasTag(nullptr, "arglfish"));
859}
860
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800861// Tests that we can extract a node index from a config.
862TEST_F(ConfigurationTest, GetNodeIndex) {
863 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700864 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuh04408fc2020-02-16 21:48:54 -0800865 FlatbufferDetachedBuffer<Configuration> config2 =
Austin Schuh373f1762021-06-02 21:07:09 -0700866 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800867 const Node *pi1 = GetNode(&config.message(), "pi1");
868 const Node *pi2 = GetNode(&config.message(), "pi2");
869
Austin Schuh04408fc2020-02-16 21:48:54 -0800870 // Try the normal case.
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800871 EXPECT_EQ(GetNodeIndex(&config.message(), pi1), 0);
872 EXPECT_EQ(GetNodeIndex(&config.message(), pi2), 1);
Austin Schuh04408fc2020-02-16 21:48:54 -0800873
874 // Now try if we have node pointers from a different message.
875 EXPECT_EQ(GetNodeIndex(&config2.message(), pi1), 0);
876 EXPECT_EQ(GetNodeIndex(&config2.message(), pi2), 1);
877
878 // And now try string names.
879 EXPECT_EQ(GetNodeIndex(&config2.message(), pi1->name()->string_view()), 0);
880 EXPECT_EQ(GetNodeIndex(&config2.message(), pi2->name()->string_view()), 1);
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800881}
882
883// Tests that GetNodeOrDie handles both single and multi-node worlds and returns
884// valid nodes.
885TEST_F(ConfigurationDeathTest, GetNodeOrDie) {
886 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700887 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800888 FlatbufferDetachedBuffer<Configuration> config2 =
Austin Schuh373f1762021-06-02 21:07:09 -0700889 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800890 {
891 // Simple case, nullptr -> nullptr
892 FlatbufferDetachedBuffer<Configuration> single_node_config =
Austin Schuh373f1762021-06-02 21:07:09 -0700893 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800894 EXPECT_EQ(nullptr, GetNodeOrDie(&single_node_config.message(), nullptr));
895
896 // Confirm that we die when a node is passed in.
897 EXPECT_DEATH(
898 {
899 GetNodeOrDie(&single_node_config.message(),
900 config.message().nodes()->Get(0));
901 },
902 "Provided a node in a single node world.");
903 }
904
905 const Node *pi1 = GetNode(&config.message(), "pi1");
906 // Now try a lookup using a node from a different instance of the config.
907 EXPECT_EQ(pi1,
908 GetNodeOrDie(&config.message(), config2.message().nodes()->Get(0)));
909}
910
Brian Silvermanaa2633f2020-02-17 21:04:14 -0800911TEST_F(ConfigurationTest, GetNodeFromHostname) {
912 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700913 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Brian Silvermanaa2633f2020-02-17 21:04:14 -0800914 EXPECT_EQ("pi1",
915 CHECK_NOTNULL(GetNodeFromHostname(&config.message(), "raspberrypi"))
916 ->name()
917 ->string_view());
918 EXPECT_EQ("pi2", CHECK_NOTNULL(
919 GetNodeFromHostname(&config.message(), "raspberrypi2"))
920 ->name()
921 ->string_view());
922 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "raspberrypi3"));
923 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "localhost"));
924 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "3"));
925}
926
927TEST_F(ConfigurationTest, GetNodeFromHostnames) {
928 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700929 ReadConfig(ArtifactPath("aos/testdata/good_multinode_hostnames.json"));
Brian Silvermanaa2633f2020-02-17 21:04:14 -0800930 EXPECT_EQ("pi1",
931 CHECK_NOTNULL(GetNodeFromHostname(&config.message(), "raspberrypi"))
932 ->name()
933 ->string_view());
934 EXPECT_EQ("pi2", CHECK_NOTNULL(
935 GetNodeFromHostname(&config.message(), "raspberrypi2"))
936 ->name()
937 ->string_view());
938 EXPECT_EQ("pi2", CHECK_NOTNULL(
939 GetNodeFromHostname(&config.message(), "raspberrypi3"))
940 ->name()
941 ->string_view());
Ravago Jonescf453ab2020-05-06 21:14:53 -0700942 EXPECT_EQ("pi2",
943 CHECK_NOTNULL(GetNodeFromHostname(&config.message(), "other"))
944 ->name()
945 ->string_view());
Brian Silvermanaa2633f2020-02-17 21:04:14 -0800946 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "raspberrypi4"));
947 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "localhost"));
948 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "3"));
949}
950
Austin Schuhfc7b6a02021-07-12 21:19:07 -0700951// Tests that SourceNodeIndex reasonably handles a multi-node log file.
952TEST_F(ConfigurationTest, SourceNodeIndex) {
953 FlatbufferDetachedBuffer<Configuration> config =
954 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
955 std::vector<size_t> result = SourceNodeIndex(&config.message());
956
957 EXPECT_THAT(result, ::testing::ElementsAreArray({0, 1, 0, 0}));
958}
959
Austin Schuh5e95bd62021-10-11 18:40:22 -0700960// Tests that we reject invalid logging configurations.
961TEST_F(ConfigurationDeathTest, InvalidLoggerConfig) {
962 EXPECT_DEATH(
963 {
Milind Upadhyay17098ba2022-04-15 22:18:50 -0700964 FlatbufferDetachedBuffer<Configuration> config = ReadConfig(
965 ArtifactPath("aos/testdata/invalid_logging_configuration.json"));
Austin Schuh5e95bd62021-10-11 18:40:22 -0700966 },
967 "Logging timestamps without data");
968}
969
Austin Schuha156fb22021-10-11 19:23:21 -0700970// Tests that we reject duplicate timestamp destination node configurations.
971TEST_F(ConfigurationDeathTest, DuplicateTimestampDestinationNodes) {
972 EXPECT_DEATH(
973 {
974 FlatbufferDetachedBuffer<Configuration> config = ReadConfig(
975 ArtifactPath("aos/testdata/duplicate_destination_nodes.json"));
976 },
977 "Found duplicate timestamp_logger_nodes in");
978}
979
980// Tests that we reject duplicate logger node configurations for a channel's
981// data.
982TEST_F(ConfigurationDeathTest, DuplicateLoggerNodes) {
983 EXPECT_DEATH(
984 {
985 FlatbufferDetachedBuffer<Configuration> config = ReadConfig(
986 ArtifactPath("aos/testdata/duplicate_logger_nodes.json"));
987 },
988 "Found duplicate logger_nodes in");
989}
990
Austin Schuhcb108412019-10-13 16:09:54 -0700991} // namespace testing
992} // namespace configuration
993} // namespace aos