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/internal/notification_requests.h"
16 #include "google/cloud/storage/notification_event_type.h"
17 #include "google/cloud/storage/notification_payload_format.h"
18 #include <gmock/gmock.h>
19 
20 namespace google {
21 namespace cloud {
22 namespace storage {
23 inline namespace STORAGE_CLIENT_NS {
24 namespace internal {
25 namespace {
26 
27 using ::testing::HasSubstr;
28 
29 /// @test Verify that we parse JSON objects into NotificationMetadata objects.
TEST(NotificationRequestTest,Parse)30 TEST(NotificationRequestTest, Parse) {
31   auto actual = NotificationMetadataParser::FromString(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                     .value();
51   EXPECT_EQ(2, actual.custom_attributes().size());
52   EXPECT_TRUE(actual.has_custom_attribute("test-ca-1"));
53   EXPECT_EQ("value1", actual.custom_attribute("test-ca-1"));
54   EXPECT_TRUE(actual.has_custom_attribute("test-ca-2"));
55   EXPECT_EQ("value2", actual.custom_attribute("test-ca-2"));
56 
57   EXPECT_EQ("XYZ=", actual.etag());
58   EXPECT_EQ(4, actual.event_type_size());
59   EXPECT_EQ(4, actual.event_types().size());
60   EXPECT_EQ(event_type::ObjectFinalize(), actual.event_type(0));
61   EXPECT_EQ(event_type::ObjectMetadataUpdate(), actual.event_type(1));
62   EXPECT_EQ(event_type::ObjectDelete(), actual.event_type(2));
63   EXPECT_EQ(event_type::ObjectArchive(), actual.event_type(3));
64 
65   EXPECT_EQ("test-id-123", actual.id());
66   EXPECT_EQ("storage#notification", actual.kind());
67   EXPECT_EQ(payload_format::JsonApiV1(), actual.payload_format());
68   EXPECT_EQ(
69       "https://storage.googleapis.com/storage/v1/b/test-bucket/"
70       "notificationConfigs/test-id-123",
71       actual.self_link());
72   EXPECT_EQ("test-topic", actual.topic());
73 }
74 
75 /// @test Verify that we parse JSON objects into NotificationMetadata objects.
TEST(NotificationRequestTest,ParseFailure)76 TEST(NotificationRequestTest, ParseFailure) {
77   auto actual = internal::NotificationMetadataParser::FromString("{123");
78   EXPECT_FALSE(actual.ok());
79 }
80 
TEST(NotificationRequestTest,List)81 TEST(NotificationRequestTest, List) {
82   ListNotificationsRequest request("my-bucket");
83   request.set_multiple_options(UserProject("project-for-billing"));
84   EXPECT_EQ("my-bucket", request.bucket_name());
85 
86   std::ostringstream os;
87   os << request;
88   auto str = os.str();
89   EXPECT_THAT(str, HasSubstr("userProject=project-for-billing"));
90   EXPECT_THAT(str, HasSubstr("my-bucket"));
91 }
92 
TEST(NotificationRequestTest,ListResponse)93 TEST(NotificationRequestTest, ListResponse) {
94   std::string text = R"""({
95       "items": [{
96           "id": "test-notification-id-1",
97           "topic": "test-topic-1"
98       }, {
99           "id": "test-notification-id-2",
100           "topic": "test-topic-2"
101       }]})""";
102 
103   auto actual = ListNotificationsResponse::FromHttpResponse(text).value();
104   ASSERT_EQ(2UL, actual.items.size());
105   EXPECT_EQ("test-notification-id-1", actual.items.at(0).id());
106   EXPECT_EQ("test-topic-1", actual.items.at(0).topic());
107   EXPECT_EQ("test-notification-id-2", actual.items.at(1).id());
108   EXPECT_EQ("test-topic-2", actual.items.at(1).topic());
109 
110   std::ostringstream os;
111   os << actual;
112   auto str = os.str();
113   EXPECT_THAT(str, HasSubstr("id=test-notification-id-1"));
114   EXPECT_THAT(str, HasSubstr("id=test-notification-id-2"));
115   EXPECT_THAT(str, HasSubstr("ListNotificationResponse={"));
116   EXPECT_THAT(str, HasSubstr("NotificationMetadata={"));
117 }
118 
TEST(NotificationRequestTest,ListResponseParseFailure)119 TEST(NotificationRequestTest, ListResponseParseFailure) {
120   std::string text = R"""({123)""";
121 
122   StatusOr<ListNotificationsResponse> actual =
123       ListNotificationsResponse::FromHttpResponse(text);
124   EXPECT_FALSE(actual.ok());
125 }
126 
TEST(NotificationRequestTest,ListResponseParseFailureListElements)127 TEST(NotificationRequestTest, ListResponseParseFailureListElements) {
128   std::string text = R"""({
129       "items": [{
130           "id": "test-notification-id-1",
131           "topic": "test-topic-1"
132       }, "invalid-element"]})""";
133 
134   StatusOr<ListNotificationsResponse> actual =
135       ListNotificationsResponse::FromHttpResponse(text);
136   EXPECT_FALSE(actual.ok());
137 }
138 
TEST(CreateNotificationRequestTest,Create)139 TEST(CreateNotificationRequestTest, Create) {
140   NotificationMetadata notification =
141       NotificationMetadata()
142           .set_topic("test-topic-1")
143           .set_payload_format(payload_format::JsonApiV1())
144           .set_object_name_prefix("test-object-prefix-");
145   CreateNotificationRequest request("my-bucket", notification);
146   request.set_multiple_options(UserProject("project-for-billing"));
147   EXPECT_EQ("my-bucket", request.bucket_name());
148   EXPECT_EQ(notification.JsonPayloadForInsert(), request.json_payload());
149 
150   std::ostringstream os;
151   os << request;
152   auto str = os.str();
153   EXPECT_THAT(str, HasSubstr("userProject=project-for-billing"));
154   EXPECT_THAT(str, HasSubstr("my-bucket"));
155   EXPECT_THAT(str, HasSubstr(notification.JsonPayloadForInsert()));
156 }
157 
TEST(NotificationRequestTest,Get)158 TEST(NotificationRequestTest, Get) {
159   GetNotificationRequest request("my-bucket", "test-notification-id");
160   request.set_multiple_options(UserProject("my-project"));
161   EXPECT_EQ("my-bucket", request.bucket_name());
162   EXPECT_EQ("test-notification-id", request.notification_id());
163   std::ostringstream os;
164   os << request;
165   auto str = os.str();
166   EXPECT_THAT(str, HasSubstr("userProject=my-project"));
167   EXPECT_THAT(str, HasSubstr("my-bucket"));
168   EXPECT_THAT(str, HasSubstr("test-notification-id"));
169 }
170 
TEST(NotificationRequestTest,Delete)171 TEST(NotificationRequestTest, Delete) {
172   DeleteNotificationRequest request("my-bucket", "test-notification-id");
173   request.set_multiple_options(UserProject("my-project"));
174   EXPECT_EQ("my-bucket", request.bucket_name());
175   EXPECT_EQ("test-notification-id", request.notification_id());
176   std::ostringstream os;
177   os << request;
178   auto str = os.str();
179   EXPECT_THAT(str, HasSubstr("userProject=my-project"));
180   EXPECT_THAT(str, HasSubstr("my-bucket"));
181   EXPECT_THAT(str, HasSubstr("test-notification-id"));
182 }
183 
184 }  // namespace
185 }  // namespace internal
186 }  // namespace STORAGE_CLIENT_NS
187 }  // namespace storage
188 }  // namespace cloud
189 }  // namespace google
190