1 // Copyright 2020 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/pubsub/internal/publisher_logging.h"
16 #include "google/cloud/pubsub/testing/mock_publisher_stub.h"
17 #include "google/cloud/testing_util/assert_ok.h"
18 #include "google/cloud/testing_util/capture_log_lines_backend.h"
19 #include "absl/memory/memory.h"
20 #include <gmock/gmock.h>
21 
22 namespace google {
23 namespace cloud {
24 namespace pubsub_internal {
25 inline namespace GOOGLE_CLOUD_CPP_PUBSUB_NS {
26 namespace {
27 
28 using ::testing::AllOf;
29 using ::testing::Contains;
30 using ::testing::HasSubstr;
31 using ::testing::Return;
32 
33 class PublisherLoggingTest : public ::testing::Test {
34  protected:
SetUp()35   void SetUp() override {
36     backend_ =
37         std::make_shared<google::cloud::testing_util::CaptureLogLinesBackend>();
38     logger_id_ = google::cloud::LogSink::Instance().AddBackend(backend_);
39   }
40 
TearDown()41   void TearDown() override {
42     google::cloud::LogSink::Instance().RemoveBackend(logger_id_);
43     logger_id_ = 0;
44   }
45 
TransientError()46   static Status TransientError() {
47     return Status(StatusCode::kUnavailable, "try-again");
48   }
49 
50   std::shared_ptr<google::cloud::testing_util::CaptureLogLinesBackend> backend_;
51 
52  private:
53   long logger_id_ = 0;  // NOLINT(google-runtime-int)
54 };
55 
TEST_F(PublisherLoggingTest,CreateTopic)56 TEST_F(PublisherLoggingTest, CreateTopic) {
57   auto mock = std::make_shared<pubsub_testing::MockPublisherStub>();
58   EXPECT_CALL(*mock, CreateTopic)
59       .WillOnce(Return(make_status_or(google::pubsub::v1::Topic{})));
60   PublisherLogging stub(mock, TracingOptions{}.SetOptions("single_line_mode"));
61   grpc::ClientContext context;
62   google::pubsub::v1::Topic topic;
63   topic.set_name("test-topic-name");
64   auto status = stub.CreateTopic(context, topic);
65   EXPECT_STATUS_OK(status);
66   EXPECT_THAT(backend_->ClearLogLines(), Contains(HasSubstr("CreateTopic")));
67 }
68 
TEST_F(PublisherLoggingTest,GetTopic)69 TEST_F(PublisherLoggingTest, GetTopic) {
70   auto mock = std::make_shared<pubsub_testing::MockPublisherStub>();
71   EXPECT_CALL(*mock, GetTopic)
72       .WillOnce(Return(make_status_or(google::pubsub::v1::Topic{})));
73   PublisherLogging stub(mock, TracingOptions{}.SetOptions("single_line_mode"));
74   grpc::ClientContext context;
75   google::pubsub::v1::GetTopicRequest request;
76   request.set_topic("test-topic-name");
77   auto status = stub.GetTopic(context, request);
78   EXPECT_STATUS_OK(status);
79   EXPECT_THAT(backend_->ClearLogLines(), Contains(HasSubstr("GetTopic")));
80 }
81 
TEST_F(PublisherLoggingTest,UpdateTopic)82 TEST_F(PublisherLoggingTest, UpdateTopic) {
83   auto mock = std::make_shared<pubsub_testing::MockPublisherStub>();
84   EXPECT_CALL(*mock, UpdateTopic)
85       .WillOnce(Return(make_status_or(google::pubsub::v1::Topic{})));
86   PublisherLogging stub(mock, TracingOptions{}.SetOptions("single_line_mode"));
87   grpc::ClientContext context;
88   google::pubsub::v1::UpdateTopicRequest request;
89   request.mutable_topic()->set_name("test-topic-name");
90   auto status = stub.UpdateTopic(context, request);
91   EXPECT_STATUS_OK(status);
92   EXPECT_THAT(backend_->ClearLogLines(), Contains(HasSubstr("UpdateTopic")));
93 }
94 
TEST_F(PublisherLoggingTest,ListTopics)95 TEST_F(PublisherLoggingTest, ListTopics) {
96   auto mock = std::make_shared<pubsub_testing::MockPublisherStub>();
97   EXPECT_CALL(*mock, ListTopics)
98       .WillOnce(
99           Return(make_status_or(google::pubsub::v1::ListTopicsResponse{})));
100   PublisherLogging stub(mock, TracingOptions{}.SetOptions("single_line_mode"));
101   grpc::ClientContext context;
102   google::pubsub::v1::ListTopicsRequest request;
103   request.set_project("test-project-name");
104   auto status = stub.ListTopics(context, request);
105   EXPECT_STATUS_OK(status);
106   EXPECT_THAT(
107       backend_->ClearLogLines(),
108       Contains(AllOf(HasSubstr("ListTopics"), HasSubstr("test-project-name"))));
109 }
110 
TEST_F(PublisherLoggingTest,DeleteTopic)111 TEST_F(PublisherLoggingTest, DeleteTopic) {
112   auto mock = std::make_shared<pubsub_testing::MockPublisherStub>();
113   EXPECT_CALL(*mock, DeleteTopic).WillOnce(Return(Status{}));
114   PublisherLogging stub(mock, TracingOptions{}.SetOptions("single_line_mode"));
115   grpc::ClientContext context;
116   google::pubsub::v1::DeleteTopicRequest request;
117   request.set_topic("test-topic-name");
118   auto status = stub.DeleteTopic(context, request);
119   EXPECT_STATUS_OK(status);
120   EXPECT_THAT(
121       backend_->ClearLogLines(),
122       Contains(AllOf(HasSubstr("DeleteTopic"), HasSubstr("test-topic-name"))));
123 }
124 
TEST_F(PublisherLoggingTest,DetachSubscription)125 TEST_F(PublisherLoggingTest, DetachSubscription) {
126   auto mock = std::make_shared<pubsub_testing::MockPublisherStub>();
127   EXPECT_CALL(*mock, DetachSubscription)
128       .WillOnce(Return(
129           make_status_or(google::pubsub::v1::DetachSubscriptionResponse{})));
130   PublisherLogging stub(mock, TracingOptions{}.SetOptions("single_line_mode"));
131   grpc::ClientContext context;
132   google::pubsub::v1::DetachSubscriptionRequest request;
133   request.set_subscription("test-subscription-name");
134   auto status = stub.DetachSubscription(context, request);
135   EXPECT_STATUS_OK(status);
136   EXPECT_THAT(backend_->ClearLogLines(),
137               Contains(AllOf(HasSubstr("DetachSubscription"),
138                              HasSubstr("test-subscription-name"))));
139 }
140 
TEST_F(PublisherLoggingTest,ListTopicSubscriptions)141 TEST_F(PublisherLoggingTest, ListTopicSubscriptions) {
142   auto mock = std::make_shared<pubsub_testing::MockPublisherStub>();
143   EXPECT_CALL(*mock, ListTopicSubscriptions)
144       .WillOnce(Return(make_status_or(
145           google::pubsub::v1::ListTopicSubscriptionsResponse{})));
146   PublisherLogging stub(mock, TracingOptions{}.SetOptions("single_line_mode"));
147   grpc::ClientContext context;
148   google::pubsub::v1::ListTopicSubscriptionsRequest request;
149   request.set_topic("test-topic-name");
150   auto status = stub.ListTopicSubscriptions(context, request);
151   EXPECT_STATUS_OK(status);
152   EXPECT_THAT(backend_->ClearLogLines(),
153               Contains(AllOf(HasSubstr("ListTopicSubscriptions"),
154                              HasSubstr("test-topic-name"))));
155 }
156 
TEST_F(PublisherLoggingTest,ListTopicSnapshots)157 TEST_F(PublisherLoggingTest, ListTopicSnapshots) {
158   auto mock = std::make_shared<pubsub_testing::MockPublisherStub>();
159   EXPECT_CALL(*mock, ListTopicSnapshots)
160       .WillOnce(Return(
161           make_status_or(google::pubsub::v1::ListTopicSnapshotsResponse{})));
162   PublisherLogging stub(mock, TracingOptions{}.SetOptions("single_line_mode"));
163   grpc::ClientContext context;
164   google::pubsub::v1::ListTopicSnapshotsRequest request;
165   request.set_topic("test-topic-name");
166   auto status = stub.ListTopicSnapshots(context, request);
167   EXPECT_STATUS_OK(status);
168   EXPECT_THAT(backend_->ClearLogLines(),
169               Contains(AllOf(HasSubstr("ListTopicSnapshots"),
170                              HasSubstr("test-topic-name"))));
171 }
172 
TEST_F(PublisherLoggingTest,AsyncPublish)173 TEST_F(PublisherLoggingTest, AsyncPublish) {
174   auto mock = std::make_shared<pubsub_testing::MockPublisherStub>();
175   EXPECT_CALL(*mock, AsyncPublish)
176       .WillOnce([](google::cloud::CompletionQueue&,
177                    std::unique_ptr<grpc::ClientContext>,
178                    google::pubsub::v1::PublishRequest const&) {
179         return make_ready_future(
180             make_status_or(google::pubsub::v1::PublishResponse{}));
181       });
182   PublisherLogging stub(mock, TracingOptions{}.SetOptions("single_line_mode"));
183   google::cloud::CompletionQueue cq;
184   google::pubsub::v1::PublishRequest request;
185   request.set_topic("test-topic-name");
186   auto status =
187       stub.AsyncPublish(cq, absl::make_unique<grpc::ClientContext>(), request)
188           .get();
189   EXPECT_STATUS_OK(status);
190   EXPECT_THAT(
191       backend_->ClearLogLines(),
192       Contains(AllOf(HasSubstr("AsyncPublish"), HasSubstr("test-topic-name"))));
193 }
194 
195 }  // namespace
196 }  // namespace GOOGLE_CLOUD_CPP_PUBSUB_NS
197 }  // namespace pubsub_internal
198 }  // namespace cloud
199 }  // namespace google
200