Repository: googleapis/java-storage
Pull request #1384 (2022-05-11 17:56:40)

feat: add skeleton implementation of GrpcStorageImpl#getServiceAccount
* Add conversion for com.google.storage.v2.ServiceAccount
* Add property test to ensure round trip decode -> endode -> decode succeeds
* Add ServiceAccountArbitraryProvider




Patch:
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java
index 3eb23801..234a1dd7 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java
@@ -33,7 +33,8 @@ final class GrpcConversions {
   private final Codec<?, ?> bucketAclCodec = Codec.of(Utils::todo, Utils::todo);
   private final Codec<?, ?> hmacKeyMetadataCodec = Codec.of(Utils::todo, Utils::todo);
   private final Codec<?, ?> hmacKeyCodec = Codec.of(Utils::todo, Utils::todo);
-  private final Codec<?, ?> serviceAccountCodec = Codec.of(Utils::todo, Utils::todo);
+  private final Codec<ServiceAccount, com.google.storage.v2.ServiceAccount> serviceAccountCodec =
+      Codec.of(this::serviceAccountEncode, this::serviceAccountDecode);
   private final Codec<?, ?> corsCodec = Codec.of(Utils::todo, Utils::todo);
   private final Codec<?, ?> loggingCodec = Codec.of(Utils::todo, Utils::todo);
   private final Codec<?, ?> iamConfigurationCodec = Codec.of(Utils::todo, Utils::todo);
@@ -68,8 +69,8 @@ final class GrpcConversions {
     return todo();
   }
 
-  Codec<?, ?> serviceAccount() {
-    return todo();
+  Codec<ServiceAccount, com.google.storage.v2.ServiceAccount> serviceAccount() {
+    return serviceAccountCodec;
   }
 
   Codec<?, ?> cors() {
@@ -147,4 +148,14 @@ final class GrpcConversions {
     // TODO(frnakyn): Add DefaultObjectAcl decoder support
     return to.build();
   }
+
+  private com.google.storage.v2.ServiceAccount serviceAccountEncode(ServiceAccount from) {
+    return com.google.storage.v2.ServiceAccount.newBuilder()
+        .setEmailAddress(from.getEmail())
+        .build();
+  }
+
+  private ServiceAccount serviceAccountDecode(com.google.storage.v2.ServiceAccount from) {
+    return ServiceAccount.of(from.getEmailAddress());
+  }
 }
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageImpl.java
index e5a3ec5b..48663f3c 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageImpl.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageImpl.java
@@ -32,6 +32,7 @@ import com.google.cloud.storage.PostPolicyV4.PostConditionsV4;
 import com.google.cloud.storage.PostPolicyV4.PostFieldsV4;
 import com.google.cloud.storage.spi.v1.StorageRpc;
 import com.google.storage.v2.GetBucketRequest;
+import com.google.storage.v2.GetServiceAccountRequest;
 import com.google.storage.v2.stub.GrpcStorageStub;
 import java.io.IOException;
 import java.io.InputStream;
@@ -460,7 +461,11 @@ final class GrpcStorageImpl extends BaseService<StorageOptions> implements Stora
 
   @Override
   public ServiceAccount getServiceAccount(String projectId) {
-    return todo();
+    GetServiceAccountRequest req =
+        GetServiceAccountRequest.newBuilder().setProject(projectId).build();
+    com.google.storage.v2.ServiceAccount resp =
+        grpcStorageStub.getServiceAccountCallable().call(req);
+    return codecs.serviceAccount().decode(resp);
   }
 
   @Override


Test patch:
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ServiceAccountPropertyTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ServiceAccountPropertyTest.java
new file mode 100644
index 00000000..d0daf563
--- /dev/null
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ServiceAccountPropertyTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.storage;
+
+import static com.google.cloud.storage.JqwikTest.report;
+import static com.google.common.truth.Truth.assertThat;
+import static net.jqwik.api.providers.TypeUsage.of;
+
+import com.google.cloud.storage.Conversions.Codec;
+import net.jqwik.api.Example;
+import net.jqwik.api.ForAll;
+import net.jqwik.api.Property;
+
+final class ServiceAccountPropertyTest {
+
+  @Example
+  void edgeCases() {
+    report(of(com.google.storage.v2.ServiceAccount.class));
+  }
+
+  @Property
+  void codecCanRoundTrip(@ForAll com.google.storage.v2.ServiceAccount sa) {
+    Codec<ServiceAccount, com.google.storage.v2.ServiceAccount> codec =
+        Conversions.grpc().serviceAccount();
+    ServiceAccount decode = codec.decode(sa);
+
+    assertThat(decode.getEmail()).isEqualTo(sa.getEmailAddress());
+
+    com.google.storage.v2.ServiceAccount encode = codec.encode(decode);
+    assertThat(encode).isEqualTo(sa);
+  }
+}
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/ServiceAccountArbitraryProvider.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/ServiceAccountArbitraryProvider.java
new file mode 100644
index 00000000..0a223ea4
--- /dev/null
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/ServiceAccountArbitraryProvider.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.storage.jqwik;
+
+import com.google.storage.v2.ServiceAccount;
+import java.util.Collections;
+import java.util.Set;
+import net.jqwik.api.Arbitrary;
+import net.jqwik.api.providers.ArbitraryProvider;
+import net.jqwik.api.providers.TypeUsage;
+import net.jqwik.web.api.EmailArbitrary;
+import net.jqwik.web.api.Web;
+
+public final class ServiceAccountArbitraryProvider implements ArbitraryProvider {
+
+  @Override
+  public boolean canProvideFor(TypeUsage targetType) {
+    return targetType.isOfType(ServiceAccount.class);
+  }
+
+  @Override
+  public Set<Arbitrary<?>> provideFor(TypeUsage targetType, SubtypeProvider subtypeProvider) {
+    EmailArbitrary emails = Web.emails();
+    return Collections.singleton(
+        emails.map(e -> ServiceAccount.newBuilder().setEmailAddress(e).build()));
+  }
+}
diff --git a/google-cloud-storage/src/test/resources/META-INF/services/net.jqwik.api.providers.ArbitraryProvider b/google-cloud-storage/src/test/resources/META-INF/services/net.jqwik.api.providers.ArbitraryProvider
index 755775cb..8433134d 100644
--- a/google-cloud-storage/src/test/resources/META-INF/services/net.jqwik.api.providers.ArbitraryProvider
+++ b/google-cloud-storage/src/test/resources/META-INF/services/net.jqwik.api.providers.ArbitraryProvider
@@ -15,4 +15,5 @@
 #
 
 com.google.cloud.storage.jqwik.ObjectArbitraryProvider
-com.google.cloud.storage.jqwik.BucketArbitraryProvider
\ No newline at end of file
+com.google.cloud.storage.jqwik.BucketArbitraryProvider
+com.google.cloud.storage.jqwik.ServiceAccountArbitraryProvider