blob: fa74e200ab957a3698c7eb7343e090a43c4547be [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 Schuhfb37c612022-08-11 15:24:51 -070019namespace chrono = std::chrono;
Austin Schuh66602132020-02-28 13:38:37 -080020
Austin Schuhcb108412019-10-13 16:09:54 -070021class ConfigurationTest : public ::testing::Test {
22 public:
23 ConfigurationTest() { ::aos::testing::EnableTestLogging(); }
24};
25
26typedef ConfigurationTest ConfigurationDeathTest;
27
28// *the* expected location for all working tests.
Austin Schuh1ef01ef2021-02-07 20:40:36 -080029aos::FlatbufferDetachedBuffer<Channel> ExpectedLocation() {
30 return JsonToFlatbuffer<Channel>(
31 "{ \"name\": \"/foo\", \"type\": \".aos.bar\", \"max_size\": 5 }");
32}
33
Austin Schuhbca6cf02019-12-22 17:28:34 -080034// And for multinode setups
Austin Schuh1ef01ef2021-02-07 20:40:36 -080035aos::FlatbufferDetachedBuffer<Channel> ExpectedMultinodeLocation() {
36 return JsonToFlatbuffer<Channel>(
37 "{ \"name\": \"/foo\", \"type\": \".aos.bar\", \"max_size\": 5, "
38 "\"source_node\": \"pi1\" }");
39}
Austin Schuhcb108412019-10-13 16:09:54 -070040
41// Tests that we can read and merge a configuration.
42TEST_F(ConfigurationTest, ConfigMerge) {
Austin Schuh40485ed2019-10-26 21:51:44 -070043 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -070044 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Ravago Jonescf453ab2020-05-06 21:14:53 -070045 LOG(INFO) << "Read: " << FlatbufferToJson(config, {.multi_line = true});
Austin Schuhcb108412019-10-13 16:09:54 -070046
Austin Schuh373f1762021-06-02 21:07:09 -070047 EXPECT_EQ(absl::StripSuffix(util::ReadFileToStringOrDie(
48 ArtifactPath("aos/testdata/expected.json")),
49 "\n"),
50 FlatbufferToJson(config, {.multi_line = true}));
Austin Schuhcb108412019-10-13 16:09:54 -070051}
52
Austin Schuhc9e10ec2020-01-26 16:08:28 -080053// Tests that we can get back a ChannelIndex.
54TEST_F(ConfigurationTest, ChannelIndex) {
55 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -070056 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -080057
58 EXPECT_EQ(
59 ChannelIndex(&config.message(), config.message().channels()->Get(1u)),
60 1u);
61}
62
Austin Schuh217a9782019-12-21 23:02:50 -080063// Tests that we can read and merge a multinode configuration.
64TEST_F(ConfigurationTest, ConfigMergeMultinode) {
65 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -070066 ReadConfig(ArtifactPath("aos/testdata/config1_multinode.json"));
Ravago Jonescf453ab2020-05-06 21:14:53 -070067 LOG(INFO) << "Read: " << FlatbufferToJson(config, {.multi_line = true});
Austin Schuh217a9782019-12-21 23:02:50 -080068
Ravago Jonescf453ab2020-05-06 21:14:53 -070069 EXPECT_EQ(std::string(absl::StripSuffix(
Austin Schuh373f1762021-06-02 21:07:09 -070070 util::ReadFileToStringOrDie(
71 ArtifactPath("aos/testdata/expected_multinode.json")),
Ravago Jonescf453ab2020-05-06 21:14:53 -070072 "\n")),
73 FlatbufferToJson(config, {.multi_line = true}));
Austin Schuh217a9782019-12-21 23:02:50 -080074}
75
Alex Perrycb7da4b2019-08-28 19:35:56 -070076// Tests that we sort the entries in a config so we can look entries up.
77TEST_F(ConfigurationTest, UnsortedConfig) {
78 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -070079 ReadConfig(ArtifactPath("aos/testdata/backwards.json"));
Alex Perrycb7da4b2019-08-28 19:35:56 -070080
Ravago Jonescf453ab2020-05-06 21:14:53 -070081 LOG(INFO) << "Read: " << FlatbufferToJson(config, {.multi_line = true});
Alex Perrycb7da4b2019-08-28 19:35:56 -070082
Austin Schuhf1fff282020-03-28 16:57:32 -070083 EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/aos/robot_state",
Austin Schuhbca6cf02019-12-22 17:28:34 -080084 "aos.RobotState", "app1", nullptr)),
Austin Schuhf1fff282020-03-28 16:57:32 -070085 "{ \"name\": \"/aos/robot_state\", \"type\": \"aos.RobotState\", "
Alex Perrycb7da4b2019-08-28 19:35:56 -070086 "\"max_size\": 5 }");
87}
88
Austin Schuhcb108412019-10-13 16:09:54 -070089// Tests that we die when a file is imported twice.
90TEST_F(ConfigurationDeathTest, DuplicateFile) {
91 EXPECT_DEATH(
92 {
Austin Schuh40485ed2019-10-26 21:51:44 -070093 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -070094 ReadConfig(ArtifactPath("aos/testdata/config1_bad.json"));
Austin Schuhcb108412019-10-13 16:09:54 -070095 },
Austin Schuh373f1762021-06-02 21:07:09 -070096 "aos/testdata/config1_bad.json");
Austin Schuhcb108412019-10-13 16:09:54 -070097}
98
Milind Upadhyay17098ba2022-04-15 22:18:50 -070099// Tests that we die when we give an invalid path.
100TEST_F(ConfigurationDeathTest, NonexistentFile) {
101 EXPECT_DEATH(
102 {
103 FlatbufferDetachedBuffer<Configuration> config =
104 ReadConfig("nonexistent/config.json");
105 },
106 "above error");
107}
108
109// Tests that we return std::nullopt when we give an invalid path.
110TEST_F(ConfigurationTest, NonexistentFileOptional) {
111 std::optional<FlatbufferDetachedBuffer<Configuration>> config =
112 MaybeReadConfig("nonexistent/config.json");
113 EXPECT_FALSE(config.has_value());
114}
115
Austin Schuhf1fff282020-03-28 16:57:32 -0700116// Tests that we reject invalid channel names. This means any channels with //
117// in their name, a trailing /, or regex characters.
118TEST_F(ConfigurationDeathTest, InvalidChannelName) {
119 EXPECT_DEATH(
120 {
121 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700122 ReadConfig(ArtifactPath("aos/testdata/invalid_channel_name1.json"));
Austin Schuhf1fff282020-03-28 16:57:32 -0700123 },
124 "Channel names can't end with '/'");
125 EXPECT_DEATH(
126 {
127 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700128 ReadConfig(ArtifactPath("aos/testdata/invalid_channel_name2.json"));
Austin Schuhf1fff282020-03-28 16:57:32 -0700129 },
130 "Invalid channel name");
131 EXPECT_DEATH(
132 {
133 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700134 ReadConfig(ArtifactPath("aos/testdata/invalid_channel_name3.json"));
Austin Schuhf1fff282020-03-28 16:57:32 -0700135 LOG(FATAL) << "Foo";
136 },
137 "Invalid channel name");
138}
139
Austin Schuh8d6cea82020-02-28 12:17:16 -0800140// Tests that we can modify a config with a json snippet.
141TEST_F(ConfigurationTest, MergeWithConfig) {
142 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700143 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Ravago Jonescf453ab2020-05-06 21:14:53 -0700144 LOG(INFO) << "Read: " << FlatbufferToJson(config, {.multi_line = true});
Austin Schuh8d6cea82020-02-28 12:17:16 -0800145
146 FlatbufferDetachedBuffer<Configuration> updated_config =
147 MergeWithConfig(&config.message(),
148 R"channel({
149 "channels": [
150 {
151 "name": "/foo",
152 "type": ".aos.bar",
153 "max_size": 100
154 }
155 ]
156})channel");
157
Austin Schuh373f1762021-06-02 21:07:09 -0700158 EXPECT_EQ(absl::StripSuffix(util::ReadFileToStringOrDie(ArtifactPath(
159 "aos/testdata/expected_merge_with.json")),
Ravago Jonescf453ab2020-05-06 21:14:53 -0700160 "\n"),
161 FlatbufferToJson(updated_config, {.multi_line = true}));
Austin Schuh8d6cea82020-02-28 12:17:16 -0800162}
163
Austin Schuhcb108412019-10-13 16:09:54 -0700164// Tests that we can lookup a location, complete with maps, from a merged
165// config.
Austin Schuh40485ed2019-10-26 21:51:44 -0700166TEST_F(ConfigurationTest, GetChannel) {
167 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700168 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Austin Schuhcb108412019-10-13 16:09:54 -0700169
170 // Test a basic lookup first.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800171 EXPECT_THAT(GetChannel(config, "/foo", ".aos.bar", "app1", nullptr),
172 aos::testing::FlatbufferEq(ExpectedLocation()));
Austin Schuhcb108412019-10-13 16:09:54 -0700173
174 // Test that an invalid name results in nullptr back.
Austin Schuhbca6cf02019-12-22 17:28:34 -0800175 EXPECT_EQ(GetChannel(config, "/invalid_name", ".aos.bar", "app1", nullptr),
176 nullptr);
Austin Schuhcb108412019-10-13 16:09:54 -0700177
178 // Tests that a root map/rename works. And that they get processed from the
179 // bottom up.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800180 EXPECT_THAT(GetChannel(config, "/batman", ".aos.bar", "app1", nullptr),
181 aos::testing::FlatbufferEq(ExpectedLocation()));
Austin Schuhcb108412019-10-13 16:09:54 -0700182
183 // And then test that an application specific map/rename works.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800184 EXPECT_THAT(GetChannel(config, "/bar", ".aos.bar", "app1", nullptr),
185 aos::testing::FlatbufferEq(ExpectedLocation()));
186 EXPECT_THAT(GetChannel(config, "/baz", ".aos.bar", "app2", nullptr),
187 aos::testing::FlatbufferEq(ExpectedLocation()));
Austin Schuhcb108412019-10-13 16:09:54 -0700188
189 // And then test that an invalid application name gets properly ignored.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800190 EXPECT_THAT(GetChannel(config, "/foo", ".aos.bar", "app3", nullptr),
191 aos::testing::FlatbufferEq(ExpectedLocation()));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800192}
193
James Kuszmaulc8503f32022-06-25 16:17:12 -0700194// Tests that we can do reverse-lookups of channel names.
195TEST_F(ConfigurationTest, GetChannelAliases) {
196 FlatbufferDetachedBuffer<Configuration> config =
197 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
198
199 // Test a basic lookup first.
200 EXPECT_THAT(
201 GetChannelAliases(&config.message(), "/foo", ".aos.bar", "app1", nullptr),
202 ::testing::UnorderedElementsAre("/foo", "/batman", "/bar"));
203 EXPECT_THAT(
204 GetChannelAliases(&config.message(), "/bar", ".aos.bar", "app1", nullptr),
205 ::testing::UnorderedElementsAre("/batman", "/bar"));
206 EXPECT_THAT(GetChannelAliases(&config.message(), "/batman", ".aos.bar",
207 "app1", nullptr),
208 ::testing::UnorderedElementsAre("/batman"));
209 // /bar (deliberately) does not get included because of the ordering in the
210 // map.
211 EXPECT_THAT(
212 GetChannelAliases(&config.message(), "/foo", ".aos.bar", "", nullptr),
213 ::testing::UnorderedElementsAre("/foo", "/batman"));
214 EXPECT_THAT(
215 GetChannelAliases(&config.message(), "/foo", ".aos.bar", "app2", nullptr),
216 ::testing::UnorderedElementsAre("/foo", "/batman", "/baz"));
217}
218
Austin Schuhbca6cf02019-12-22 17:28:34 -0800219// Tests that we can lookup a location with node specific maps.
220TEST_F(ConfigurationTest, GetChannelMultinode) {
221 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700222 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800223 const Node *pi1 = GetNode(&config.message(), "pi1");
224 const Node *pi2 = GetNode(&config.message(), "pi2");
225
226 // Test a basic lookup first.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800227 EXPECT_THAT(GetChannel(config, "/foo", ".aos.bar", "app1", pi1),
228 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
229 EXPECT_THAT(GetChannel(config, "/foo", ".aos.bar", "app1", pi2),
230 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800231
232 // Tests that a root map/rename works with a node specific map.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800233 EXPECT_THAT(GetChannel(config, "/batman", ".aos.bar", "app1", pi1),
234 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800235
236 // Tests that a root map/rename fails with a node specific map for the wrong
237 // node.
238 EXPECT_EQ(GetChannel(config, "/batman", ".aos.bar", "app1", pi2), nullptr);
239
240 // And then test that an application specific map/rename works.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800241 EXPECT_THAT(GetChannel(config, "/batman2", ".aos.bar", "app1", pi1),
242 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
243 EXPECT_THAT(GetChannel(config, "/batman3", ".aos.bar", "app1", pi1),
244 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800245
246 // And then that it fails when the node changes.
247 EXPECT_EQ(GetChannel(config, "/batman3", ".aos.bar", "app1", pi2), nullptr);
248}
249
James Kuszmaulc8503f32022-06-25 16:17:12 -0700250// Tests that reverse channel lookup on a multi-node config (including with
251// wildcards) works.
252TEST_F(ConfigurationTest, GetChannelAliasesMultinode) {
253 FlatbufferDetachedBuffer<Configuration> config =
254 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
255
256 const Node *pi1 = GetNode(&config.message(), "pi1");
257 const Node *pi2 = GetNode(&config.message(), "pi2");
258
259 EXPECT_THAT(
260 GetChannelAliases(&config.message(), "/foo", ".aos.bar", "app1", pi1),
261 ::testing::UnorderedElementsAre("/foo", "/batman", "/batman2", "/batman3",
262 "/magic/string"));
263
264 EXPECT_THAT(
265 GetChannelAliases(&config.message(), "/foo", ".aos.baz", "app1", pi1),
266 ::testing::UnorderedElementsAre("/foo", "/batman3", "/magic/string"));
267
268 EXPECT_THAT(
269 GetChannelAliases(&config.message(), "/foo/testing", ".aos.bar", "", pi1),
270 ::testing::UnorderedElementsAre("/foo/testing", "/magic/string/testing"));
271
272 EXPECT_THAT(
273 GetChannelAliases(&config.message(), "/foo/testing", ".aos.bar", "app1",
274 pi2),
275 ::testing::UnorderedElementsAre("/foo/testing", "/magic/string/testing"));
276}
277
Austin Schuhbca6cf02019-12-22 17:28:34 -0800278// Tests that we can lookup a location with type specific maps.
279TEST_F(ConfigurationTest, GetChannelTypedMultinode) {
280 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700281 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800282 const Node *pi1 = GetNode(&config.message(), "pi1");
283
284 // Test a basic lookup first.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800285 EXPECT_THAT(GetChannel(config, "/batman", ".aos.bar", "app1", pi1),
286 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
Austin Schuhbca6cf02019-12-22 17:28:34 -0800287
288 // Now confirm that a second message on the same name doesn't get remapped.
289 const char *kExpectedBazMultinodeLocation =
290 "{ \"name\": \"/batman\", \"type\": \".aos.baz\", \"max_size\": 5, "
291 "\"source_node\": \"pi1\" }";
292 EXPECT_EQ(
293 FlatbufferToJson(GetChannel(config, "/batman", ".aos.baz", "app1", pi1)),
294 kExpectedBazMultinodeLocation);
Austin Schuhcb108412019-10-13 16:09:54 -0700295}
296
Austin Schuhf1fff282020-03-28 16:57:32 -0700297// Tests that we can lookup a location with a glob
298TEST_F(ConfigurationTest, GetChannelGlob) {
299 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700300 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhf1fff282020-03-28 16:57:32 -0700301 const Node *pi1 = GetNode(&config.message(), "pi1");
302
303 // Confirm that a glob with nothing after it matches.
Austin Schuh1ef01ef2021-02-07 20:40:36 -0800304 EXPECT_THAT(GetChannel(config, "/magic/string", ".aos.bar", "app7", pi1),
305 aos::testing::FlatbufferEq(ExpectedMultinodeLocation()));
Austin Schuhf1fff282020-03-28 16:57:32 -0700306
307 // Now confirm that glob with something following it matches and renames
308 // correctly.
309 const char *kExpectedSubfolderMultinodeLocation =
310 "{ \"name\": \"/foo/subfolder\", \"type\": \".aos.bar\", \"max_size\": "
311 "5, \"source_node\": \"pi1\" }";
312 EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/magic/string/subfolder",
313 ".aos.bar", "app7", pi1)),
314 kExpectedSubfolderMultinodeLocation);
315}
316
Austin Schuh217a9782019-12-21 23:02:50 -0800317// Tests that we reject a configuration which has a nodes list, but has channels
318// withoout source_node filled out.
319TEST_F(ConfigurationDeathTest, InvalidSourceNode) {
320 EXPECT_DEATH(
321 {
322 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700323 ReadConfig(ArtifactPath("aos/testdata/invalid_nodes.json"));
Austin Schuh217a9782019-12-21 23:02:50 -0800324 },
325 "source_node");
326
327 EXPECT_DEATH(
328 {
329 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700330 ReadConfig(ArtifactPath("aos/testdata/invalid_source_node.json"));
Austin Schuh217a9782019-12-21 23:02:50 -0800331 },
332 "source_node");
333
334 EXPECT_DEATH(
335 {
Austin Schuh373f1762021-06-02 21:07:09 -0700336 FlatbufferDetachedBuffer<Configuration> config = ReadConfig(
337 ArtifactPath("aos/testdata/invalid_destination_node.json"));
Austin Schuh217a9782019-12-21 23:02:50 -0800338 },
339 "destination_nodes");
340
341 EXPECT_DEATH(
342 {
343 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700344 ReadConfig(ArtifactPath("aos/testdata/self_forward.json"));
Austin Schuh217a9782019-12-21 23:02:50 -0800345 },
346 "forwarding data to itself");
347}
348
349// Tests that our node writeable helpers work as intended.
350TEST_F(ConfigurationTest, ChannelIsSendableOnNode) {
351 FlatbufferDetachedBuffer<Channel> good_channel(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800352 R"channel({
Austin Schuh217a9782019-12-21 23:02:50 -0800353 "name": "/test",
354 "type": "aos.examples.Ping",
355 "source_node": "foo"
356})channel",
357 Channel::MiniReflectTypeTable()));
358
359 FlatbufferDetachedBuffer<Channel> bad_channel(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800360 R"channel({
Austin Schuh217a9782019-12-21 23:02:50 -0800361 "name": "/test",
362 "type": "aos.examples.Ping",
363 "source_node": "bar"
364})channel",
365 Channel::MiniReflectTypeTable()));
366
367 FlatbufferDetachedBuffer<Node> node(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800368 R"node({
Austin Schuh217a9782019-12-21 23:02:50 -0800369 "name": "foo"
370})node",
371 Node::MiniReflectTypeTable()));
372
373 EXPECT_TRUE(
374 ChannelIsSendableOnNode(&good_channel.message(), &node.message()));
375 EXPECT_FALSE(
376 ChannelIsSendableOnNode(&bad_channel.message(), &node.message()));
377}
378
379// Tests that our node readable and writeable helpers work as intended.
380TEST_F(ConfigurationTest, ChannelIsReadableOnNode) {
381 FlatbufferDetachedBuffer<Channel> good_channel(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800382 R"channel({
Austin Schuh217a9782019-12-21 23:02:50 -0800383 "name": "/test",
384 "type": "aos.examples.Ping",
385 "source_node": "bar",
386 "destination_nodes": [
Austin Schuh719946b2019-12-28 14:51:01 -0800387 {
388 "name": "baz"
389 },
390 {
391 "name": "foo"
392 }
Austin Schuh217a9782019-12-21 23:02:50 -0800393 ]
394})channel",
395 Channel::MiniReflectTypeTable()));
396
397 FlatbufferDetachedBuffer<Channel> bad_channel1(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800398 R"channel({
Austin Schuh217a9782019-12-21 23:02:50 -0800399 "name": "/test",
400 "type": "aos.examples.Ping",
401 "source_node": "bar"
402})channel",
403 Channel::MiniReflectTypeTable()));
404
405 FlatbufferDetachedBuffer<Channel> bad_channel2(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800406 R"channel({
Austin Schuh217a9782019-12-21 23:02:50 -0800407 "name": "/test",
408 "type": "aos.examples.Ping",
409 "source_node": "bar",
410 "destination_nodes": [
Austin Schuh719946b2019-12-28 14:51:01 -0800411 {
412 "name": "baz"
413 }
Austin Schuh217a9782019-12-21 23:02:50 -0800414 ]
415})channel",
416 Channel::MiniReflectTypeTable()));
417
418 FlatbufferDetachedBuffer<Node> node(JsonToFlatbuffer(
Austin Schuh719946b2019-12-28 14:51:01 -0800419 R"node({
Austin Schuh217a9782019-12-21 23:02:50 -0800420 "name": "foo"
421})node",
422 Node::MiniReflectTypeTable()));
423
424 EXPECT_TRUE(
425 ChannelIsReadableOnNode(&good_channel.message(), &node.message()));
426 EXPECT_FALSE(
427 ChannelIsReadableOnNode(&bad_channel1.message(), &node.message()));
428 EXPECT_FALSE(
429 ChannelIsReadableOnNode(&bad_channel2.message(), &node.message()));
430}
431
Austin Schuh719946b2019-12-28 14:51:01 -0800432// Tests that our node message is logged helpers work as intended.
433TEST_F(ConfigurationTest, ChannelMessageIsLoggedOnNode) {
434 FlatbufferDetachedBuffer<Channel> logged_on_self_channel(JsonToFlatbuffer(
435 R"channel({
436 "name": "/test",
437 "type": "aos.examples.Ping",
438 "source_node": "bar",
439 "destination_nodes": [
440 {
441 "name": "baz"
442 }
443 ]
444})channel",
445 Channel::MiniReflectTypeTable()));
Austin Schuh217a9782019-12-21 23:02:50 -0800446
Austin Schuh719946b2019-12-28 14:51:01 -0800447 FlatbufferDetachedBuffer<Channel> not_logged_channel(JsonToFlatbuffer(
448 R"channel({
449 "name": "/test",
450 "type": "aos.examples.Ping",
451 "source_node": "bar",
452 "logger": "NOT_LOGGED",
453 "destination_nodes": [
454 {
455 "name": "baz",
456 "timestamp_logger": "LOCAL_LOGGER"
457 }
458 ]
459})channel",
460 Channel::MiniReflectTypeTable()));
461
462 FlatbufferDetachedBuffer<Channel> logged_on_remote_channel(JsonToFlatbuffer(
463 R"channel({
464 "name": "/test",
465 "type": "aos.examples.Ping",
466 "source_node": "bar",
467 "logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700468 "logger_nodes": ["baz"],
Austin Schuh719946b2019-12-28 14:51:01 -0800469 "destination_nodes": [
470 {
471 "name": "baz"
472 }
473 ]
474})channel",
475 Channel::MiniReflectTypeTable()));
476
477 FlatbufferDetachedBuffer<Channel> logged_on_separate_logger_node_channel(
478 JsonToFlatbuffer(
479 R"channel({
480 "name": "/test",
481 "type": "aos.examples.Ping",
482 "source_node": "bar",
483 "logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700484 "logger_nodes": ["foo"],
Austin Schuh719946b2019-12-28 14:51:01 -0800485 "destination_nodes": [
486 {
487 "name": "baz"
488 }
489 ]
490})channel",
491 Channel::MiniReflectTypeTable()));
492
Ravago Jonescf453ab2020-05-06 21:14:53 -0700493 FlatbufferDetachedBuffer<Channel> logged_on_both_channel(JsonToFlatbuffer(
494 R"channel({
Austin Schuh719946b2019-12-28 14:51:01 -0800495 "name": "/test",
496 "type": "aos.examples.Ping",
497 "source_node": "bar",
498 "logger": "LOCAL_AND_REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700499 "logger_nodes": ["baz"],
Austin Schuh719946b2019-12-28 14:51:01 -0800500 "destination_nodes": [
501 {
502 "name": "baz"
503 }
504 ]
505})channel",
Ravago Jonescf453ab2020-05-06 21:14:53 -0700506 Channel::MiniReflectTypeTable()));
Austin Schuh719946b2019-12-28 14:51:01 -0800507
508 FlatbufferDetachedBuffer<Node> foo_node(JsonToFlatbuffer(
509 R"node({
510 "name": "foo"
511})node",
512 Node::MiniReflectTypeTable()));
513
514 FlatbufferDetachedBuffer<Node> bar_node(JsonToFlatbuffer(
515 R"node({
516 "name": "bar"
517})node",
518 Node::MiniReflectTypeTable()));
519
520 FlatbufferDetachedBuffer<Node> baz_node(JsonToFlatbuffer(
521 R"node({
522 "name": "baz"
523})node",
524 Node::MiniReflectTypeTable()));
525
526 // Local logger.
527 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&logged_on_self_channel.message(),
528 &foo_node.message()));
529 EXPECT_TRUE(ChannelMessageIsLoggedOnNode(&logged_on_self_channel.message(),
530 &bar_node.message()));
531 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&logged_on_self_channel.message(),
532 &baz_node.message()));
Austin Schuh48e94502021-06-18 18:35:53 -0700533 EXPECT_TRUE(
534 ChannelMessageIsLoggedOnNode(&logged_on_self_channel.message(), nullptr));
Austin Schuh719946b2019-12-28 14:51:01 -0800535
536 // No logger.
537 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&not_logged_channel.message(),
538 &foo_node.message()));
539 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&not_logged_channel.message(),
Ravago Jonescf453ab2020-05-06 21:14:53 -0700540 &bar_node.message()));
Austin Schuh719946b2019-12-28 14:51:01 -0800541 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&not_logged_channel.message(),
542 &baz_node.message()));
Austin Schuh48e94502021-06-18 18:35:53 -0700543 EXPECT_FALSE(
544 ChannelMessageIsLoggedOnNode(&not_logged_channel.message(), nullptr));
Austin Schuh719946b2019-12-28 14:51:01 -0800545
546 // Remote logger.
547 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&logged_on_remote_channel.message(),
548 &foo_node.message()));
549 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&logged_on_remote_channel.message(),
550 &bar_node.message()));
551 EXPECT_TRUE(ChannelMessageIsLoggedOnNode(&logged_on_remote_channel.message(),
552 &baz_node.message()));
553
554 // Separate logger.
555 EXPECT_TRUE(ChannelMessageIsLoggedOnNode(
556 &logged_on_separate_logger_node_channel.message(), &foo_node.message()));
557 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(
558 &logged_on_separate_logger_node_channel.message(), &bar_node.message()));
559 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(
560 &logged_on_separate_logger_node_channel.message(), &baz_node.message()));
561
562 // Logged in multiple places.
563 EXPECT_FALSE(ChannelMessageIsLoggedOnNode(&logged_on_both_channel.message(),
564 &foo_node.message()));
565 EXPECT_TRUE(ChannelMessageIsLoggedOnNode(&logged_on_both_channel.message(),
566 &bar_node.message()));
567 EXPECT_TRUE(ChannelMessageIsLoggedOnNode(&logged_on_both_channel.message(),
568 &baz_node.message()));
569}
570
Austin Schuh48e94502021-06-18 18:35:53 -0700571// Tests that our node message is logged helpers work as intended.
572TEST_F(ConfigurationDeathTest, ChannelMessageIsLoggedOnNode) {
573 FlatbufferDetachedBuffer<Channel> logged_on_both_channel(JsonToFlatbuffer(
574 R"channel({
575 "name": "/test",
576 "type": "aos.examples.Ping",
577 "source_node": "bar",
578 "logger": "LOCAL_AND_REMOTE_LOGGER",
579 "logger_nodes": ["baz"],
580 "destination_nodes": [
581 {
582 "name": "baz"
583 }
584 ]
585})channel",
586 Channel::MiniReflectTypeTable()));
587
588 FlatbufferDetachedBuffer<Channel> logged_on_separate_logger_node_channel(
589 JsonToFlatbuffer(
590 R"channel({
591 "name": "/test",
592 "type": "aos.examples.Ping",
593 "source_node": "bar",
594 "logger": "REMOTE_LOGGER",
595 "logger_nodes": ["foo"],
596 "destination_nodes": [
597 {
598 "name": "baz"
599 }
600 ]
601})channel",
602 Channel::MiniReflectTypeTable()));
603
604 EXPECT_DEATH(
605 {
606 ChannelMessageIsLoggedOnNode(&logged_on_both_channel.message(),
607 nullptr);
608 },
609 "Unsupported logging configuration in a single node world");
610 EXPECT_DEATH(
611 {
612 ChannelMessageIsLoggedOnNode(
613 &logged_on_separate_logger_node_channel.message(), nullptr);
614 },
615 "Unsupported logging configuration in a single node world");
616}
617
Austin Schuh719946b2019-12-28 14:51:01 -0800618// Tests that our forwarding timestamps are logged helpers work as intended.
619TEST_F(ConfigurationTest, ConnectionDeliveryTimeIsLoggedOnNode) {
620 FlatbufferDetachedBuffer<Channel> logged_on_self_channel(JsonToFlatbuffer(
621 R"channel({
622 "name": "/test",
623 "type": "aos.examples.Ping",
624 "source_node": "bar",
625 "logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700626 "logger_nodes": ["baz"],
Austin Schuh719946b2019-12-28 14:51:01 -0800627 "destination_nodes": [
628 {
629 "name": "baz"
630 }
631 ]
632})channel",
633 Channel::MiniReflectTypeTable()));
634
635 FlatbufferDetachedBuffer<Channel> not_logged_channel(JsonToFlatbuffer(
636 R"channel({
637 "name": "/test",
638 "type": "aos.examples.Ping",
639 "source_node": "bar",
640 "logger": "NOT_LOGGED",
641 "destination_nodes": [
642 {
643 "name": "baz",
644 "timestamp_logger": "NOT_LOGGED"
645 }
646 ]
647})channel",
648 Channel::MiniReflectTypeTable()));
649
650 FlatbufferDetachedBuffer<Channel> logged_on_remote_channel(JsonToFlatbuffer(
651 R"channel({
652 "name": "/test",
653 "type": "aos.examples.Ping",
654 "source_node": "bar",
655 "destination_nodes": [
656 {
657 "name": "baz",
658 "timestamp_logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700659 "timestamp_logger_nodes": ["bar"]
Austin Schuh719946b2019-12-28 14:51:01 -0800660 }
661 ]
662})channel",
663 Channel::MiniReflectTypeTable()));
664
665 FlatbufferDetachedBuffer<Channel> logged_on_separate_logger_node_channel(
666 JsonToFlatbuffer(
667 R"channel({
668 "name": "/test",
669 "type": "aos.examples.Ping",
670 "source_node": "bar",
671 "logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700672 "logger_nodes": ["foo"],
Austin Schuh719946b2019-12-28 14:51:01 -0800673 "destination_nodes": [
674 {
675 "name": "baz",
676 "timestamp_logger": "REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700677 "timestamp_logger_nodes": ["foo"]
Austin Schuh719946b2019-12-28 14:51:01 -0800678 }
679 ]
680})channel",
681 Channel::MiniReflectTypeTable()));
682
Ravago Jonescf453ab2020-05-06 21:14:53 -0700683 FlatbufferDetachedBuffer<Channel> logged_on_both_channel(JsonToFlatbuffer(
684 R"channel({
Austin Schuh719946b2019-12-28 14:51:01 -0800685 "name": "/test",
686 "type": "aos.examples.Ping",
687 "source_node": "bar",
688 "destination_nodes": [
689 {
690 "name": "baz",
691 "timestamp_logger": "LOCAL_AND_REMOTE_LOGGER",
Austin Schuhda40e472020-03-28 15:15:29 -0700692 "timestamp_logger_nodes": ["bar"]
Austin Schuh719946b2019-12-28 14:51:01 -0800693 }
694 ]
695})channel",
Ravago Jonescf453ab2020-05-06 21:14:53 -0700696 Channel::MiniReflectTypeTable()));
Austin Schuh719946b2019-12-28 14:51:01 -0800697
698 FlatbufferDetachedBuffer<Node> foo_node(JsonToFlatbuffer(
699 R"node({
700 "name": "foo"
701})node",
702 Node::MiniReflectTypeTable()));
703
704 FlatbufferDetachedBuffer<Node> bar_node(JsonToFlatbuffer(
705 R"node({
706 "name": "bar"
707})node",
708 Node::MiniReflectTypeTable()));
709
710 FlatbufferDetachedBuffer<Node> baz_node(JsonToFlatbuffer(
711 R"node({
712 "name": "baz"
713})node",
714 Node::MiniReflectTypeTable()));
715
716 // Local logger.
717 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
718 &logged_on_self_channel.message(), &baz_node.message(),
719 &foo_node.message()));
720 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
721 &logged_on_self_channel.message(), &baz_node.message(),
722 &bar_node.message()));
723 EXPECT_TRUE(ConnectionDeliveryTimeIsLoggedOnNode(
724 &logged_on_self_channel.message(), &baz_node.message(),
725 &baz_node.message()));
726
727 // No logger means.
728 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
729 &not_logged_channel.message(), &baz_node.message(), &foo_node.message()));
730 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
731 &not_logged_channel.message(), &baz_node.message(), &bar_node.message()));
732 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
733 &not_logged_channel.message(), &baz_node.message(), &baz_node.message()));
734
735 // Remote logger.
736 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
737 &logged_on_remote_channel.message(), &baz_node.message(),
738 &foo_node.message()));
739 EXPECT_TRUE(ConnectionDeliveryTimeIsLoggedOnNode(
740 &logged_on_remote_channel.message(), &baz_node.message(),
741 &bar_node.message()));
742 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
743 &logged_on_remote_channel.message(), &baz_node.message(),
744 &baz_node.message()));
745
746 // Separate logger.
747 EXPECT_TRUE(ConnectionDeliveryTimeIsLoggedOnNode(
748 &logged_on_separate_logger_node_channel.message(), &baz_node.message(),
749 &foo_node.message()));
750 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
751 &logged_on_separate_logger_node_channel.message(), &baz_node.message(),
752 &bar_node.message()));
753 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
754 &logged_on_separate_logger_node_channel.message(), &baz_node.message(),
755 &baz_node.message()));
756
757 // Logged on both the node and a remote node.
758 EXPECT_FALSE(ConnectionDeliveryTimeIsLoggedOnNode(
759 &logged_on_both_channel.message(), &baz_node.message(),
760 &foo_node.message()));
761 EXPECT_TRUE(ConnectionDeliveryTimeIsLoggedOnNode(
762 &logged_on_both_channel.message(), &baz_node.message(),
763 &bar_node.message()));
764 EXPECT_TRUE(ConnectionDeliveryTimeIsLoggedOnNode(
765 &logged_on_both_channel.message(), &baz_node.message(),
766 &baz_node.message()));
767}
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800768
769// Tests that we can deduce source nodes from a multinode config.
770TEST_F(ConfigurationTest, SourceNodeNames) {
771 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700772 ReadConfig(ArtifactPath("aos/testdata/config1_multinode.json"));
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800773
774 // This is a bit simplistic in that it doesn't test deduplication, but it does
775 // exercise a lot of the logic.
776 EXPECT_THAT(
777 SourceNodeNames(&config.message(), config.message().nodes()->Get(0)),
778 ::testing::ElementsAreArray({"pi2"}));
779 EXPECT_THAT(
780 SourceNodeNames(&config.message(), config.message().nodes()->Get(1)),
781 ::testing::ElementsAreArray({"pi1"}));
782}
783
784// Tests that we can deduce destination nodes from a multinode config.
785TEST_F(ConfigurationTest, DestinationNodeNames) {
786 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700787 ReadConfig(ArtifactPath("aos/testdata/config1_multinode.json"));
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800788
789 // This is a bit simplistic in that it doesn't test deduplication, but it does
790 // exercise a lot of the logic.
791 EXPECT_THAT(
792 DestinationNodeNames(&config.message(), config.message().nodes()->Get(0)),
793 ::testing::ElementsAreArray({"pi2"}));
794 EXPECT_THAT(
795 DestinationNodeNames(&config.message(), config.message().nodes()->Get(1)),
796 ::testing::ElementsAreArray({"pi1"}));
797}
798
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800799// Tests that we can pull out all the nodes.
800TEST_F(ConfigurationTest, GetNodes) {
801 {
802 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700803 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800804 const Node *pi1 = GetNode(&config.message(), "pi1");
805 const Node *pi2 = GetNode(&config.message(), "pi2");
806
807 EXPECT_THAT(GetNodes(&config.message()), ::testing::ElementsAre(pi1, pi2));
808 }
809
810 {
811 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700812 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800813 EXPECT_THAT(GetNodes(&config.message()), ::testing::ElementsAre(nullptr));
814 }
815}
816
Austin Schuh65465332020-11-05 17:36:53 -0800817// Tests that we can pull out all the nodes with a tag.
818TEST_F(ConfigurationTest, GetNodesWithTag) {
819 {
820 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700821 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuh65465332020-11-05 17:36:53 -0800822 const Node *pi1 = GetNode(&config.message(), "pi1");
823 const Node *pi2 = GetNode(&config.message(), "pi2");
824
825 EXPECT_THAT(GetNodesWithTag(&config.message(), "a"),
826 ::testing::ElementsAre(pi1));
827 EXPECT_THAT(GetNodesWithTag(&config.message(), "b"),
828 ::testing::ElementsAre(pi2));
829 EXPECT_THAT(GetNodesWithTag(&config.message(), "c"),
830 ::testing::ElementsAre(pi1, pi2));
831 }
832
833 {
834 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700835 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Austin Schuh65465332020-11-05 17:36:53 -0800836 EXPECT_THAT(GetNodesWithTag(&config.message(), "arglfish"),
837 ::testing::ElementsAre(nullptr));
838 }
839}
840
Brian Silverman631b6262021-11-10 12:25:08 -0800841// Tests that we can check if a node has a tag.
842TEST_F(ConfigurationTest, NodeHasTag) {
843 {
844 FlatbufferDetachedBuffer<Configuration> config =
845 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
846 const Node *pi1 = GetNode(&config.message(), "pi1");
847 const Node *pi2 = GetNode(&config.message(), "pi2");
848
849 EXPECT_TRUE(NodeHasTag(pi1, "a"));
850 EXPECT_FALSE(NodeHasTag(pi2, "a"));
851 EXPECT_FALSE(NodeHasTag(pi1, "b"));
852 EXPECT_TRUE(NodeHasTag(pi2, "b"));
853 EXPECT_TRUE(NodeHasTag(pi1, "c"));
854 EXPECT_TRUE(NodeHasTag(pi2, "c"));
855 EXPECT_FALSE(NodeHasTag(pi1, "nope"));
856 EXPECT_FALSE(NodeHasTag(pi2, "nope"));
857 }
858
859 EXPECT_TRUE(NodeHasTag(nullptr, "arglfish"));
860}
861
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800862// Tests that we can extract a node index from a config.
863TEST_F(ConfigurationTest, GetNodeIndex) {
864 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700865 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuh04408fc2020-02-16 21:48:54 -0800866 FlatbufferDetachedBuffer<Configuration> config2 =
Austin Schuh373f1762021-06-02 21:07:09 -0700867 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800868 const Node *pi1 = GetNode(&config.message(), "pi1");
869 const Node *pi2 = GetNode(&config.message(), "pi2");
870
Austin Schuh04408fc2020-02-16 21:48:54 -0800871 // Try the normal case.
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800872 EXPECT_EQ(GetNodeIndex(&config.message(), pi1), 0);
873 EXPECT_EQ(GetNodeIndex(&config.message(), pi2), 1);
Austin Schuh04408fc2020-02-16 21:48:54 -0800874
875 // Now try if we have node pointers from a different message.
876 EXPECT_EQ(GetNodeIndex(&config2.message(), pi1), 0);
877 EXPECT_EQ(GetNodeIndex(&config2.message(), pi2), 1);
878
879 // And now try string names.
880 EXPECT_EQ(GetNodeIndex(&config2.message(), pi1->name()->string_view()), 0);
881 EXPECT_EQ(GetNodeIndex(&config2.message(), pi2->name()->string_view()), 1);
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800882}
883
884// Tests that GetNodeOrDie handles both single and multi-node worlds and returns
885// valid nodes.
886TEST_F(ConfigurationDeathTest, GetNodeOrDie) {
887 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700888 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800889 FlatbufferDetachedBuffer<Configuration> config2 =
Austin Schuh373f1762021-06-02 21:07:09 -0700890 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800891 {
892 // Simple case, nullptr -> nullptr
893 FlatbufferDetachedBuffer<Configuration> single_node_config =
Austin Schuh373f1762021-06-02 21:07:09 -0700894 ReadConfig(ArtifactPath("aos/testdata/config1.json"));
Austin Schuhc9e10ec2020-01-26 16:08:28 -0800895 EXPECT_EQ(nullptr, GetNodeOrDie(&single_node_config.message(), nullptr));
896
897 // Confirm that we die when a node is passed in.
898 EXPECT_DEATH(
899 {
900 GetNodeOrDie(&single_node_config.message(),
901 config.message().nodes()->Get(0));
902 },
903 "Provided a node in a single node world.");
904 }
905
906 const Node *pi1 = GetNode(&config.message(), "pi1");
907 // Now try a lookup using a node from a different instance of the config.
908 EXPECT_EQ(pi1,
909 GetNodeOrDie(&config.message(), config2.message().nodes()->Get(0)));
910}
911
Brian Silvermanaa2633f2020-02-17 21:04:14 -0800912TEST_F(ConfigurationTest, GetNodeFromHostname) {
913 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700914 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
Brian Silvermanaa2633f2020-02-17 21:04:14 -0800915 EXPECT_EQ("pi1",
916 CHECK_NOTNULL(GetNodeFromHostname(&config.message(), "raspberrypi"))
917 ->name()
918 ->string_view());
919 EXPECT_EQ("pi2", CHECK_NOTNULL(
920 GetNodeFromHostname(&config.message(), "raspberrypi2"))
921 ->name()
922 ->string_view());
923 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "raspberrypi3"));
924 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "localhost"));
925 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "3"));
926}
927
928TEST_F(ConfigurationTest, GetNodeFromHostnames) {
929 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuh373f1762021-06-02 21:07:09 -0700930 ReadConfig(ArtifactPath("aos/testdata/good_multinode_hostnames.json"));
Brian Silvermanaa2633f2020-02-17 21:04:14 -0800931 EXPECT_EQ("pi1",
932 CHECK_NOTNULL(GetNodeFromHostname(&config.message(), "raspberrypi"))
933 ->name()
934 ->string_view());
935 EXPECT_EQ("pi2", CHECK_NOTNULL(
936 GetNodeFromHostname(&config.message(), "raspberrypi2"))
937 ->name()
938 ->string_view());
939 EXPECT_EQ("pi2", CHECK_NOTNULL(
940 GetNodeFromHostname(&config.message(), "raspberrypi3"))
941 ->name()
942 ->string_view());
Ravago Jonescf453ab2020-05-06 21:14:53 -0700943 EXPECT_EQ("pi2",
944 CHECK_NOTNULL(GetNodeFromHostname(&config.message(), "other"))
945 ->name()
946 ->string_view());
Brian Silvermanaa2633f2020-02-17 21:04:14 -0800947 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "raspberrypi4"));
948 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "localhost"));
949 EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "3"));
950}
951
Austin Schuhfc7b6a02021-07-12 21:19:07 -0700952// Tests that SourceNodeIndex reasonably handles a multi-node log file.
953TEST_F(ConfigurationTest, SourceNodeIndex) {
954 FlatbufferDetachedBuffer<Configuration> config =
955 ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
956 std::vector<size_t> result = SourceNodeIndex(&config.message());
957
958 EXPECT_THAT(result, ::testing::ElementsAreArray({0, 1, 0, 0}));
959}
960
Austin Schuh5e95bd62021-10-11 18:40:22 -0700961// Tests that we reject invalid logging configurations.
962TEST_F(ConfigurationDeathTest, InvalidLoggerConfig) {
963 EXPECT_DEATH(
964 {
Milind Upadhyay17098ba2022-04-15 22:18:50 -0700965 FlatbufferDetachedBuffer<Configuration> config = ReadConfig(
966 ArtifactPath("aos/testdata/invalid_logging_configuration.json"));
Austin Schuh5e95bd62021-10-11 18:40:22 -0700967 },
968 "Logging timestamps without data");
969}
970
Austin Schuha156fb22021-10-11 19:23:21 -0700971// Tests that we reject duplicate timestamp destination node configurations.
972TEST_F(ConfigurationDeathTest, DuplicateTimestampDestinationNodes) {
973 EXPECT_DEATH(
974 {
975 FlatbufferDetachedBuffer<Configuration> config = ReadConfig(
976 ArtifactPath("aos/testdata/duplicate_destination_nodes.json"));
977 },
978 "Found duplicate timestamp_logger_nodes in");
979}
980
981// Tests that we reject duplicate logger node configurations for a channel's
982// data.
983TEST_F(ConfigurationDeathTest, DuplicateLoggerNodes) {
984 EXPECT_DEATH(
985 {
986 FlatbufferDetachedBuffer<Configuration> config = ReadConfig(
987 ArtifactPath("aos/testdata/duplicate_logger_nodes.json"));
988 },
989 "Found duplicate logger_nodes in");
990}
991
Austin Schuhfb37c612022-08-11 15:24:51 -0700992// Tests that we properly compute the queue size for the provided duration.
993TEST_F(ConfigurationTest, QueueSize) {
994 EXPECT_EQ(QueueSize(100, chrono::seconds(2)), 200);
995 EXPECT_EQ(QueueSize(200, chrono::seconds(2)), 400);
996 EXPECT_EQ(QueueSize(100, chrono::seconds(6)), 600);
997 EXPECT_EQ(QueueSize(100, chrono::milliseconds(10)), 1);
998 EXPECT_EQ(QueueSize(100, chrono::milliseconds(10) - chrono::nanoseconds(1)),
999 1);
1000 EXPECT_EQ(QueueSize(100, chrono::milliseconds(10) - chrono::nanoseconds(2)),
1001 1);
1002}
1003
1004// Tests that we compute scratch buffer size correctly too.
1005TEST_F(ConfigurationTest, QueueScratchBufferSize) {
1006 const aos::FlatbufferDetachedBuffer<Channel> channel =
1007 JsonToFlatbuffer<Channel>(
1008 "{ \"name\": \"/foo\", \"type\": \".aos.bar\", \"num_readers\": 5, "
1009 "\"num_senders\": 10 }");
1010
1011 EXPECT_EQ(QueueScratchBufferSize(&channel.message()), 15);
1012}
1013
Austin Schuhcb108412019-10-13 16:09:54 -07001014} // namespace testing
1015} // namespace configuration
1016} // namespace aos