1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "google/cloud/storage/notification_metadata.h"
16 #include "google/cloud/storage/internal/notification_metadata_parser.h"
17 #include "google/cloud/storage/internal/notification_requests.h"
18 #include "google/cloud/storage/notification_event_type.h"
19 #include "google/cloud/storage/notification_payload_format.h"
20 #include <gmock/gmock.h>
21
22 namespace google {
23 namespace cloud {
24 namespace storage {
25 inline namespace STORAGE_CLIENT_NS {
26 namespace {
27
28 using ::testing::HasSubstr;
29
CreateNotificationMetadataForTest()30 NotificationMetadata CreateNotificationMetadataForTest() {
31 std::string text = R"""({
32 "custom_attributes": {
33 "test-ca-1": "value1",
34 "test-ca-2": "value2"
35 },
36 "etag": "XYZ=",
37 "event_types": [
38 "OBJECT_FINALIZE",
39 "OBJECT_METADATA_UPDATE",
40 "OBJECT_DELETE",
41 "OBJECT_ARCHIVE"
42 ],
43 "id": "test-id-123",
44 "kind": "storage#notification",
45 "object_name_prefix": "test-prefix-",
46 "payload_format": "JSON_API_V1",
47 "selfLink": "https://storage.googleapis.com/storage/v1/b/test-bucket/notificationConfigs/test-id-123",
48 "topic": "test-topic"
49 })""";
50 return internal::NotificationMetadataParser::FromString(text).value();
51 }
52
53 /// @test Verifies NotificationMetadata iostream operator.
TEST(NotificationMetadataTest,IOStream)54 TEST(NotificationMetadataTest, IOStream) {
55 auto notification = CreateNotificationMetadataForTest();
56 std::ostringstream os;
57 os << notification;
58 auto actual = os.str();
59 EXPECT_THAT(actual, HasSubstr("test-ca-1"));
60 EXPECT_THAT(actual, HasSubstr("value1"));
61 EXPECT_THAT(actual, HasSubstr("test-ca-2"));
62 EXPECT_THAT(actual, HasSubstr("value2"));
63 EXPECT_THAT(actual, HasSubstr("XYZ="));
64 EXPECT_THAT(actual, HasSubstr(event_type::ObjectFinalize()));
65 EXPECT_THAT(actual, HasSubstr(event_type::ObjectMetadataUpdate()));
66 EXPECT_THAT(actual, HasSubstr(event_type::ObjectDelete()));
67 EXPECT_THAT(actual, HasSubstr(event_type::ObjectArchive()));
68 EXPECT_THAT(actual, HasSubstr("test-id-123"));
69 EXPECT_THAT(actual, HasSubstr("storage#notification"));
70 EXPECT_THAT(actual, HasSubstr(payload_format::JsonApiV1()));
71 EXPECT_THAT(actual, HasSubstr("https://storage.googleapis.com/"));
72 EXPECT_THAT(actual, HasSubstr("test-topic"));
73 }
74
75 /// @test Verifies NotificationMetadata::JsonPayloadForInsert.
TEST(NotificationMetadataTest,JsonPayloadForInsert)76 TEST(NotificationMetadataTest, JsonPayloadForInsert) {
77 auto notification = CreateNotificationMetadataForTest();
78 auto text = notification.JsonPayloadForInsert();
79 auto actual = nlohmann::json::parse(text);
80
81 nlohmann::json expected_attributes{
82 {"test-ca-1", "value1"},
83 {"test-ca-2", "value2"},
84 };
85 std::vector<std::string> expected_event_types{
86 "OBJECT_FINALIZE",
87 "OBJECT_METADATA_UPDATE",
88 "OBJECT_DELETE",
89 "OBJECT_ARCHIVE",
90 };
91 nlohmann::json expected{
92 {"custom_attributes", expected_attributes},
93 {"topic", "test-topic"},
94 {"payload_format", "JSON_API_V1"},
95 {"event_types", expected_event_types},
96 {"object_name_prefix", "test-prefix-"},
97 };
98
99 auto diff = nlohmann::json::diff(expected, actual);
100 EXPECT_EQ("[]", diff.dump()) << " text=" << text;
101 }
102
103 /// @test Verify we can make changes to the custom attributes.
TEST(NotificationMetadataTest,MutableCustomAttributes)104 TEST(NotificationMetadataTest, MutableCustomAttributes) {
105 auto expected = CreateNotificationMetadataForTest();
106 auto copy = expected;
107 EXPECT_EQ(expected, copy);
108 copy.mutable_custom_attributes().emplace("test-ca-3", "value3");
109 EXPECT_TRUE(copy.has_custom_attribute("test-ca-3"));
110 EXPECT_EQ("value3", copy.custom_attribute("test-ca-3"));
111 EXPECT_NE(expected, copy);
112 }
113
114 /// @test Verify we can delete custom attributes.
TEST(NotificationMetadataTest,DeleteCustomAttribute)115 TEST(NotificationMetadataTest, DeleteCustomAttribute) {
116 auto expected = CreateNotificationMetadataForTest();
117 auto copy = expected;
118 EXPECT_EQ(expected, copy);
119 copy.delete_custom_attribute("test-ca-1");
120 EXPECT_FALSE(copy.has_custom_attribute("test-ca-1"));
121 EXPECT_NE(expected, copy);
122 }
123
124 /// @test Verify we can update and insert custom attributes.
TEST(NotificationMetadataTest,UpsertCustomAttribute)125 TEST(NotificationMetadataTest, UpsertCustomAttribute) {
126 auto expected = CreateNotificationMetadataForTest();
127 auto copy = expected;
128 EXPECT_EQ(expected, copy);
129 EXPECT_TRUE(copy.has_custom_attribute("test-ca-1"));
130 EXPECT_EQ("value1", copy.custom_attribute("test-ca-1"));
131 copy.upsert_custom_attributes("test-ca-3", "value3");
132 copy.upsert_custom_attributes("test-ca-1", "value1-updated");
133 EXPECT_EQ("value1-updated", copy.custom_attribute("test-ca-1"));
134 EXPECT_EQ("value3", copy.custom_attribute("test-ca-3"));
135 EXPECT_NE(expected, copy);
136 }
137
138 /// @test Verify we can make changes to the event types.
TEST(NotificationMetadataTest,MutableEventTypes)139 TEST(NotificationMetadataTest, MutableEventTypes) {
140 auto expected = CreateNotificationMetadataForTest();
141 auto copy = expected;
142 EXPECT_EQ(expected, copy);
143 copy.mutable_event_types().pop_back();
144 EXPECT_EQ(3, copy.event_type_size());
145 EXPECT_NE(expected, copy);
146 }
147
148 /// @test Verify we can make changes to the event types.
TEST(NotificationMetadataTest,AppendEventTypes)149 TEST(NotificationMetadataTest, AppendEventTypes) {
150 auto expected = CreateNotificationMetadataForTest();
151 auto copy = expected;
152 EXPECT_EQ(expected, copy);
153 copy.mutable_event_types().clear();
154 EXPECT_EQ(0, copy.event_type_size());
155 copy.append_event_type(event_type::ObjectFinalize());
156 EXPECT_EQ(1, copy.event_type_size());
157 EXPECT_EQ("OBJECT_FINALIZE", copy.event_type(0));
158 EXPECT_NE(expected, copy);
159 }
160
161 /// @test Verify we can make changes to the object name prefix.
TEST(NotificationMetadataTest,SetObjectNamePrefix)162 TEST(NotificationMetadataTest, SetObjectNamePrefix) {
163 auto expected = CreateNotificationMetadataForTest();
164 auto copy = expected;
165 EXPECT_EQ(expected, copy);
166 EXPECT_EQ("test-prefix-", copy.object_name_prefix());
167 copy.set_object_name_prefix("another-prefix/");
168 EXPECT_EQ("another-prefix/", copy.object_name_prefix());
169 EXPECT_NE(expected, copy);
170 }
171
172 /// @test Verify we can make changes to the payload format.
TEST(NotificationMetadataTest,SetPayloadFormat)173 TEST(NotificationMetadataTest, SetPayloadFormat) {
174 auto expected = CreateNotificationMetadataForTest();
175 auto copy = expected;
176 EXPECT_EQ(expected, copy);
177 EXPECT_EQ("JSON_API_V1", copy.payload_format());
178 copy.set_payload_format(payload_format::None());
179 EXPECT_EQ("NONE", copy.payload_format());
180 EXPECT_NE(expected, copy);
181 }
182
183 /// @test Verify we can make changes to the topic.
TEST(NotificationMetadataTest,SetTopic)184 TEST(NotificationMetadataTest, SetTopic) {
185 auto expected = CreateNotificationMetadataForTest();
186 auto copy = expected;
187 EXPECT_EQ(expected, copy);
188 EXPECT_EQ("test-topic", copy.topic());
189 copy.set_topic("another-topic");
190 EXPECT_EQ("another-topic", copy.topic());
191 EXPECT_NE(expected, copy);
192 }
193
194 } // namespace
195 } // namespace STORAGE_CLIENT_NS
196 } // namespace storage
197 } // namespace cloud
198 } // namespace google
199