1515#include " google/cloud/internal/oauth2_impersonate_service_account_credentials.h"
1616#include " google/cloud/testing_util/status_matchers.h"
1717#include < gmock/gmock.h>
18+ #include < nlohmann/json.hpp>
1819#include < memory>
1920
2021namespace google {
@@ -30,8 +31,83 @@ using ::google::cloud::testing_util::IsOkAndHolds;
3031using ::google::cloud::testing_util::StatusIs;
3132using ::std::chrono::minutes;
3233using ::std::chrono::seconds;
34+ using ::testing::AllOf;
35+ using ::testing::ElementsAre;
36+ using ::testing::HasSubstr;
37+ using ::testing::Optional;
3338using ::testing::Return;
3439
40+ auto constexpr kFullValidConfig = R"""( {
41+ "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/[email protected] :generateAccessToken", 42+ "delegates": [
43+ 44+ 45+ ],
46+ "quota_project_id": "my-project",
47+ "source_credentials": {
48+ "type": "authorized_user"
49+ },
50+ "type": "impersonated_service_account"
51+ })""" ;
52+
53+ TEST (ParseImpersonatedServiceAccountCredentials, Success) {
54+ auto actual =
55+ ParseImpersonatedServiceAccountCredentials (kFullValidConfig , " test-data" );
56+ ASSERT_STATUS_OK (actual);
57+ EXPECT_EQ (actual->
service_account ,
" [email protected] " );
58+ EXPECT_THAT (actual->delegates ,
59+ 60+ 61+ EXPECT_THAT (actual->quota_project_id , Optional<std::string>(" my-project" ));
62+ EXPECT_THAT (actual->source_credentials ,
63+ AllOf (HasSubstr (" type" ), HasSubstr (" authorized_user" )));
64+ }
65+
66+ TEST (ParseImpersonatedServiceAccountCredentials, MissingRequiredFieldsError) {
67+ for (auto const & required_field :
68+ {" service_account_impersonation_url" , " source_credentials" }) {
69+ auto json = nlohmann::json::parse (kFullValidConfig );
70+ json.erase (required_field);
71+ auto actual = ParseImpersonatedServiceAccountCredentials (json.dump (), " " );
72+ EXPECT_THAT (actual, StatusIs (StatusCode::kInvalidArgument ,
73+ AllOf (HasSubstr (" Missing" ),
74+ HasSubstr (required_field))));
75+ }
76+ }
77+
78+ TEST (ParseImpersonatedServiceAccountCredentials, MissingOptionalFieldsIsOk) {
79+ for (auto const & optional_field : {" delegates" , " quota_project_id" }) {
80+ auto json = nlohmann::json::parse (kFullValidConfig );
81+ json.erase (optional_field);
82+ auto actual = ParseImpersonatedServiceAccountCredentials (json.dump (), " " );
83+ EXPECT_STATUS_OK (actual);
84+ }
85+ }
86+
87+ TEST (ParseImpersonatedServiceAccountCredentials, MalformedServiceAccountPath) {
88+ auto json = nlohmann::json::parse (kFullValidConfig );
89+ json[" service_account_impersonation_url" ] = " not-a-valid-url-path" ;
90+ auto actual = ParseImpersonatedServiceAccountCredentials (json.dump (), " " );
91+ EXPECT_THAT (actual,
92+ StatusIs (StatusCode::kInvalidArgument ,
93+ AllOf (HasSubstr (" Malformed" ),
94+ HasSubstr (" service_account_impersonation_url" ),
95+ HasSubstr (" contents" ))));
96+ }
97+
98+ TEST (ParseImpersonatedServiceAccountCredentials, MalformedJsonFields) {
99+ for (auto const & non_int_field :
100+ {" service_account_impersonation_url" , " delegates" , " quota_project_id" ,
101+ " source_credentials" }) {
102+ auto json = nlohmann::json::parse (kFullValidConfig );
103+ json[non_int_field] = 0 ; // Provide an unexpected JSON type
104+ auto actual = ParseImpersonatedServiceAccountCredentials (json.dump (), " " );
105+ EXPECT_THAT (actual, StatusIs (StatusCode::kInvalidArgument ,
106+ AllOf (HasSubstr (" Malformed" ),
107+ HasSubstr (non_int_field))));
108+ }
109+ }
110+
35111class MockMinimalIamCredentialsRest : public MinimalIamCredentialsRest {
36112 public:
37113 MOCK_METHOD (StatusOr<google::cloud::AccessToken>, GenerateAccessToken,
0 commit comments