blob: 35b9daf08fb8e942e4bf517ae19d314831bcc1b4 [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"
5#include "aos/testing/test_logging.h"
6#include "aos/util/file.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -07007#include "flatbuffers/reflection.h"
8#include "glog/logging.h"
Austin Schuhcb108412019-10-13 16:09:54 -07009#include "gtest/gtest.h"
10
11namespace aos {
12namespace configuration {
13namespace testing {
14
15class ConfigurationTest : public ::testing::Test {
16 public:
17 ConfigurationTest() { ::aos::testing::EnableTestLogging(); }
18};
19
20typedef ConfigurationTest ConfigurationDeathTest;
21
22// *the* expected location for all working tests.
23const char *kExpectedLocation =
24 "{ \"name\": \"/foo\", \"type\": \".aos.bar\", \"max_size\": 5 }";
25
26// Tests that we can read and merge a configuration.
27TEST_F(ConfigurationTest, ConfigMerge) {
Austin Schuh40485ed2019-10-26 21:51:44 -070028 FlatbufferDetachedBuffer<Configuration> config =
29 ReadConfig("aos/testdata/config1.json");
Alex Perrycb7da4b2019-08-28 19:35:56 -070030 LOG(INFO) << "Read: " << FlatbufferToJson(config, true);
Austin Schuhcb108412019-10-13 16:09:54 -070031
32 EXPECT_EQ(
33 absl::StripSuffix(
34 util::ReadFileToStringOrDie("aos/testdata/expected.json"), "\n"),
35 FlatbufferToJson(config, true));
36}
37
Austin Schuh217a9782019-12-21 23:02:50 -080038// Tests that we can read and merge a multinode configuration.
39TEST_F(ConfigurationTest, ConfigMergeMultinode) {
40 FlatbufferDetachedBuffer<Configuration> config =
41 ReadConfig("aos/testdata/config1_multinode.json");
42 LOG(INFO) << "Read: " << FlatbufferToJson(config, true);
43
44 EXPECT_EQ(
45 std::string(absl::StripSuffix(
46 util::ReadFileToStringOrDie("aos/testdata/expected_multinode.json"),
47 "\n")),
48 FlatbufferToJson(config, true));
49}
50
Alex Perrycb7da4b2019-08-28 19:35:56 -070051// Tests that we sort the entries in a config so we can look entries up.
52TEST_F(ConfigurationTest, UnsortedConfig) {
53 FlatbufferDetachedBuffer<Configuration> config =
54 ReadConfig("aos/testdata/backwards.json");
55
56 LOG(INFO) << "Read: " << FlatbufferToJson(config, true);
57
58 EXPECT_EQ(FlatbufferToJson(GetChannel(config, ".aos.robot_state",
59 "aos.RobotState", "app1")),
60 "{ \"name\": \".aos.robot_state\", \"type\": \"aos.RobotState\", "
61 "\"max_size\": 5 }");
62}
63
Austin Schuhcb108412019-10-13 16:09:54 -070064// Tests that we die when a file is imported twice.
65TEST_F(ConfigurationDeathTest, DuplicateFile) {
66 EXPECT_DEATH(
67 {
Austin Schuh40485ed2019-10-26 21:51:44 -070068 FlatbufferDetachedBuffer<Configuration> config =
Austin Schuhcb108412019-10-13 16:09:54 -070069 ReadConfig("aos/testdata/config1_bad.json");
70 },
71 "aos/testdata/config1_bad.json");
72}
73
74// Tests that we can lookup a location, complete with maps, from a merged
75// config.
Austin Schuh40485ed2019-10-26 21:51:44 -070076TEST_F(ConfigurationTest, GetChannel) {
77 FlatbufferDetachedBuffer<Configuration> config =
78 ReadConfig("aos/testdata/config1.json");
Austin Schuhcb108412019-10-13 16:09:54 -070079
80 // Test a basic lookup first.
Austin Schuh40485ed2019-10-26 21:51:44 -070081 EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/foo", ".aos.bar", "app1")),
Austin Schuhcb108412019-10-13 16:09:54 -070082 kExpectedLocation);
83
84 // Test that an invalid name results in nullptr back.
Austin Schuh40485ed2019-10-26 21:51:44 -070085 EXPECT_EQ(GetChannel(config, "/invalid_name", ".aos.bar", "app1"), nullptr);
Austin Schuhcb108412019-10-13 16:09:54 -070086
87 // Tests that a root map/rename works. And that they get processed from the
88 // bottom up.
89 EXPECT_EQ(
Austin Schuh40485ed2019-10-26 21:51:44 -070090 FlatbufferToJson(GetChannel(config, "/batman", ".aos.bar", "app1")),
Austin Schuhcb108412019-10-13 16:09:54 -070091 kExpectedLocation);
92
93 // And then test that an application specific map/rename works.
Austin Schuh40485ed2019-10-26 21:51:44 -070094 EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/bar", ".aos.bar", "app1")),
Austin Schuhcb108412019-10-13 16:09:54 -070095 kExpectedLocation);
Austin Schuh40485ed2019-10-26 21:51:44 -070096 EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/baz", ".aos.bar", "app2")),
Austin Schuhcb108412019-10-13 16:09:54 -070097 kExpectedLocation);
98
99 // And then test that an invalid application name gets properly ignored.
Austin Schuh40485ed2019-10-26 21:51:44 -0700100 EXPECT_EQ(FlatbufferToJson(GetChannel(config, "/foo", ".aos.bar", "app3")),
Austin Schuhcb108412019-10-13 16:09:54 -0700101 kExpectedLocation);
102}
103
Austin Schuh217a9782019-12-21 23:02:50 -0800104// Tests that we reject a configuration which has a nodes list, but has channels
105// withoout source_node filled out.
106TEST_F(ConfigurationDeathTest, InvalidSourceNode) {
107 EXPECT_DEATH(
108 {
109 FlatbufferDetachedBuffer<Configuration> config =
110 ReadConfig("aos/testdata/invalid_nodes.json");
111 },
112 "source_node");
113
114 EXPECT_DEATH(
115 {
116 FlatbufferDetachedBuffer<Configuration> config =
117 ReadConfig("aos/testdata/invalid_source_node.json");
118 },
119 "source_node");
120
121 EXPECT_DEATH(
122 {
123 FlatbufferDetachedBuffer<Configuration> config =
124 ReadConfig("aos/testdata/invalid_destination_node.json");
125 },
126 "destination_nodes");
127
128 EXPECT_DEATH(
129 {
130 FlatbufferDetachedBuffer<Configuration> config =
131 ReadConfig("aos/testdata/self_forward.json");
132 },
133 "forwarding data to itself");
134}
135
136// Tests that our node writeable helpers work as intended.
137TEST_F(ConfigurationTest, ChannelIsSendableOnNode) {
138 FlatbufferDetachedBuffer<Channel> good_channel(JsonToFlatbuffer(
139R"channel({
140 "name": "/test",
141 "type": "aos.examples.Ping",
142 "source_node": "foo"
143})channel",
144 Channel::MiniReflectTypeTable()));
145
146 FlatbufferDetachedBuffer<Channel> bad_channel(JsonToFlatbuffer(
147R"channel({
148 "name": "/test",
149 "type": "aos.examples.Ping",
150 "source_node": "bar"
151})channel",
152 Channel::MiniReflectTypeTable()));
153
154 FlatbufferDetachedBuffer<Node> node(JsonToFlatbuffer(
155R"node({
156 "name": "foo"
157})node",
158 Node::MiniReflectTypeTable()));
159
160 EXPECT_TRUE(
161 ChannelIsSendableOnNode(&good_channel.message(), &node.message()));
162 EXPECT_FALSE(
163 ChannelIsSendableOnNode(&bad_channel.message(), &node.message()));
164}
165
166// Tests that our node readable and writeable helpers work as intended.
167TEST_F(ConfigurationTest, ChannelIsReadableOnNode) {
168 FlatbufferDetachedBuffer<Channel> good_channel(JsonToFlatbuffer(
169R"channel({
170 "name": "/test",
171 "type": "aos.examples.Ping",
172 "source_node": "bar",
173 "destination_nodes": [
174 "baz",
175 "foo",
176 ]
177})channel",
178 Channel::MiniReflectTypeTable()));
179
180 FlatbufferDetachedBuffer<Channel> bad_channel1(JsonToFlatbuffer(
181R"channel({
182 "name": "/test",
183 "type": "aos.examples.Ping",
184 "source_node": "bar"
185})channel",
186 Channel::MiniReflectTypeTable()));
187
188 FlatbufferDetachedBuffer<Channel> bad_channel2(JsonToFlatbuffer(
189R"channel({
190 "name": "/test",
191 "type": "aos.examples.Ping",
192 "source_node": "bar",
193 "destination_nodes": [
194 "baz"
195 ]
196})channel",
197 Channel::MiniReflectTypeTable()));
198
199 FlatbufferDetachedBuffer<Node> node(JsonToFlatbuffer(
200R"node({
201 "name": "foo"
202})node",
203 Node::MiniReflectTypeTable()));
204
205 EXPECT_TRUE(
206 ChannelIsReadableOnNode(&good_channel.message(), &node.message()));
207 EXPECT_FALSE(
208 ChannelIsReadableOnNode(&bad_channel1.message(), &node.message()));
209 EXPECT_FALSE(
210 ChannelIsReadableOnNode(&bad_channel2.message(), &node.message()));
211}
212
213
Austin Schuhcb108412019-10-13 16:09:54 -0700214} // namespace testing
215} // namespace configuration
216} // namespace aos