1 //
2 //
3 // Copyright 2023 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 #include "src/cpp/ext/gcp/environment_autodetect.h"
20
21 #include <grpc/grpc.h>
22
23 #include <string>
24 #include <thread> // NOLINT
25 #include <vector>
26
27 #include "absl/strings/string_view.h"
28 #include "absl/synchronization/notification.h"
29 #include "gmock/gmock.h"
30 #include "gtest/gtest.h"
31 #include "src/core/util/env.h"
32 #include "src/core/util/notification.h"
33 #include "test/core/test_util/test_config.h"
34
35 namespace grpc {
36 namespace testing {
37
38 namespace {
39
40 class EnvironmentAutoDetectTest : public ::testing::Test {
41 protected:
GetNotifiedOnEnvironmentDetection(grpc::internal::EnvironmentAutoDetect * env,grpc_core::Notification * notify)42 void GetNotifiedOnEnvironmentDetection(
43 grpc::internal::EnvironmentAutoDetect* env,
44 grpc_core::Notification* notify) {
45 env->NotifyOnDone([notify]() { notify->Notify(); });
46 }
47 };
48
49 // TODO(yashykt): We could create a mock MetadataServer to test this more end to
50 // end, but given that that should be covered by our integration testing so
51 // deferring to that.
52
TEST_F(EnvironmentAutoDetectTest,Basic)53 TEST_F(EnvironmentAutoDetectTest, Basic) {
54 grpc::internal::EnvironmentAutoDetect env("project");
55
56 grpc_core::Notification notify;
57 GetNotifiedOnEnvironmentDetection(&env, ¬ify);
58 notify.WaitForNotification();
59
60 // Unless we test in a specific GCP resource, we should get "global" here.
61 // EXPECT_EQ(env.resource()->resource_type, "global");
62 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
63 }
64
TEST_F(EnvironmentAutoDetectTest,GkeEnvironment)65 TEST_F(EnvironmentAutoDetectTest, GkeEnvironment) {
66 grpc_core::SetEnv("KUBERNETES_SERVICE_HOST", "k8s_service_host");
67 grpc::internal::EnvironmentAutoDetect env("project");
68
69 grpc_core::Notification notify;
70 GetNotifiedOnEnvironmentDetection(&env, ¬ify);
71 notify.WaitForNotification();
72
73 EXPECT_EQ(env.resource()->resource_type, "k8s_container");
74 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
75 grpc_core::UnsetEnv("KUBERNETES_SERVICE_HOST");
76 }
77
TEST_F(EnvironmentAutoDetectTest,CloudFunctions)78 TEST_F(EnvironmentAutoDetectTest, CloudFunctions) {
79 grpc_core::SetEnv("FUNCTION_NAME", "function_name");
80 grpc::internal::EnvironmentAutoDetect env("project");
81
82 grpc_core::Notification notify;
83 GetNotifiedOnEnvironmentDetection(&env, ¬ify);
84 notify.WaitForNotification();
85
86 EXPECT_EQ(env.resource()->resource_type, "cloud_function");
87 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
88 grpc_core::UnsetEnv("FUNCTION_NAME");
89 }
90
TEST_F(EnvironmentAutoDetectTest,CloudRun)91 TEST_F(EnvironmentAutoDetectTest, CloudRun) {
92 grpc_core::SetEnv("K_CONFIGURATION", "config");
93 grpc::internal::EnvironmentAutoDetect env("project");
94
95 grpc_core::Notification notify;
96 GetNotifiedOnEnvironmentDetection(&env, ¬ify);
97 notify.WaitForNotification();
98
99 EXPECT_EQ(env.resource()->resource_type, "cloud_run_revision");
100 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
101 grpc_core::UnsetEnv("K_CONFIGURATION");
102 }
103
TEST_F(EnvironmentAutoDetectTest,AppEngine)104 TEST_F(EnvironmentAutoDetectTest, AppEngine) {
105 grpc_core::SetEnv("K_CONFIGURATION", "config");
106 grpc::internal::EnvironmentAutoDetect env("project");
107
108 grpc_core::Notification notify;
109 GetNotifiedOnEnvironmentDetection(&env, ¬ify);
110 notify.WaitForNotification();
111
112 EXPECT_EQ(env.resource()->resource_type, "cloud_run_revision");
113 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
114 grpc_core::UnsetEnv("K_CONFIGURATION");
115 }
116
TEST_F(EnvironmentAutoDetectTest,MultipleNotifyWaiters)117 TEST_F(EnvironmentAutoDetectTest, MultipleNotifyWaiters) {
118 grpc::internal::EnvironmentAutoDetect env("project");
119
120 grpc_core::Notification notify[10];
121 for (int i = 0; i < 10; ++i) {
122 GetNotifiedOnEnvironmentDetection(&env, ¬ify[i]);
123 }
124 for (int i = 0; i < 10; ++i) {
125 notify[i].WaitForNotification();
126 }
127
128 // Unless we test in a specific GCP resource, we should get "global" here.
129 // EXPECT_EQ(env.resource()->resource_type, "global");
130 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
131 }
132
133 } // namespace
134
135 } // namespace testing
136 } // namespace grpc
137
main(int argc,char ** argv)138 int main(int argc, char** argv) {
139 grpc::testing::TestEnvironment env(&argc, argv);
140 ::testing::InitGoogleTest(&argc, argv);
141 grpc_init();
142 int ret_val = RUN_ALL_TESTS();
143 grpc_shutdown();
144 return ret_val;
145 }
146