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 <string>
22 #include <thread> // NOLINT
23 #include <vector>
24
25 #include "absl/strings/string_view.h"
26 #include "absl/synchronization/notification.h"
27 #include "gmock/gmock.h"
28 #include "gtest/gtest.h"
29
30 #include <grpc/grpc.h>
31
32 #include "src/core/lib/gprpp/env.h"
33 #include "src/core/lib/gprpp/notification.h"
34 #include "test/core/util/test_config.h"
35
36 namespace grpc {
37 namespace testing {
38
39 namespace {
40
41 class EnvironmentAutoDetectTest : public ::testing::Test {
42 protected:
GetNotifiedOnEnvironmentDetection(grpc::internal::EnvironmentAutoDetect * env,grpc_core::Notification * notify)43 void GetNotifiedOnEnvironmentDetection(
44 grpc::internal::EnvironmentAutoDetect* env,
45 grpc_core::Notification* notify) {
46 env->NotifyOnDone([notify]() { notify->Notify(); });
47 }
48 };
49
50 // TODO(yashykt): We could create a mock MetadataServer to test this more end to
51 // end, but given that that should be covered by our integration testing so
52 // deferring to that.
53
TEST_F(EnvironmentAutoDetectTest,Basic)54 TEST_F(EnvironmentAutoDetectTest, Basic) {
55 grpc::internal::EnvironmentAutoDetect env("project");
56
57 grpc_core::Notification notify;
58 GetNotifiedOnEnvironmentDetection(&env, ¬ify);
59 notify.WaitForNotification();
60
61 // Unless we test in a specific GCP resource, we should get "global" here.
62 // EXPECT_EQ(env.resource()->resource_type, "global");
63 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
64 }
65
TEST_F(EnvironmentAutoDetectTest,GkeEnvironment)66 TEST_F(EnvironmentAutoDetectTest, GkeEnvironment) {
67 grpc_core::SetEnv("KUBERNETES_SERVICE_HOST", "k8s_service_host");
68 grpc::internal::EnvironmentAutoDetect env("project");
69
70 grpc_core::Notification notify;
71 GetNotifiedOnEnvironmentDetection(&env, ¬ify);
72 notify.WaitForNotification();
73
74 EXPECT_EQ(env.resource()->resource_type, "k8s_container");
75 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
76 grpc_core::UnsetEnv("KUBERNETES_SERVICE_HOST");
77 }
78
TEST_F(EnvironmentAutoDetectTest,CloudFunctions)79 TEST_F(EnvironmentAutoDetectTest, CloudFunctions) {
80 grpc_core::SetEnv("FUNCTION_NAME", "function_name");
81 grpc::internal::EnvironmentAutoDetect env("project");
82
83 grpc_core::Notification notify;
84 GetNotifiedOnEnvironmentDetection(&env, ¬ify);
85 notify.WaitForNotification();
86
87 EXPECT_EQ(env.resource()->resource_type, "cloud_function");
88 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
89 grpc_core::UnsetEnv("FUNCTION_NAME");
90 }
91
TEST_F(EnvironmentAutoDetectTest,CloudRun)92 TEST_F(EnvironmentAutoDetectTest, CloudRun) {
93 grpc_core::SetEnv("K_CONFIGURATION", "config");
94 grpc::internal::EnvironmentAutoDetect env("project");
95
96 grpc_core::Notification notify;
97 GetNotifiedOnEnvironmentDetection(&env, ¬ify);
98 notify.WaitForNotification();
99
100 EXPECT_EQ(env.resource()->resource_type, "cloud_run_revision");
101 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
102 grpc_core::UnsetEnv("K_CONFIGURATION");
103 }
104
TEST_F(EnvironmentAutoDetectTest,AppEngine)105 TEST_F(EnvironmentAutoDetectTest, AppEngine) {
106 grpc_core::SetEnv("K_CONFIGURATION", "config");
107 grpc::internal::EnvironmentAutoDetect env("project");
108
109 grpc_core::Notification notify;
110 GetNotifiedOnEnvironmentDetection(&env, ¬ify);
111 notify.WaitForNotification();
112
113 EXPECT_EQ(env.resource()->resource_type, "cloud_run_revision");
114 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
115 grpc_core::UnsetEnv("K_CONFIGURATION");
116 }
117
TEST_F(EnvironmentAutoDetectTest,MultipleNotifyWaiters)118 TEST_F(EnvironmentAutoDetectTest, MultipleNotifyWaiters) {
119 grpc::internal::EnvironmentAutoDetect env("project");
120
121 grpc_core::Notification notify[10];
122 for (int i = 0; i < 10; ++i) {
123 GetNotifiedOnEnvironmentDetection(&env, ¬ify[i]);
124 }
125 for (int i = 0; i < 10; ++i) {
126 notify[i].WaitForNotification();
127 }
128
129 // Unless we test in a specific GCP resource, we should get "global" here.
130 // EXPECT_EQ(env.resource()->resource_type, "global");
131 EXPECT_EQ((env.resource()->labels).at("project_id"), "project");
132 }
133
134 } // namespace
135
136 } // namespace testing
137 } // namespace grpc
138
main(int argc,char ** argv)139 int main(int argc, char** argv) {
140 grpc::testing::TestEnvironment env(&argc, argv);
141 ::testing::InitGoogleTest(&argc, argv);
142 grpc_init();
143 int ret_val = RUN_ALL_TESTS();
144 grpc_shutdown();
145 return ret_val;
146 }
147