• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 
3 // Copyright 2019 The 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 #endregion
18 
19 using System;
20 using System.Collections.Generic;
21 using System.Net.Sockets;
22 using System.Linq;
23 using System.Threading;
24 using System.Threading.Tasks;
25 using Grpc.Core;
26 using Grpc.Core.Logging;
27 using Grpc.Core.Utils;
28 using Grpc.Core.Internal;
29 using Grpc.Testing;
30 using NUnit.Framework;
31 
32 namespace Grpc.IntegrationTesting
33 {
34     /// <summary>
35     /// See https://github.com/grpc/grpc/issues/18074, this test is meant to
36     /// try to trigger the described bug.
37     /// Runs interop tests in-process, with that client using a target
38     /// name that using a target name that triggers interaction with
39     /// external DNS servers (even though it resolves to the in-proc server).
40     /// </summary>
41     public class ExternalDnsWithTracingClientServerTest
42     {
43         Server server;
44         Channel channel;
45         TestService.TestServiceClient client;
46 
47         [OneTimeSetUp]
Init()48         public void Init()
49         {
50             // We only care about running this test on Windows (see #18074)
51             // TODO(jtattermusch): We could run it on Linux and Mac as well,
52             // but there are two issues.
53             // 1. Due to https://github.com/grpc/grpc/issues/14963, setting the
54             // enviroment variables actually has no effect on CoreCLR.
55             // 2. On mono the test with enabled tracing sometimes times out
56             // due to suspected mono-related issue on shutdown
57             // See https://github.com/grpc/grpc/issues/18126
58             if (PlatformApis.IsWindows)
59             {
60                 Environment.SetEnvironmentVariable("GRPC_TRACE", "all");
61                 Environment.SetEnvironmentVariable("GRPC_VERBOSITY", "DEBUG");
62                 var newLogger = new SocketUsingLogger(GrpcEnvironment.Logger);
63                 GrpcEnvironment.SetLogger(newLogger);
64             }
65             // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755
66             server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
67             {
68                 Services = { TestService.BindService(new TestServiceImpl()) },
69                 Ports = { { "[::1]", ServerPort.PickUnused, ServerCredentials.Insecure } },
70                 // reduce the number of request call tokens to
71                 // avoid flooding the logs with token-related messages
72                 RequestCallTokensPerCompletionQueue = 3,
73             };
74             server.Start();
75             int port = server.Ports.Single().BoundPort;
76             channel = new Channel("loopback6.unittest.grpc.io", port, ChannelCredentials.Insecure);
77             client = new TestService.TestServiceClient(channel);
78         }
79 
80         [OneTimeTearDown]
Cleanup()81         public void Cleanup()
82         {
83             channel.ShutdownAsync().Wait();
84             server.ShutdownAsync().Wait();
85         }
86 
87         [Test]
EmptyUnary()88         public void EmptyUnary()
89         {
90             InteropClient.RunEmptyUnary(client);
91         }
92     }
93 
94     /// <summary>
95     /// Logger which does some socket operation after delegating
96     /// actual logging to its delegate logger. The main goal is to
97     /// reset the current thread's WSA error status.
98     /// The only reason for the delegateLogger is to continue
99     /// to have this test display debug logs.
100     /// </summary>
101     internal sealed class SocketUsingLogger : ILogger
102     {
103         private ILogger delegateLogger;
104 
SocketUsingLogger(ILogger delegateLogger)105         public SocketUsingLogger(ILogger delegateLogger) {
106             this.delegateLogger = delegateLogger;
107         }
108 
Debug(string message)109         public void Debug(string message)
110         {
111             MyLog(() => delegateLogger.Debug(message));
112         }
113 
Debug(string format, params object[] formatArgs)114         public void Debug(string format, params object[] formatArgs)
115         {
116             MyLog(() => delegateLogger.Debug(format, formatArgs));
117         }
118 
Error(string message)119         public void Error(string message)
120         {
121             MyLog(() => delegateLogger.Error(message));
122         }
123 
Error(Exception exception, string message)124         public void Error(Exception exception, string message)
125         {
126             MyLog(() => delegateLogger.Error(exception, message));
127         }
128 
Error(string format, params object[] formatArgs)129         public void Error(string format, params object[] formatArgs)
130         {
131             MyLog(() => delegateLogger.Error(format, formatArgs));
132         }
133 
ForType()134         public ILogger ForType<T>()
135         {
136             return this;
137         }
138 
Info(string message)139         public void Info(string message)
140         {
141             MyLog(() => delegateLogger.Info(message));
142         }
143 
Info(string format, params object[] formatArgs)144         public void Info(string format, params object[] formatArgs)
145         {
146             MyLog(() => delegateLogger.Info(format, formatArgs));
147         }
148 
Warning(string message)149         public void Warning(string message)
150         {
151             MyLog(() => delegateLogger.Warning(message));
152         }
153 
Warning(Exception exception, string message)154         public void Warning(Exception exception, string message)
155         {
156             MyLog(() => delegateLogger.Warning(exception, message));
157         }
158 
Warning(string format, params object[] formatArgs)159         public void Warning(string format, params object[] formatArgs)
160         {
161             MyLog(() => delegateLogger.Warning(format, formatArgs));
162         }
163 
MyLog(Action delegateLog)164         private void MyLog(Action delegateLog)
165         {
166           delegateLog();
167           // Create and close a socket, just in order to affect
168           // the WSA (on Windows) error status of the current thread.
169           Socket s = new Socket(AddressFamily.InterNetwork,
170                                 SocketType.Stream,
171                                 ProtocolType.Tcp);
172 
173           s.Dispose();
174         }
175     }
176 }
177