@@ -25,7 +25,9 @@ namespace {
2525
2626using ::google::cloud::spanner_mocks::MockDatabaseAdminConnection;
2727using ::testing::_;
28+ using ::testing::AtLeast;
2829using ::testing::ElementsAre;
30+ using ::testing::HasSubstr;
2931namespace gcsa = ::google::spanner::admin::database::v1;
3032
3133// / @test Verify DatabaseAdminClient uses CreateDatabase() correctly.
@@ -186,10 +188,130 @@ TEST(DatabaseAdminClientTest, SetIamPolicy) {
186188 return p.policy ;
187189 });
188190 DatabaseAdminClient client (std::move (mock));
189- auto response = client.SetIamPolicy (expected_db, {});
191+ auto response = client.SetIamPolicy (expected_db, google::iam::v1::Policy {});
190192 EXPECT_STATUS_OK (response);
191193}
192194
195+ TEST (DatabaseAdminClientTest, SetIamPolicyOccGetFailure) {
196+ Database const db (" test-project" , " test-instance" , " test-database" );
197+ auto mock = std::make_shared<MockDatabaseAdminConnection>();
198+ EXPECT_CALL (*mock, GetIamPolicy (_))
199+ .WillOnce ([&db](DatabaseAdminConnection::GetIamPolicyParams const & p) {
200+ EXPECT_EQ (db, p.database );
201+ return Status (StatusCode::kPermissionDenied , " uh-oh" );
202+ });
203+
204+ DatabaseAdminClient client (mock);
205+ auto actual = client.SetIamPolicy (db, [](google::iam::v1::Policy const &) {
206+ return optional<google::iam::v1::Policy>{};
207+ });
208+ EXPECT_EQ (StatusCode::kPermissionDenied , actual.status ().code ());
209+ }
210+
211+ TEST (DatabaseAdminClientTest, SetIamPolicyOccNoUpdates) {
212+ Database const db (" test-project" , " test-instance" , " test-database" );
213+ auto mock = std::make_shared<MockDatabaseAdminConnection>();
214+ EXPECT_CALL (*mock, GetIamPolicy (_))
215+ .WillOnce ([&db](DatabaseAdminConnection::GetIamPolicyParams const & p) {
216+ EXPECT_EQ (db, p.database );
217+ google::iam::v1::Policy r;
218+ r.set_etag (" test-etag" );
219+ return r;
220+ });
221+ EXPECT_CALL (*mock, SetIamPolicy (_)).Times (0 );
222+
223+ DatabaseAdminClient client (mock);
224+ auto actual = client.SetIamPolicy (db, [](google::iam::v1::Policy const & p) {
225+ EXPECT_EQ (" test-etag" , p.etag ());
226+ return optional<google::iam::v1::Policy>{};
227+ });
228+ ASSERT_STATUS_OK (actual);
229+ EXPECT_EQ (" test-etag" , actual->etag ());
230+ }
231+
232+ std::unique_ptr<TransactionRerunPolicy> RerunPolicyForTesting () {
233+ return LimitedErrorCountTransactionRerunPolicy (/* maximum_failures=*/ 3 )
234+ .clone ();
235+ }
236+
237+ std::unique_ptr<BackoffPolicy> BackoffPolicyForTesting () {
238+ return ExponentialBackoffPolicy (
239+ /* initial_delay=*/ std::chrono::microseconds (1 ),
240+ /* maximum_delay=*/ std::chrono::microseconds (1 ), /* scaling=*/ 2.0 )
241+ .clone ();
242+ }
243+
244+ TEST (DatabaseAdminClientTest, SetIamPolicyOccRetryAborted) {
245+ Database const db (" test-project" , " test-instance" , " test-database" );
246+ auto mock = std::make_shared<MockDatabaseAdminConnection>();
247+ EXPECT_CALL (*mock, GetIamPolicy (_))
248+ .WillOnce ([&db](DatabaseAdminConnection::GetIamPolicyParams const & p) {
249+ EXPECT_EQ (db, p.database );
250+ google::iam::v1::Policy r;
251+ r.set_etag (" test-etag-1" );
252+ return r;
253+ })
254+ .WillOnce ([&db](DatabaseAdminConnection::GetIamPolicyParams const & p) {
255+ EXPECT_EQ (db, p.database );
256+ google::iam::v1::Policy r;
257+ r.set_etag (" test-etag-2" );
258+ return r;
259+ });
260+ EXPECT_CALL (*mock, SetIamPolicy (_))
261+ .WillOnce ([&db](DatabaseAdminConnection::SetIamPolicyParams const & p) {
262+ EXPECT_EQ (db, p.database );
263+ EXPECT_EQ (" test-etag-1" , p.policy .etag ());
264+ return Status (StatusCode::kAborted , " aborted" );
265+ })
266+ .WillOnce ([&db](DatabaseAdminConnection::SetIamPolicyParams const & p) {
267+ EXPECT_EQ (db, p.database );
268+ EXPECT_EQ (" test-etag-2" , p.policy .etag ());
269+ google::iam::v1::Policy r;
270+ r.set_etag (" test-etag-3" );
271+ return r;
272+ });
273+
274+ DatabaseAdminClient client (mock);
275+ int counter = 0 ;
276+ auto actual = client.SetIamPolicy (
277+ db,
278+ [&counter](google::iam::v1::Policy p) {
279+ EXPECT_EQ (" test-etag-" + std::to_string (++counter), p.etag ());
280+ return p;
281+ },
282+ RerunPolicyForTesting (), BackoffPolicyForTesting ());
283+ ASSERT_STATUS_OK (actual);
284+ EXPECT_EQ (" test-etag-3" , actual->etag ());
285+ }
286+
287+ TEST (DatabaseAdminClientTest, SetIamPolicyOccRetryAbortedTooManyFailures) {
288+ Database const db (" test-project" , " test-instance" , " test-database" );
289+ auto mock = std::make_shared<MockDatabaseAdminConnection>();
290+ EXPECT_CALL (*mock, GetIamPolicy (_))
291+ .WillRepeatedly (
292+ [&db](DatabaseAdminConnection::GetIamPolicyParams const & p) {
293+ EXPECT_EQ (db, p.database );
294+ google::iam::v1::Policy r;
295+ r.set_etag (" test-etag-1" );
296+ return r;
297+ });
298+ EXPECT_CALL (*mock, SetIamPolicy (_))
299+ .Times (AtLeast (2 ))
300+ .WillRepeatedly (
301+ [&db](DatabaseAdminConnection::SetIamPolicyParams const & p) {
302+ EXPECT_EQ (db, p.database );
303+ EXPECT_EQ (" test-etag-1" , p.policy .etag ());
304+ return Status (StatusCode::kAborted , " test-msg" );
305+ });
306+
307+ DatabaseAdminClient client (mock);
308+ auto actual = client.SetIamPolicy (
309+ db, [](google::iam::v1::Policy p) { return p; }, RerunPolicyForTesting (),
310+ BackoffPolicyForTesting ());
311+ EXPECT_EQ (StatusCode::kAborted , actual.status ().code ());
312+ EXPECT_THAT (actual.status ().message (), HasSubstr (" test-msg" ));
313+ }
314+
193315// / @test Verify DatabaseAdminClient uses TestIamPermissions() correctly.
194316TEST (DatabaseAdminClientTest, TestIamPermissions) {
195317 auto mock = std::make_shared<MockDatabaseAdminConnection>();
0 commit comments