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_requests.h"
17 #include "google/cloud/storage/notification_event_type.h"
18 #include "google/cloud/storage/notification_payload_format.h"
19 #include <gmock/gmock.h>
20
21 namespace google {
22 namespace cloud {
23 namespace storage {
24 inline namespace STORAGE_CLIENT_NS {
25 namespace {
26
27 using ::testing::HasSubstr;
28
CreateNotificationMetadataForTest()29 NotificationMetadata CreateNotificationMetadataForTest() {
30 std::string text = R"""({
31 "custom_attributes": {
32 "test-ca-1": "value1",
33 "test-ca-2": "value2"
34 },
35 "etag": "XYZ=",
36 "event_types": [
37 "OBJECT_FINALIZE",
38 "OBJECT_METADATA_UPDATE",
39 "OBJECT_DELETE",
40 "OBJECT_ARCHIVE"
41 ],
42 "id": "test-id-123",
43 "kind": "storage#notification",
44 "object_name_prefix": "test-prefix-",
45 "payload_format": "JSON_API_V1",
46 "selfLink": "https://storage.googleapis.com/storage/v1/b/test-bucket/notificationConfigs/test-id-123",
47 "topic": "test-topic"
48 })""";
49 return internal::NotificationMetadataParser::FromString(text).value();
50 }
51
52 /// @test Verifies NotificationMetadata iostream operator.
TEST(NotificationMetadataTest,IOStream)53 TEST(NotificationMetadataTest, IOStream) {
54 auto notification = CreateNotificationMetadataForTest();
55 std::ostringstream os;
56 os << notification;
57 auto actual = os.str();
58 EXPECT_THAT(actual, HasSubstr("test-ca-1"));
59 EXPECT_THAT(actual, HasSubstr("value1"));
60 EXPECT_THAT(actual, HasSubstr("test-ca-2"));
61 EXPECT_THAT(actual, HasSubstr("value2"));
62 EXPECT_THAT(actual, HasSubstr("XYZ="));
63 EXPECT_THAT(actual, HasSubstr(event_type::ObjectFinalize()));
64 EXPECT_THAT(actual, HasSubstr(event_type::ObjectMetadataUpdate()));
65 EXPECT_THAT(actual, HasSubstr(event_type::ObjectDelete()));
66 EXPECT_THAT(actual, HasSubstr(event_type::ObjectArchive()));
67 EXPECT_THAT(actual, HasSubstr("test-id-123"));
68 EXPECT_THAT(actual, HasSubstr("storage#notification"));
69 EXPECT_THAT(actual, HasSubstr(payload_format::JsonApiV1()));
70 EXPECT_THAT(actual, HasSubstr("https://storage.googleapis.com/"));
71 EXPECT_THAT(actual, HasSubstr("test-topic"));
72 }
73
74 /// @test Verifies NotificationMetadata::JsonPayloadForInsert.
TEST(NotificationMetadataTest,JsonPayloadForInsert)75 TEST(NotificationMetadataTest, JsonPayloadForInsert) {
76 auto notification = CreateNotificationMetadataForTest();
77 auto text = notification.JsonPayloadForInsert();
78 auto actual = nlohmann::json::parse(text);
79
80 nlohmann::json expected_attributes{
81 {"test-ca-1", "value1"},
82 {"test-ca-2", "value2"},
83 };
84 std::vector<std::string> expected_event_types{
85 "OBJECT_FINALIZE",
86 "OBJECT_METADATA_UPDATE",
87 "OBJECT_DELETE",
88 "OBJECT_ARCHIVE",
89 };
90 nlohmann::json expected{
91 {"custom_attributes", expected_attributes},
92 {"topic", "test-topic"},
93 {"payload_format", "JSON_API_V1"},
94 {"event_types", expected_event_types},
95 {"object_name_prefix", "test-prefix-"},
96 };
97
98 auto diff = nlohmann::json::diff(expected, actual);
99 EXPECT_EQ("[]", diff.dump()) << " text=" << text;
100 }
101
102 /// @test Verify we can make changes to the custom attributes.
TEST(NotificationMetadataTest,MutableCustomAttributes)103 TEST(NotificationMetadataTest, MutableCustomAttributes) {
104 auto expected = CreateNotificationMetadataForTest();
105 auto copy = expected;
106 EXPECT_EQ(expected, copy);
107 copy.mutable_custom_attributes().emplace("test-ca-3", "value3");
108 EXPECT_TRUE(copy.has_custom_attribute("test-ca-3"));
109 EXPECT_EQ("value3", copy.custom_attribute("test-ca-3"));
110 EXPECT_NE(expected, copy);
111 }
112
113 /// @test Verify we can delete custom attributes.
TEST(NotificationMetadataTest,DeleteCustomAttribute)114 TEST(NotificationMetadataTest, DeleteCustomAttribute) {
115 auto expected = CreateNotificationMetadataForTest();
116 auto copy = expected;
117 EXPECT_EQ(expected, copy);
118 copy.delete_custom_attribute("test-ca-1");
119 EXPECT_FALSE(copy.has_custom_attribute("test-ca-1"));
120 EXPECT_NE(expected, copy);
121 }
122
123 /// @test Verify we can update and insert custom attributes.
TEST(NotificationMetadataTest,UpsertCustomAttribute)124 TEST(NotificationMetadataTest, UpsertCustomAttribute) {
125 auto expected = CreateNotificationMetadataForTest();
126 auto copy = expected;
127 EXPECT_EQ(expected, copy);
128 EXPECT_TRUE(copy.has_custom_attribute("test-ca-1"));
129 EXPECT_EQ("value1", copy.custom_attribute("test-ca-1"));
130 copy.upsert_custom_attributes("test-ca-3", "value3");
131 copy.upsert_custom_attributes("test-ca-1", "value1-updated");
132 EXPECT_EQ("value1-updated", copy.custom_attribute("test-ca-1"));
133 EXPECT_EQ("value3", copy.custom_attribute("test-ca-3"));
134 EXPECT_NE(expected, copy);
135 }
136
137 /// @test Verify we can make changes to the event types.
TEST(NotificationMetadataTest,MutableEventTypes)138 TEST(NotificationMetadataTest, MutableEventTypes) {
139 auto expected = CreateNotificationMetadataForTest();
140 auto copy = expected;
141 EXPECT_EQ(expected, copy);
142 copy.mutable_event_types().pop_back();
143 EXPECT_EQ(3, copy.event_type_size());
144 EXPECT_NE(expected, copy);
145 }
146
147 /// @test Verify we can make changes to the event types.
TEST(NotificationMetadataTest,AppendEventTypes)148 TEST(NotificationMetadataTest, AppendEventTypes) {
149 auto expected = CreateNotificationMetadataForTest();
150 auto copy = expected;
151 EXPECT_EQ(expected, copy);
152 copy.mutable_event_types().clear();
153 EXPECT_EQ(0, copy.event_type_size());
154 copy.append_event_type(event_type::ObjectFinalize());
155 EXPECT_EQ(1, copy.event_type_size());
156 EXPECT_EQ("OBJECT_FINALIZE", copy.event_type(0));
157 EXPECT_NE(expected, copy);
158 }
159
160 /// @test Verify we can make changes to the object name prefix.
TEST(NotificationMetadataTest,SetObjectNamePrefix)161 TEST(NotificationMetadataTest, SetObjectNamePrefix) {
162 auto expected = CreateNotificationMetadataForTest();
163 auto copy = expected;
164 EXPECT_EQ(expected, copy);
165 EXPECT_EQ("test-prefix-", copy.object_name_prefix());
166 copy.set_object_name_prefix("another-prefix/");
167 EXPECT_EQ("another-prefix/", copy.object_name_prefix());
168 EXPECT_NE(expected, copy);
169 }
170
171 /// @test Verify we can make changes to the payload format.
TEST(NotificationMetadataTest,SetPayloadFormat)172 TEST(NotificationMetadataTest, SetPayloadFormat) {
173 auto expected = CreateNotificationMetadataForTest();
174 auto copy = expected;
175 EXPECT_EQ(expected, copy);
176 EXPECT_EQ("JSON_API_V1", copy.payload_format());
177 copy.set_payload_format(payload_format::None());
178 EXPECT_EQ("NONE", copy.payload_format());
179 EXPECT_NE(expected, copy);
180 }
181
182 /// @test Verify we can make changes to the topic.
TEST(NotificationMetadataTest,SetTopic)183 TEST(NotificationMetadataTest, SetTopic) {
184 auto expected = CreateNotificationMetadataForTest();
185 auto copy = expected;
186 EXPECT_EQ(expected, copy);
187 EXPECT_EQ("test-topic", copy.topic());
188 copy.set_topic("another-topic");
189 EXPECT_EQ("another-topic", copy.topic());
190 EXPECT_NE(expected, copy);
191 }
192
193 } // namespace
194 } // namespace STORAGE_CLIENT_NS
195 } // namespace storage
196 } // namespace cloud
197 } // namespace google
198