1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/fuchsia_component_support/annotations_manager.h"
7 #include "base/fuchsia/mem_buffer_util.h"
8 #include "base/test/gtest_util.h"
9 #include "base/test/task_environment.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 namespace fuchsia_component_support {
16 class AnnotationsManagerTest : public testing::Test {
18 AnnotationsManagerTest() = default;
20 base::test::SingleThreadTaskEnvironment task_environment_{
21 base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
24 constexpr char kGlobalNamespace[] = "global";
26 constexpr char kAnnotationName1[] = "annotation1";
27 constexpr char kAnnotationName2[] = "annotation2";
29 constexpr char kAnnotationValue1[] = "annotation_value1";
30 constexpr char kAnnotationValue2[] = "annotation_value2";
32 TEST(MakeAnnotationTest, KeyNamespaceAndName) {
33 auto annotation = MakeAnnotation(kAnnotationName1, "ignored");
34 EXPECT_EQ(annotation.key.namespace_, kGlobalNamespace);
35 EXPECT_EQ(annotation.key.value, kAnnotationName1);
38 TEST(MakeAnnotationTest, BooleanValue) {
39 auto annotation = MakeBoolAnnotation(kAnnotationName1, true);
40 ASSERT_TRUE(annotation.value.is_text());
41 EXPECT_EQ(annotation.value.text(), "true");
44 TEST(MakeAnnotationTest, IntegerValue) {
45 auto annotation = MakeIntAnnotation(kAnnotationName1, 12345678);
46 ASSERT_TRUE(annotation.value.is_text());
47 EXPECT_EQ(annotation.value.text(), "12345678");
50 TEST(MakeAnnotationTest, TextValue) {
51 constexpr char kSmallText[] = "This is a short text annotation";
52 auto annotation = MakeAnnotation(kAnnotationName1, kSmallText);
53 ASSERT_TRUE(annotation.value.is_text());
54 EXPECT_EQ(annotation.value.text(), kSmallText);
57 TEST(MakeAnnotationTest, LargeTextValue) {
58 const std::string large_text(1024, 'a');
59 auto annotation = MakeAnnotation(kAnnotationName1, large_text);
60 ASSERT_TRUE(annotation.value.is_buffer());
61 auto value = base::StringFromMemBuffer(annotation.value.buffer());
62 EXPECT_EQ(value, large_text);
65 // Basic verification that a single client can connect.
66 TEST_F(AnnotationsManagerTest, SingleClient) {
67 AnnotationsManager annotations;
69 fuchsia::element::AnnotationControllerPtr ptr;
70 annotations.Connect(ptr.NewRequest());
73 // Verifies that multiple clients can connect.
74 TEST_F(AnnotationsManagerTest, MultipleClients) {
75 AnnotationsManager annotations;
77 fuchsia::element::AnnotationControllerPtr ptr1;
78 annotations.Connect(ptr1.NewRequest());
79 fuchsia::element::AnnotationControllerPtr ptr2;
80 annotations.Connect(ptr2.NewRequest());
83 // Verifies that WatchAnnotations() hanging-get behaviour:
84 // - first call returns all annotations.
85 // - watch when nothing has changed "hangs" until the next change.
86 // - watch after a change returns immediately.
87 TEST_F(AnnotationsManagerTest, WatchAnnotationsHangingGet) {
88 AnnotationsManager annotations;
90 fuchsia::element::AnnotationControllerPtr controller;
91 annotations.Connect(controller.NewRequest());
93 // Dispatch an initial watch, that will return immediately.
94 bool received_annotations = false;
95 controller->WatchAnnotations([&received_annotations](auto annotations) {
96 EXPECT_EQ(annotations.response().annotations.size(), 0u);
97 received_annotations = true;
99 base::RunLoop().RunUntilIdle();
100 EXPECT_TRUE(received_annotations);
102 // Set a new watch, which should not return immediately, since nothing has
104 received_annotations = false;
105 controller->WatchAnnotations([&received_annotations](auto annotations) {
106 EXPECT_EQ(annotations.response().annotations.size(), 1u);
107 received_annotations = true;
109 base::RunLoop().RunUntilIdle();
110 EXPECT_FALSE(received_annotations);
112 // Set an annotation and spin the loop, to verify that the update is reported.
113 std::vector<fuchsia::element::Annotation> to_set;
114 to_set.push_back(MakeAnnotation(kAnnotationName1, kAnnotationValue1));
115 annotations.UpdateAnnotations(std::move(to_set));
116 base::RunLoop().RunUntilIdle();
117 EXPECT_TRUE(received_annotations);
119 // Change the annotation and spin the loop, then call WatchAnnotations() to
120 // verify that it returns immediately.
122 to_set.push_back(MakeAnnotation(kAnnotationName1, kAnnotationValue2));
123 annotations.UpdateAnnotations(std::move(to_set));
124 received_annotations = false;
125 controller->WatchAnnotations([&received_annotations](auto annotations) {
126 EXPECT_EQ(annotations.response().annotations.size(), 1u);
127 received_annotations = true;
129 base::RunLoop().RunUntilIdle();
130 EXPECT_TRUE(received_annotations);
133 // Verifies that WatchAnnotations() returns all annotations when any annotation
134 // is updated, not just the changed one.
135 TEST_F(AnnotationsManagerTest, WatchAnnotationsReturnsAllAnnotations) {
136 AnnotationsManager annotations;
138 fuchsia::element::AnnotationControllerPtr controller;
139 annotations.Connect(controller.NewRequest());
141 // Set multiple annotations.
142 std::vector<fuchsia::element::Annotation> annotations_to_set;
143 annotations_to_set.push_back(
144 MakeAnnotation(kAnnotationName1, kAnnotationValue1));
145 annotations_to_set.push_back(
146 MakeAnnotation(kAnnotationName2, kAnnotationValue2));
147 annotations.UpdateAnnotations(std::move(annotations_to_set));
149 // Dispatch an initial watch, that will return immediately.
150 bool received_annotations = false;
151 controller->WatchAnnotations([&received_annotations](auto annotations) {
152 EXPECT_EQ(annotations.response().annotations.size(), 2u);
153 received_annotations = true;
155 base::RunLoop().RunUntilIdle();
156 EXPECT_TRUE(received_annotations);
158 // Update a single annotation, then call WatchAnnotations() again to verify
159 // that all annotations including unchanged ones are returned.
160 std::vector<fuchsia::element::Annotation> to_set;
161 to_set.push_back(MakeAnnotation(kAnnotationName1, kAnnotationValue2));
162 annotations.UpdateAnnotations(std::move(to_set));
163 received_annotations = false;
164 controller->WatchAnnotations([&received_annotations](auto annotations) {
165 EXPECT_EQ(annotations.response().annotations.size(), 2u);
166 received_annotations = true;
168 base::RunLoop().RunUntilIdle();
169 EXPECT_TRUE(received_annotations);
172 // Verifies insertion of a new annotation via UpdateAnnotations().
173 TEST_F(AnnotationsManagerTest, UpdateAnnotationsSetsAnnotations) {
174 AnnotationsManager annotations;
176 auto all_annotations = annotations.GetAnnotations();
177 ASSERT_EQ(all_annotations.size(), 0u);
179 std::vector<fuchsia::element::Annotation> to_set;
180 to_set.push_back(MakeAnnotation(kAnnotationName1, kAnnotationValue1));
181 annotations.UpdateAnnotations(std::move(to_set));
183 all_annotations = annotations.GetAnnotations();
184 ASSERT_EQ(all_annotations.size(), 1u);
185 EXPECT_EQ(all_annotations[0].key.value, kAnnotationName1);
186 ASSERT_TRUE(all_annotations[0].value.is_text());
187 EXPECT_EQ(all_annotations[0].value.text(), kAnnotationValue1);
190 // Verifies update of existing annotation via UpdateAnnotations().
191 TEST_F(AnnotationsManagerTest, UpdateAnnotationsUpdatesAnnotations) {
192 AnnotationsManager annotations;
194 std::vector<fuchsia::element::Annotation> to_set;
195 to_set.push_back(MakeAnnotation(kAnnotationName1, kAnnotationValue1));
196 annotations.UpdateAnnotations(std::move(to_set));
197 to_set.push_back(MakeAnnotation(kAnnotationName1, kAnnotationValue2));
198 annotations.UpdateAnnotations(std::move(to_set));
200 auto all_annotations = annotations.GetAnnotations();
201 ASSERT_EQ(all_annotations.size(), 1u);
202 EXPECT_EQ(all_annotations[0].key.value, kAnnotationName1);
203 ASSERT_TRUE(all_annotations[0].value.is_text());
204 EXPECT_EQ(all_annotations[0].value.text(), kAnnotationValue2);
207 // Verifies that multiple annotations can be updated or insert in a single call.
208 TEST_F(AnnotationsManagerTest, UpdateAnnotationsMultipleAnnotations) {
209 AnnotationsManager annotations;
211 std::vector<fuchsia::element::Annotation> annotations_to_set;
212 annotations_to_set.push_back(
213 MakeAnnotation(kAnnotationName1, kAnnotationValue1));
214 annotations_to_set.push_back(
215 MakeAnnotation(kAnnotationName2, kAnnotationValue2));
216 annotations.UpdateAnnotations(std::move(annotations_to_set));
218 auto all_annotations = annotations.GetAnnotations();
219 ASSERT_EQ(all_annotations.size(), 2u);
220 EXPECT_EQ(all_annotations[0].key.value, kAnnotationName1);
221 ASSERT_TRUE(all_annotations[0].value.is_text());
222 EXPECT_EQ(all_annotations[0].value.text(), kAnnotationValue1);
223 EXPECT_EQ(all_annotations[1].key.value, kAnnotationName2);
224 ASSERT_TRUE(all_annotations[1].value.is_text());
225 EXPECT_EQ(all_annotations[1].value.text(), kAnnotationValue2);
228 // Verifies that the controller fails the operation if duplicate annotations
229 // appear in the same bulk-UpdateAnnotations operation.
230 TEST_F(AnnotationsManagerTest,
231 UpdateAnnotationsMultipleAnnotations_WithDuplicate) {
232 AnnotationsManager annotations;
234 std::vector<fuchsia::element::Annotation> annotations_to_set;
235 annotations_to_set.push_back(
236 MakeAnnotation(kAnnotationName1, kAnnotationValue1));
237 annotations_to_set.push_back(
238 MakeAnnotation(kAnnotationName1, kAnnotationValue2));
240 EXPECT_FALSE(annotations.UpdateAnnotations(std::move(annotations_to_set)));
245 } // namespace fuchsia_component_support